【WordPress】xmlrpc.phpを無効にする

概要

WordPress3.5以降の場合は、デフォルトでxmlrpc機能が有効であり無効に設定できない。
「xmlrpc.php」に脆弱性があるため修正する。

「xmlrpc.php」の脆弱性

ブラウザからWordPressを表示しなくても、スマートフォン等の外部システムからxml-rpc経由でWordPressサイトに記事を投稿等できる。

  • メールで投稿、編集、削除する
  • ファイルをアップロードする
  • コメントを投稿、編集、削除する
  • ピンバックする(リンク元がリンク先に通知する機能)

xmlrpcを使ったブルートフォースアタックについて

外部システムからの投稿等に使用される「xmlrpc.php」の引数に,を指定すると、リスト型ブルートフォース攻撃が可能。
ログインIDとパスワードをWordPressのxmlrpc.phpに送信すると、その結果でログインの成否がわかる。
通常のブルートフォース攻撃と異なり、単一のリクエストで多数のID、パスワードを試行できる。

影響範囲

  • 管理者権限のユーザID、パスワードが取得される。
  • サイト改竄(攻撃コードの挿入等)される可能性あり。

対策

  • 緊急対応としてはxmlrpc.phpを削除する、パーミッションを変更するという方法もあるが、WordPressをアップデートした時に復活してしまうので除外。
  • .htaccess」を使用して、xmlrpc.php へのアクセスをhttp://0.0.0.0にリダイレクトさせる。
  • ついでに、アクセス不要なファイル(wp-config.php、wp-cron.php)も外部接続禁止にする。
vi .htaccess

<IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteBase /
        RewriteRule ^xmlrpc\.php$ "http\:\/\/0\.0\.0\.0\/" [R=301,L]
        RewriteRule ^index\.php$ - [L]
</IfModule>

<FilesMatch "^(wp-config\.php|wp-cron\.php)">
order allow,deny
deny from all
</FilesMatch>

検証

対策前のアクセスログと対策後のアクセスログを確認する。

対策前

# xmlrpcによるログイン失敗時のログ
接続IP - - [接続日時] "POST /xmlrpc.php HTTP/1.1" 200 441 "-" "curl/7.67.0"

# xmlrpcによるログイン成功時のログ
接続IP - - [接続日時] "POST /xmlrpc.php HTTP/1.1" 200 660 "-" "curl/7.67.0"

curlコマンドでxmlrpcログインを実施するした場合、
コンテンツは403で戻っているが、HTTPステータスコードは200となっている。

  • curlコマンドによるxmlrpcログイン失敗時
HTTP/1.1 200 OK
Date: Sat, 07 Mar 2020 07:00:40 GMT
Server: Apache
Connection: close
Content-Length: 441
Content-Type: text/xml; charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <fault>
    <value>
      <struct>
        <member>
          <name>faultCode</name>
          <value><int>403</int></value>
        </member>
        <member>
          <name>faultString</name>
          <value><string>ユーザー名またはパスワードが正しくありません。</string></value>
        </member>
      </struct>
    </value>
  </fault>
</methodResponse>
  • curlコマンドによるxmlrpcログイン成功時
HTTP/1.1 200 OK
Date: Sat, 07 Mar 2020 07:02:00 GMT
Server: Apache
Connection: close
Content-Length: 660
Content-Type: text/xml; charset=UTF-8

<?xml version="1.0" encoding="UTF-8"?>
<methodResponse>
  <params>
    <param>
      <value>
      <array><data>
  <value><struct>
  <member><name>isAdmin</name><value><boolean>1</boolean></value></member>
  <member><name>url</name><value><string>http://WORDPRESS設置サイト/</string></value></member>
  <member><name>blogid</name><value><string>1</string></value></member>
  <member><name>blogName</name><value><string>ブログのタイトル</string></value></member>
  <member><name>xmlrpc</name><value><string>http://WORDPRESS設置サイト/xmlrpc.php</string></value></member>
</struct></value>
</data></array>
      </value>
    </param>
  </params>
</methodResponse>

対策後

xmlrpc.php接続時のリダイレクト等、設定した動作を確認。

# リダイレクト
接続IP - - [接続日時] "POST /xmlrpc.php HTTP/1.1" 301 223 "-" "curl/7.67.0"

# アクセス禁止
接続IP - - [接続日時] "GET /wp-config.php HTTP/1.1" 403 220 "-" "Mozilla/5.0 (UA)"
接続IP - - [接続日時] "GET /wp-cron.php HTTP/1.1" 403 218 "-" "Mozilla/5.0  (UA)"
  • curlコマンドによるxmlrpcログイン
HTTP/1.1 301 Moved Permanently
Date: Sat, 07 Mar 2020 07:19:02 GMT
Server: Apache
Location: http://0.0.0.0/
Content-Length: 223
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>301 Moved Permanently</title>
</head><body>
<h1>Moved Permanently</h1>
<p>The document has moved <a href="http://0.0.0.0/">here</a>.</p>
</body></html>
  • curlコマンドによるwp-config.php接続
HTTP/1.1 403 Forbidden
Date: Sat, 07 Mar 2020 07:08:57 GMT
Server: Apache
Content-Length: 217
Content-Type: text/html; charset=iso-8859-1

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /xmlrpc.php
on this server.</p>
</body></html>

その他対応

WordPressのバージョン漏洩防止策

rm /wordpress_path/readme.html
rm /wordpress_path/readme-ja.html

ヘッダー出力防止策

WEBサーバのバージョンやPHPのバージョンを非表示にする

SERVER: Apache/2.4.6 (CentOS) PHP/7.3.8

vi /etc/httpd/conf/httpd.conf

ServerTokens Prod
PHPのバージョンを非表示にする

X-POWERED-BY: PHP/7.3.8

vi /etc/php.ini

expose_php = Off
REST API

WordPress4.4からコアに実装された REST API を呼び出すためのコード
稼働中のWordPressのURLに「wp-json/wp/v2/posts/」を含めると、その記事の情報を抜き出せる。

LINK: ; rel="https://api.w.org/"