Laboratoires Docker + scanner défensif pour la RCE de fastjson par chargement de classe à distance. fastjson 1.2.66-1.2.83 : sonde de ressource @JSONType (CVE-2026-16723). fastjson2 2.0.57 : le @type de l'attaquant atteint loadClass avec autoType DÉSACTIVÉ via les types polymorphes (@JSONType(seeAlso) / Jackson @JsonSubTypes). Payloads de marqueur uniquement ; contrôles safeMode + JDK17.
@JSONType de FastjsonCe dépôt conserve désormais deux axes de recherche Fastjson distincts :
modern-fd/ est la reconstruction recommandée, à base de marqueurs uniquement, de la chaîne remote-JAR/file-descriptor en un seul corps de Fastjson 1.2.83 sur Spring Boot 3, Tomcat embarqué standard et JDK 17. Elle utilise le point de chute littéral à DTO fixe JSON.parseObject(body, BoundEnvelope.class) avec AutoType désactivé.scanner/ contient la détection passive de requêtes/journaux, l'inventaire statique d'artefacts et une sonde de joignabilité sans exécution.Le bug :
ParserConfig.checkAutoTypesonde chaque valeur@typeà la recherche de l'annotation@JSONTypeen exécutantgetResourceAsStream(typeName.replace('.','/') + ".class"). Sur les combinaisons Linux/JDK modernes, une sonde distantejar:httppeut laisser le JAR en cache derrière un descripteur ouvert ; des sondes ultérieuresjar:file:/proc/self/fd/Ndans le même corps peuvent le rouvrir sous des noms de classe valides et initialiser une classe annotée. La composition exacte 1.2.83 fonctionne avec AutoType désactivé et via un DTO fixe contenantList<Object>. La liaison (binding) seule n'est donc pas une mesure d'atténuation. Explication complète :docs/MECHANISM.md.
La revue associée de l'ensemble du projet a couvert 2 041 lignes callables/initialiseurs statiques dans les 193 fichiers Java de production de Fastjson 1.2.83. Le tableau ci-dessous hiérarchise les résultats au plus fort impact ; il n'affirme pas que chaque déploiement Fastjson est concerné. Ce dépôt reproduit directement F105. Les autres entrées résument une revue de code source scellée séparément et des preuves de laboratoire limitées.
| Priorité | Constat | Résultat prouvé | Limite importante |
|---|---|---|---|
| 1 | F105 — exécution de bytecode distante @JSONType | Initialisation de classe fournie par l'attaquant via des chargeurs Spring Boot compatibles, notamment la voie directe JDK 8 et la continuation JAR retenu /proc/self/fd/N sous Linux/JDK 17 | Nécessite un porteur @type atteignable par le parseur, un chargeur Boot/TCCL compatible, une sortie réseau, SafeMode/IgnoreAutoType désactivés et un JAR attaquant exact. La voie moderne à DTO fixe exige en outre une voie de valeurs génériques (le laboratoire utilise List<Object>), le procfs Linux, un descripteur retenu et un alignement exact des noms ; elle n'est pas universelle pour chaque JDK, chargeur ou OS |
| 2 | F1/F45 — exécution de commande TemplatesImpl | Exécution de commande marqueur via l'API à DTO fixe, y compris une propriété de corps ignorée | Nécessite une politique serveur affaiblie : admission de classe, AutoType et population de champs privés ou chemins équivalents ; des réglages par défaut intacts la bloquent |
| 3 | F70/C016 — mise en tampon illimitée et expansion GZIP | Les chemins byte/InputStream typés et DTO annotés se développent ou se mettent en tampon sans plafond de sortie ; un OOME Java à tas contraint a été reproduit | La joignabilité du point de terminaison/schéma et des octets de l'attaquant est requise ; une panne étendue à la production n'a pas été établie |
| 4 | F18/C089 — épuisement de la pile du thread du parseur | Des valeurs d'objets ordinaires profondément imbriquées peuvent produire une StackOverflowError avec l'analyse par défaut | Impact sur la disponibilité du thread de requête ; pas un crash JVM systématique ni un crash touchant tout le service |
| 5 | F120/C162 — SSRF HTTP à schéma fixe / chargement de ressources locales | Le JEditorPane/JTextPane.page contrôlé par le corps effectue des requêtes HTTP et peut charger du contenu file: borné dans l'état du Document | Nécessite que l'application déclare le type Swing ; aucune exfiltration automatique de réponse ni RCE n'a été prouvée |
| 6 | F118/C160 — défaillance d'autorisation/intégrité des données par collision de hachage | Une collision Unicode FNV-1a-64 distincte peut se lier à une constante d'enum privilégiée ou router une mutation JSONPath vers le mauvais setter de bean | Nécessite une collision exploitable et une confiance en aval, ou une opération de mutation JSONPath exposée ; pas d'admission de classe ni de RCE |
| 7 | F121/C163 — joignabilité JNDI de JdbcRowSet fixe | Un ordre exact des setters a provoqué une connexion JNDI/LDAP sortante sélectionnée par le corps | Les preuves s'arrêtent à une connexion : aucune réponse d'annuaire, usine d'objets, chargement de bytecode ni RCE |
| 8 | F2/F45 — résolution DNS par défaut | La résolution de nom d'hôte contrôlée par l'attaquant fonctionne avec la configuration par défaut et via une propriété de DTO fixe ignorée | Interaction DNS/OOB uniquement, pas de SSRF HTTP générique ni de RCE |
Voir findings/FINDINGS.md pour les étiquettes de validation, les prérequis, les constats de niveau inférieur, les priorités de remédiation et les limites négatives explicites.
Ce dépôt est destiné à l'éducation, la recherche défensive et les tests autorisés de systèmes que vous possédez ou pour lesquels vous êtes explicitement autorisé à tester. La publication de l'hôte, lorsqu'elle est prise en charge pour le réseau interne du laboratoire moderne, n'est demandée que sur 127.0.0.1 ; ses scripts conduisent le test entièrement à l'intérieur de ce réseau isolé. Le laboratoire moderne ne possède aucune primitive d'exécution de processus et ne pose qu'un marqueur fixe dans la JVM.
Le laboratoire hérité JDK 8 exécute bien id et écrit sa sortie dans /tmp/PWNED ; gardez-le isolé. Ne pointez pas l'exploit hérité ni la sonde active vers des systèmes non autorisés.
Le répertoire scanner/ fournit quatre outils Python 3 sans dépendance (aucune installation pip).
fjdetect.py — inspecte passivement les corps de requêtes JSON décodés ou les journaux JSON structurés pour y chercher des amorces remote-JAR et des séquences /proc/self/fd ou /dev/fd.fjscan_static.py — inventorie les jars/wars/ears pour la combinaison vulnérable (1.2.83 vérifié par métadonnées et contenu × contenu réel des classes du chargeur Spring Boot). Les versions 1.2.48–1.2.82 portant la sonde et les candidats limités aux métadonnées/noms de fichiers sont signalés séparément pour examen. Conçu pour les passerelles CI (code de sortie 2 sur EXPOSED).fjscan_probe.py — contrôle actif et sûr de joignabilité : envoie le @type vers une canary que vous contrôlez (écouteur intégré ou Burp Collaborator / interactsh) et corrèle le rappel de récupération de ressource. Son écouteur intégré renvoie un 404 vide ; configurez les écouteurs externes de manière équivalente. Un rappel ne prouve ni le chargement de classe ni une RCE.fjpayload.py — génère des corps de récupération de ressources distantes pour les tests manuels ; n'utilisez qu'un écouteur vide/404 lorsque l'exécution n'est pas voulue.# 1) passive request/log inspection
python3 scanner/fjdetect.py --ndjson gateway.jsonl
# 2) inventory build artifacts / unpacked images (parallel)
python3 scanner/fjscan_static.py /path/to/artifacts --threads 16