Recherche en sécurité sur Liferay CE 7.0.3 GA4 : RCE pré-authentification en tant que root (classe CVE-2020-7961) reproduite de bout en bout, plus 16 autres découvertes — 8+ sans CVE connu. Chasse en boucle agentique : 25 générateurs, 22 juges, 9 validateurs en direct sur Docker. Piste de preuves + vérificateur en une passe inclus.
Partager
Liferay CE 7.0.3 GA4 — Recherche de vulnérabilités (RAPTOR Loop-Hunt)
Un audit de sécurité de Liferay Portal CE 7.0.3 GA4 (tag git 7.0.3-ga4, commit
b2d7cc68a) réalisé avec la méthodologie RAPTOR loop-hunt :
reconnaissance déterministe → 25 agents générateurs isolés lisant le code source brut → 22 agents juges
indépendants réfutant à partir du code brut → 9 validateurs en conditions réelles attaquant une véritable instance GA4 dans Docker.
Titre : RCE non authentifié en tant que root reproduit de bout en bout (classe CVE-2020-7961),
plus 8 vulnérabilités supplémentaires vérifiées en conditions réelles — plusieurs sans CVE connu.
⚠️ Aspects légaux/éthiques : tout ceci cible une instance de test auto-hébergée. Liferay CE 7.0 est
en fin de vie (dernière version 7.0.6 GA7, 2018) ; ces problèmes ne sont pas corrigés en amont. N'utilisez ce
contenu que contre des systèmes qui vous appartiennent ou pour lesquels vous êtes explicitement autorisé à tester.
Statut : ✅ vérifié en conditions réelles contre l'instance GA4 sous Docker · 🔬 confirmé par le code (un
juge indépendant a redérivé la trace complète du code source brut) · 🧪 nécessite une config / conditionné par la config.
ID
Découverte
Gravité
Authentification
Statut
Preuve
F-1
Surcharge de type JSONWS → instanciation arbitraire de classes + setters → RCE en tant que root (c3p0 HexAsciiSerializedMap → ObjectInputStream → gadget d'écriture de fichier AspectJWeaver → JSP)
Le moteur de templates XSL ignore le sandboxing (secureProcessing=false, restricted supprimé) → SSRF document()et exécution de commandes XSLTC rt:exec
Critique
auteur de template du site
✅
Liste complète organisée avec les rejets : FINDINGS.md · rapport narratif : REPORT.md
Nouveau vs connu — comparaison des CVE
Catalogue d'environ 50 problèmes Liferay 7.0.x connus utilisés comme état de l'art : PRIOR-ART.md
(OSV [email protected], balayage NVD, avis Code White / CERT-EU).
Découverte
CVE connu ?
Relation
F-1 RCE par désérialisation JSONWS
CVE-2020-7961 (CISA KEV, exploité dans la nature)
Reproduction + redérivation indépendante. Non corrigé confirmé dans GA4 ; chaîne complète prouvée avec un gadget d'écriture de fichier AspectJWeaver (les PoC publics utilisent généralement JdbcRowSetImpl JNDI).
F-10 readObject de TunnelServlet
CVE-2020-15842 (correspondance de classe)
Classe connue. Garde de désérialisation par liste noire seule confirmée ; barrières pré-auth vérifiées en conditions réelles (non exploitable sans secret partagé / hôte autorisé).
F-7 fuite propsUtil des templates
CVE-2020-13445 (injection de template, FreeMarker/Velocity)
Variante. Même classe de bug (l'API de templates ne restreint pas les objets sensibles), mécanisme différent : objets PropsImpl/saxReaderUtil bruts exposés dans le contexte restreint.
Défaut non sécurisé connu — confirmé indépendamment en conditions réelles.
F-12 (oracle + ticket de réinitialisation par réponse vide)
aucun trouvé
Nouveau. Contournement du captcha par nouveau JSESSIONID à l'étape 2 ; une answer vide crée un ticket de réinitialisation valide 24 h pour les comptes sans question, sans aucune connaissance du secret.
F-11 Force brute SimpleCaptcha
aucun trouvé (CVE-2019-6588 est un autre problème de captcha — XSS)
Nouveau. PIN à 4 chiffres + aucune invalidation + contournement du compteur d'invités.
F-2 Désérialisation jabsorb du poller
aucun trouvé
Nouveau. Sink confirmé en conditions réelles ; weaponisation bloquée par l'injection de champs LiferaySerializer (recherche ouverte).
F-4 Oracle SSRF pingback
aucun trouvé
Nouveau.
F-5 IDOR versionId sync
aucun trouvé
Nouveau.
F-6 RCE du moteur XSL
aucun trouvé (CVE-2020-13445 ne couvre que FreeMarker/Velocity)
« Nouveau » = aucun CVE correspondant trouvé dans les avis OSV/NVD/Liferay à la date de 2026-07 ; les découvertes n'ont pas
été soumises pour attribution de CVE (la gamme de produits est en fin de vie).
CVE connus confirmés présents dans GA4 mais non re-testés en conditions réelles
CVE-2020-15840 (contournement du filtre d'URL à double encodage), CVE-2024-8980 + CVE-2025-43748
(CSRF → RCE de la console de scripts), CVE-2021-33335 (prise de contrôle d'un admin d'entreprise — GA4 est le plancher de la
plage affectée), CVE-2017-1000425 (XSS flash.jsp), CVE-2021-29040 (erreurs JSONWS verbeuses),
CVE-2022-41414 / CVE-2023-33949 (défauts d'énumération/inscription), CVE-2025-62261 (jetons
de réinitialisation en clair — NVD nomme directement 7.0.3 GA4). Voir PRIOR-ART.md.
Le processus (RAPTOR loop-hunt)
Étape
Ce qui a été exécuté
Sortie
0 — déterministe
audit des dépendances raptor-sca (727 dépendances), 17 règles Semgrep (1 098 ancres), modèle de menaces, manifeste des points d'entrée de web.xml, catalogue de CVE d'état de l'art
25 agents isolés, un par tranche de composant × optique de classe de bug, raisonnant uniquement à partir du code source brut (aucun résumé antérieur — anti-ancrage)
22 agents indépendants réfutant chaque candidat à partir du code brut ; un rejet exige une preuve visible dans le code (« ne supposez pas que la couche invisible est sécurisée »)
Registre : TRIED.md (tout ce qui a été tenté, y compris 3 tranches « dry » documentées) ·
INVENTORY.md (dénominateur de couverture) · environnement/fixtures : ENV.md
Reproduction locale avec Docker
Il n'existe pas d'image officielle liferay/portal:7.0.3-ga4 ; construisez donc à partir du bundle officiel :
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
Ensuite, terminez l'assistant de configuration initiale sur http://localhost:8080/ (base HSQL par défaut ; l'assistant
définit le mot de passe administrateur pour [email protected]).
Exécuter le validateur tout-en-un
tools/liferay_ga4_check.py est un script Python 3 mono-fichier, uniquement basé sur la bibliothèque standard — pointez-le vers
n'importe quelle instance GA4 et il teste chaque découverte vérifiée en conditions réelles :
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
Sortie attendue sur une installation GA4 par défaut : 9 découvertes VULNERABLE
(F-1, F-1+RCE, F-2, F-4, F-5*, F-8, F-11, F-12, F-13*) plus F-10 confirmée non vulnérable
(la barrière du tunnel tient). *F-5 et F-13 nécessitent des paramètres de fixture (--leg-uuid/--version-id,
--wcd-page/--group-id/--article-id) — voir --help.
Le gadget de désérialisation est généré en Python pur dans le script (vérifié octet par octet contre
la charge utile ysoserial AspectJWeaver utilisée lors de l'engagement) — ni Java, ni jars, ni ysoserial nécessaires.
Vérifié solide (pour que vous puissiez calibrer le reste)
Tickets de réinitialisation de mot de passe (UUID 128 bits, à usage unique, 24 h), renouvellement de session lors de la connexion par ticket,
cookie « remember-me » AES-128 avec clé SecureRandom par entreprise, hachage PBKDF2 par défaut,
pile XML à l'échelle du portail (entités externes désactivées par défaut), barrières digest WebDAV/SharePoint,
verrous d'IP localhost /api/axis|/api/liferay|/api/atom, validation des chemins d'upload, garde-fous anti-traversal /combo/sprite,
contrôle omni-admin de la console de scripts et de l'interface web Gogo.
Déclaration de couverture et limites
La couverture a été suivie par composant par rapport à l'inventaire complet (TRIED.md).
Non couvert : l'altitude fonction par fonction sur tout l'arbre de 4 Go (uniquement les ancres Semgrep),
la majeure partie de modules/apps hors foundation/web-experience à l'altitude fichier, la recherche de gadgets F-2,
les tests en conditions réelles hors configuration par défaut (F-9/F-14), et l'atteignabilité des CVE de dépendance de PDFBox 2.0.3.
La boucle a été mise en pause pour la rédaction du rapport, pas parce qu'elle était à sec.
IDOR sur la table Image_ via /image/*?img_id=N — aucun jeton, contrôles limités au préfixe contournés par échange de préfixe, identifiants séquentiels énumérables
Mot de passe oublié : énumération d'utilisateurs + oracle de réponse de rappel sans captcha (contournement par nouvelle session) ; une réponse vide déclenche un véritable ticket de réinitialisation pour les comptes sans question
Écrasement des paramètres de requête du Web Content Display (groupId/articleId/ddmTemplateKey) → lecture intersite d'articles non destinés aux invités (défaut journal.article.view.permission.check.enabled=false)
L'import LAR par un admin de site fait passer en fraude RolesAdminPortletDataHandler → suppression massive de rôles d'entreprise / effacement des permissions
Nouveau. Le moteur XSL était hors de tous les correctifs d'injection de templates antérieurs.
F-8 IDOR Image_
aucun trouvé
Nouveau.
F-13 Lecture intersite WCD
aucun trouvé
Nouveau. Défaut non sécurisé racine (journal.article.view.permission.check.enabled=false) plus un nouveau vecteur de livraison (écrasement des paramètres de requête du portlet).
F-3 Contournement SAP de l'axis-extender
aucun trouvé
Nouveau.
F-9 OpenID lien-avant-vérification
aucun trouvé
Nouveau.
F-14 Confiance dans l'en-tête SM_USER
aucun trouvé
Nouveau.
F-15 Contrebande de data-handler de rôles LAR
aucun trouvé
Nouveau.
F-16 / F-17 OpenSocial / WSRP
aucun trouvé
Nouveau, mais les modules ne sont pas dans le bundle GA4 par défaut (Liferay-Releng-Bundle: false).