WordPressがデフォルトで設定する 「admin」のアカウントのパスワードを辞書を使用して見つけようとする大規模無差別攻撃が行われていました。
つまり特定のアカウントで何回もパスワードを変更してログインを試みると言う事です。
最近はチェックしてなかったので忘れていたら、大量ブルートフォースアタックが来ましたのでどんなログインを試みているかを調べてみました。
検証コード
/* * brute force attack check_mail * どんなログインを試みているかを調べてメールを送る * * License: GPLv2 or later */ function nendebcom_bfa_user_check_mail() { $admin_email = '自分のメールアドレス'; $subject = 'ログイン試行'; $ip = $_SERVER[ "REMOTE_ADDR" ]; $message = date_i18n( "Y-m-d H:i:s" ); $message .= "\r\n IP:" . $ip; $message .= "\r\n HOST:" . gethostbyaddr( $ip ); $message .= "\r\n USER_AGENT:" . $_SERVER[ "HTTP_USER_AGENT" ]; $message .= "\r\n REFERER:" . $_SERVER[ "HTTP_REFERER" ]; $message .= "\r\n URL:http://" . $_SERVER[ "HTTP_HOST" ] . $_SERVER[ "REQUEST_URI" ]; $message .= "\r\n REQUEST_METHOD:" . $_SERVER[ "REQUEST_METHOD" ]; $message .= "\r\n QUERY_STRING:" . $_SERVER[ "QUERY_STRING" ]; $message .= "\r\n"; $message .= "\r\n POST"; $message .= "\r\n user_login: " . $_POST[ "log" ]; $message .= "\r\n user_pass: " . $_POST[ "pwd" ]; $message .= "\r\n rememberme: " . $_POST[ "rememberme" ]; $message .= "\r\n redirect_to: " . $_POST[ "redirect_to" ]; $message .= "\r\n testcookie: " . $_POST[ "testcookie" ]; $message .= "\r\n wp-submit: " . $_POST[ "wp-submit" ]; $message .= "\r\n customize-login: " . $_POST[ "customize-login" ]; $message .= "\r\n interim-login: " . $_GET[ "interim-login" ]; $message .= "\r\n"; $message .= "\r\n GET"; $message .= "\r\n user_login: " . $_GET[ "log" ]; $message .= "\r\n user_pass: " . $_GET[ "pwd" ]; $message .= "\r\n rememberme: " . $_GET[ "rememberme" ]; $message .= "\r\n redirect_to: " . $_GET[ "redirect_to" ]; $message .= "\r\n testcookie: " . $_GET[ "testcookie" ]; $message .= "\r\n wp-submit: " . $_GET[ "wp-submit" ]; $message .= "\r\n customize-login: " . $_GET[ "customize-login" ]; $message .= "\r\n interim-login: " . $_POST[ "interim-login" ]; $message .= "\r\n"; $message .= "\r\nREQUEST"; $message .= "\r\n user_login: " . $_REQUEST[ "log" ]; $message .= "\r\n user_pass: " . $_REQUEST[ "pwd" ]; $message .= "\r\n rememberme: " . $_REQUEST[ "rememberme" ]; $message .= "\r\n redirect_to: " . $_REQUEST[ "redirect_to" ]; $message .= "\r\n testcookie: " . $_REQUEST[ "testcookie" ]; $message .= "\r\n wp-submit: " . $_REQUEST[ "wp-submit" ]; $message .= "\r\n customize-login: " . $_REQUEST[ "customize-login" ]; $message .= "\r\n interim-login: " . $_REQUEST[ "interim-login" ]; @wp_mail( $admin_email, $subject, $message ); } add_action( 'login_init', 'nendebcom_bfa_user_check_mail', 9 );
*これを試す場合はメールが一瞬で大量に来て慌てるかもしれませんのでやらないでくださいね。
検証・対策
すると、以下のような事がだいたいわかりました、
- データーは 殆ど POST でデーターをダイレクトに送っている。(たまにGET)
- データーは [log] と [pwd] だけがほとんど。たまに [rememberme] と [redirect_to] に値が 入ってる場合がある。
- USER_AGENT は わりと古いブラウザーので送られている。
- 秒あたり10回くらいでやってきて 30分くらいで終わるのもあれば、3分置きにpassを変更して何日もかけて試行するのもある。
- 毎回IPアドレス(サーバー)を変更して試行するのもある。
4.だと、サイトが遅くなったり 共用サーバーの場合はリソース制限をかけられたりするかもしれません。
5.だと、Login Lockdown系のプラグインはひっかからない可能性があります。
スポンサードリンク
対策コード
このままではパスワードを破られないように複雑なのにしてても 一瞬で大量に来られるとサーバーのリソースが心配です。
できれば ログイン処理(ユーザー名・パスワードの照合)前にやっつけたいと言う事で 「ログインの手順」 に注目しました。
通常は wp-login.php を一度開いてから フォームに入力してログインします。
ログインフォームに予め独自の隠しコードを入れておけば、ダイレクトに来てるかどうかを判別します。
具体的にはログインフォームに wp_create_nonce で隠しコードを入れて、ログイン処理前に wp_verify_nonce でチェックしてNGの場合は中断して403を返すといった簡単なものです。
ついでに 隠し入力エリアを設置して データが入ってるとNGになるようにします。
以下のコードを my-plugin.php に張り付けてください。
/* * brute force attack check * * License: GPLv2 or later */ if ( !function_exists( 'nendebcom_bfa_user_check' ) && !function_exists( 'nendebcom_bfa_user_nonce' ) ) { // brute force attack check function nendebcom_bfa_user_check() { $is_spams = false; //USER_AGENTが取れない場合 $useragent = esc_attr( $_SERVER[ "HTTP_USER_AGENT" ] ); if ( empty( $useragent ) ) $is_spams = true; $user_login = isset( $_POST[ "log" ] ) ? $_POST[ "log" ] : ''; if ( !$user_login ) $user_login = isset( $_GET[ "log" ] ) ? $_GET[ "log" ] : ''; $user_pass = isset( $_POST[ "pwd" ] ) ? $_POST[ "pwd" ] : ''; if ( !$user_pass ) $user_pass = isset( $_GET[ "pwd" ] ) ? $_GET[ "pwd" ] : ''; //Dummy Item CSRF $user_url = isset( $_POST[ "url" ] ) ? $_POST[ "url" ] : ''; if ( !$user_url ) $user_url = isset( $_GET[ "url" ] ) ? $_GET[ "url" ] : ''; if ( $user_url != '' ) $is_spams = true; //nonce $login_nonce = isset( $_POST[ 'login_nonce' ] ) ? $_POST[ 'login_nonce' ] : ''; if ( !$login_nonce ) $login_nonce = isset( $_GET[ 'login_nonce' ] ) ? $_GET[ 'login_nonce' ] : ''; if ( !$is_spams && $user_login && !$login_nonce ) $is_spams = true; if ( !$is_spams && $user_login && !wp_verify_nonce( $login_nonce, 'login_nonce' ) ) $is_spams = true; //wp-submit $wp_submit = isset( $_POST[ 'wp-submit' ] ) ? $_POST[ 'wp-submit' ] : ''; if ( !$wp_submit ) $wp_submit = isset( $_GET[ "wp-submit" ] ) ? $_GET[ "wp-submit" ] : ''; if ( !$is_spams && $user_login && !$wp_submit ) $is_spams = true; if ( $is_spams ) { status_header( 403 ); exit(); } } add_action( 'login_init', 'nendebcom_bfa_user_check', 1 ); // add login form nonce CSRF function nendebcom_bfa_user_nonce() { echo '<input type="hidden" name="login_nonce" value="' . wp_create_nonce( 'login_nonce' ) . '" />'; echo '<p class="form-url" style="display:none"><label>URL</label><input type="text" name="url" id="url" class="input" size="30" /></p>'; } add_action( 'login_form', 'nendebcom_bfa_user_nonce', 10 ); }
*不動産プラグインには この機能が装備されていますので設置する必要はありません。
*対策方法は他にもいろいろありますので、2重、3重にもかけておきましょう。2段階認証、Basic認証 等・・
*あと、何日もかけて試行して来るところや一度に大量にしかけて来るところは、.htaccess で 「deny from ipアドレス」しましょう。
*admin だけでなく administrator ゃ support や ドメイン名(例 nendebとか) とかいろいろ来てますので今後も注意しましょう。
*WordPress のログイン履歴を保存するプラグイン「狂骨」http://dogmap.jp/2013/05/13/crazy-bone/ で監視しましょう。
参考
WordPress 日本語Codex ブルートフォース攻撃
https://wpdocs.osdn.jp/%E3%83%96%E3%83%AB%E3%83%BC%E3%83%88%E3%83%95%E3%82%A9%E3%83%BC%E3%82%B9%E6%94%BB%E6%92%83
WordPress 日本語Codex 関数リファレンス/wp create nonce
http://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_create_nonce
WordPress 日本語Codex 関数リファレンス/wp verify nonce
http://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/wp_verify_nonce
WordPress Codex Plugin API/Action Reference/login form
https://codex.wordpress.org/Plugin_API/Action_Reference/login_form
あとがき。
他には コメントスパムのようにログイン画面を開いて各項目を自動入力し送信して来るのも観測されています。
現在はルートフォースアタックと判定すると無条件に、IPアドレスを、.htaccess で 「deny from ipアドレス」しています。(HTMLソース)
現在 15000件程 IPを拒否していますが こちらの方が やはりサーバーは快適になっています。