Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!
liferay-ga4-rce-research — 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. | Kitploit
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.
Liferay CE 7.0.3 GA4 — Vulnerability Research (RAPTOR Loop-Hunt)
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 root reproduced 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.
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).
Finding
Known CVE?
Relationship
F-1 JSONWS deserialization RCE
CVE-2020-7961 (CISA KEV, exploited in the wild)
Reproduction + independent re-derivation. Confirmed unpatched in GA4; full chain proven with an AspectJWeaver file-write gadget (public PoCs typically use JdbcRowSetImpl JNDI).
F-10 TunnelServlet readObject
CVE-2020-15842 (class match)
Known class. Blacklist-only deserialization guard confirmed; pre-auth barriers verified live (not exploitable without shared secret/allowed host).
Variant. Same bug class (template API fails to restrict sensitive objects), different mechanism: raw PropsImpl/saxReaderUtil objects exposed inside the restricted context.
none found (CVE-2020-13445 covers FreeMarker/Velocity only)
New. The XSL engine was outside every prior template-injection fix.
F-8 Image_ IDOR
none found
New.
"New" = no matching CVE located in OSV/NVD/Liferay advisories as of 2026-07; findings have not been
submitted for CVE assignment (the product line is EOL).
Known CVEs confirmed present in GA4 but not re-tested live
CVE-2020-15840 (double-encoded URL filter bypass), CVE-2024-8980 + CVE-2025-43748
(CSRF → script console RCE), CVE-2021-33335 (company-admin takeover — GA4 is the floor of the
affected range), CVE-2017-1000425 (flash.jsp XSS), CVE-2021-29040 (verbose JSONWS errors),
CVE-2022-41414 / CVE-2023-33949 (enumeration/registration defaults), CVE-2025-62261 (reset
tokens in plaintext — NVD names 7.0.3 GA4 directly). See PRIOR-ART.md.
docker build -t liferay-ga4 .
docker run -d --name liferay-ga4 -p 8080:8080 liferay-ga4
# first boot takes several minutes — wait for it:
until [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:8080/)" = 200 ]; do sleep 10; done
Then complete the one-time setup wizard at http://localhost:8080/ (default HSQL DB; the wizard
sets the admin password for [email protected]).
Run the one-go validator
tools/liferay_ga4_check.py is a single-file, stdlib-only Python 3 script — point it at any
GA4 instance and it tests every live-verified finding:
root@kitploit:~
# passive validation of all findings (safe, no payloads detonated)
python3 tools/liferay_ga4_check.py http://localhost:8080
# with an account (self-registration is on by default) for the poller sink test
python3 tools/liferay_ga4_check.py http://localhost:8080 --user [email protected] --password '***'
# full RCE proof (opt-in): drops a SELF-DELETING JSP via the deserialization file-write
# gadget and fetches the command output; adjust --web-root to your install
python3 tools/liferay_ga4_check.py http://localhost:8080 --rce \
--web-root /opt/liferay/tomcat-8.0.32/webapps/ROOT
Expected output against a default GA4 install: 9 findings VULNERABLE
(F-1, F-1+RCE, F-2, F-4, F-5*, F-8, F-11, F-12, F-13*) plus F-10 confirmed not vulnerable
(tunnel barrier holds). *F-5 and F-13 need fixture parameters (--leg-uuid/--version-id,
--wcd-page/--group-id/--article-id) — see --help.
The deserialization gadget is generated in pure Python inside the script (byte-verified against
the ysoserial AspectJWeaver payload used in the engagement) — no Java, jars, or ysoserial needed.
Verified solid (so you can calibrate the rest)
Password-reset tickets (128-bit UUID, single-use, 24 h), session renewal on ticket login,
remember-me cookie AES-128 with per-company SecureRandom key, default PBKDF2 hashing, the
portal-wide XML stack (external entities disabled by default), WebDAV/SharePoint digest gates,
/api/axis|/api/liferay|/api/atom localhost IP locks, upload path validation, /combo/sprite
traversal guards, omni-admin gating of the script console and Gogo web UI.
Coverage statement & limitations
Coverage was tracked per component against the full inventory (TRIED.md).
Not covered: function-by-function altitude over the whole 4 GB tree (Semgrep anchors only),
most of modules/apps outside foundation/web-experience at file altitude, the F-2 gadget
research, non-default-config live tests (F-9/F-14), and PDFBox 2.0.3 dependency-CVE reachability.
The loop was paused for reporting, not because it ran dry.
Forgot-password: user enumeration + reminder-answer oracle without captcha (fresh-session bypass); empty answer fires a real reset ticket for query-less accounts