
Security research on Liferay CE 7.0.3 GA4: pre-auth RCE as root (CVE-2020-7961 class) reproduced end-to-end, plus 16 more findings — 8+ with no known CVE. Agentic loop-hunt: 25 generators, 22 judges, 9 live validators on Docker. Evidence trail + one-go checker included.
A security audit of Liferay Portal CE 7.0.3 GA4 (git tag 7.0.3-ga4, commit
b2d7cc68a) performed with the RAPTOR loop-hunt methodology:
deterministic recon → 25 isolated generator agents reading raw source → 22 independent judge
agents refuting from raw → 9 live validators attacking a real GA4 instance in Docker.
Headline: unauthenticated RCE as
rootreproduced end-to-end (CVE-2020-7961 class), plus 8 more live-verified vulnerabilities — several of them with no known CVE.
⚠️ Legal/ethical: everything here targets a self-hosted test instance. Liferay CE 7.0 is end-of-life (last release 7.0.6 GA7, 2018); these issues are unpatched upstream. Use this material only against systems you own or are explicitly authorized to test.
Status: ✅ live-verified against the Docker GA4 instance · 🔬 confirmed-by-code (independent judge re-derived the full trace from raw source) · 🧪 needs/config-gated.
| ID | Finding | Severity | Auth | Status | Evidence |
|---|---|---|---|---|---|
| F-1 | JSONWS type-override → arbitrary class instantiation + setters → RCE as root (c3p0 HexAsciiSerializedMap → ObjectInputStream → AspectJWeaver file-write → JSP) | Critical | none | ✅ | verified/f1-jsonws-deser-rce.md |
| F-2 | /poller/* jabsorb javaClass hint → arbitrary class instantiation + field injection, before userId validation | High (potential) | any account (self-registration default-on) | ✅ sink / RCE arm open | verified/F-2-poller.md |
| F-4 | XML-RPC pingback.ping fetch-before-validate → blind SSRF + internal port oracle (reached Gogo shell on 127.0.0.1:11311) | Medium | none | ✅ | verified/f4-xmlrpc-pingback-ssrf.md |
| F-5 | SyncDownloadServlet versionId IDOR → read any DL file version (cross-site, no VIEW check on the streamed object) | High | none (via guest-viewable "leg") | ✅ | verified/F-5.md |
| F-6 | XSL template engine ignores sandboxing (secureProcessing=false, restricted dropped) → document() SSRF and XSLTC rt:exec command execution | Critical | site template author | ✅ | verified/F-6-F-7-template-engines.md |
| F-7 | Velocity and FreeMarker restricted templates expose raw propsUtil / saxReaderUtil → portal property + file:// disclosure to guests | High | template author | ✅ | verified/F-6-F-7-template-engines.md |
| F-8 | Image_ table IDOR via /image/*?img_id=N — no token, prefix-scoped checks bypassed by prefix swap, sequential ids enumerable | Medium | none | ✅ | verified/f-8-image-idor.md |
| F-11 | SimpleCaptcha = 4-digit PIN, never invalidated on wrong guesses, guest counter never increments → ~5k-request break | Medium | none | ✅ | verified/f11-f12-captcha-reminder.md |
| F-12 | Forgot-password: user enumeration + reminder-answer oracle without captcha (fresh-session bypass); empty answer fires a real reset ticket for query-less accounts | Medium-High | none | ✅ | verified/f11-f12-captcha-reminder.md |
| F-13 | Web Content Display request-param override (groupId/articleId/ddmTemplateKey) → cross-site read of non-guest articles (journal.article.view.permission.check.enabled=false default) | High | none (needs a WCD on a guest page) | ✅ | verified/F-13-wcd-param-override.md |
| F-3 | OSGi axis-extender skips ServiceAccessPolicy / remote-access marking on module SOAP services | Medium (High w/ WSDD module) | none | 🔬 | judge/axis-spring-remoting.md |
| F-9 | OpenID links victim account to attacker's OpenID before assertion verification → account takeover | High | none (OpenID enabled, non-default) | 🔬 🧪 | judge/sso-autologin.md |
| F-10 | TunnelServlet readObject guarded only by a class blacklist; ROME/JdbcRowSetImpl/c3p0/AspectJWeaver gadgets on classpath | Critical potential | trusted peer (shared secret + allowed host) | ✅ barriers hold pre-auth | verified/f10-f20-tunnel-auth-pipeline.md |
| F-14 | TokenAutoLogin trusts a bare SM_USER header (no verification, no IP allowlist) | Medium | none (token SSO enabled, non-default) | 🔬 🧪 | judge/sso-autologin.md |
| F-15 | Site-admin LAR import smuggles RolesAdminPortletDataHandler → mass company-role deletion / permission wipe | Medium | site admin | 🔬 | judge/export-import-lar.md |
| F-16 | OpenSocial (not in default bundle): pre-auth makeRequest SSRF, /gadgets/ifr origin JS, forgeable security tokens → impersonation, stored XSS | High ×4 | none / site member | 🔬 (deployment-conditional) | judge/opensocial-shindig.md |
| F-17 | WSRP (not in default bundle): pre-auth ProxyServlet SSRF; markup endpoint → arbitrary portlet render + layout typeSettings persistence | Medium | none | 🔬 (deployment-conditional) | judge/wsrp.md |
Full curated list with rejections: FINDINGS.md · narrative report: REPORT.md
Catalogue of ~50 known Liferay 7.0.x issues used as prior art: PRIOR-ART.md
(OSV [email protected], NVD sweep, Code White / CERT-EU advisories).