Skip to content

ねんでぶろぐ

twitter facebook rss
WordPress Fudousan Plugin for Real Estate
  • TopPage >
  • セキュリティ >
  • WordPressブルートフォースアタック対策

WordPressブルートフォースアタック対策

Posted on 2015年1月16日 Update 2015年9月11日 by admin

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 );

admin_login-2[1]
*これを試す場合はメールが一瞬で大量に来て慌てるかもしれませんのでやらないでくださいね。

 

検証・対策

すると、以下のような事がだいたいわかりました、

  1. データーは 殆ど POST でデーターをダイレクトに送っている。(たまにGET)
  2. データーは [log] と [pwd] だけがほとんど。たまに [rememberme] と [redirect_to] に値が 入ってる場合がある。
  3. USER_AGENT は わりと古いブラウザーので送られている。
  4. 秒あたり10回くらいでやってきて 30分くらいで終わるのもあれば、3分置きにpassを変更して何日もかけて試行するのもある。
  5. 毎回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を拒否していますが こちらの方が やはりサーバーは快適になっています。




スポンサードリンク



Posted in セキュリティTagged date_i18n, login_form, login_init, wp_create_nonce, wp_mail, wp_verify_nonce

投稿ナビゲーション

← マイ・プラグインを最後に読み込むようにする
WordPress ユーザー登録やコメントフォームのスパム対策例 →

関連記事

WordPress ブラックリストで登録できないユーザー名を設定する

今まで知らなかったフィルターですが「illegal_user_logins」というアクションフィルターが WordPress4.4 から使えるようになっています。 ユーザー名リストを作ってこのフィルターを使うと、このリストにあるユーザ ...

WordPress ユーザー登録やコメントフォームのスパム対策例

これ書いちゃうと対策されるかもしれませんが、昔からこっそりやってるスパム対策です。 スパムは入力できる項目は、ほぼ全ての項目に何か入れて送ってきます。そこでCSSで隠した項目にデーターが入っていればスパムと判定してerrorを表示するよう ...


スポンサードリンク

カテゴリー

  • WordPress
  • その他
  • セキュリティ
  • テーマ
  • プラグイン

Recent Posts

  • WordPress6.9 をチェックしています
  • WordPress 6.8 をチェックしています
  • WordPress6.7 新デフォルトテーマ Twenty Twenty-Five をチェックしています
  • WordPress6.7 をチェックしています
  • WordPress 6.6 をチェックしています
  • WordPress 6.5 をチェックしています
  • WordPress6.4 を チェックしています
  • WordPress6.4 新デフォルトテーマ Twenty Twenty-Four をチェックしています

タグクラウド

activated_plugin activate_tinymce_for_media_description add_meta_boxes add_options_page add_theme_support admin_body_class admin_email_check_interval admin_enqueue_scripts admin_footer-$hook_suffix admin_head-$hook_suffix admin_init admin_menu admin_notices admin_print_styles-$hook_suffix after_populate_network after_setup_theme after_upgrade_to_multisite allowed_block_types_all appearance-tools appearanceTools apply_filters apply_shortcodes before_populate_network blockEditor.useSetting.before block_categories_all block_core_navigation_listable_blocks block_core_navigation_render_inner_blocks block_core_social_link_get_services block_editor_settings_all bulk_actions-{screen_id} bulk_edit_custom_box bulk_edit_posts comment_form_after_fields compare_key Contact Form 7 custom-spacing customize_register customize_save_after date_i18n default-font-sizes default-spacing-sizes deleted_post_{$post->post_type} delete_post_{$post->post_type} delete_user delete_user_form deprecated_function_trigger_error document_title_parts document_title_separator editor_script_handles editor_style_handles edit_user_profile_update Embed embed_head embed_template embed_thumbnail_image_shape embed_thumbnail_image_size emoji enqueue_block_editor_assets enqueue_empty_block_content_assets fluid Fluid typography Fonts API Footnotes get_category_parents get_currentuserinfo get_file_data get_option get_parent_post get_parent_theme_file_path get_parent_theme_file_uri get_permalink get_query_template get_term_parents_list get_theme_file_path get_theme_file_uri get_the_content get_the_post_thumbnail get_the_title get_users Google APPs Google Fonts Google Maps Gutenberg has_post_parent has_post_thumbnail hooked_block/hooked_block_{$block_type} illegal_user_logins init is_admin_screen is_customize_preview is_post_status_viewable is_post_type_viewable is_singular is_user_logged_in jQuery Lazy-Loading login_footer login_form login_init login_site_html_link Masonry max-image-preview my-plugin new_admin_email_subject paginate_links_output password_hint personal_options personal_options_update phpmailer_init plugins_list plugin_row_meta post_password_expires post_password_required post_search_columns post_states_html post_thumbnail_id post_thumbnail_url pre_comment_on_post pre_get_document_title pre_months_dropdown_query pre_post_insert pre_site_option pre_wp_mail pre_wp_unique_post_slug prime_options prime_options_by_group protected_title_format quick_edit_dropdown_authors_args quick_edit_statuses RECOVERY_MODE_EMAIL registered_post_type_{$post_type} registered_taxonomy_{$taxonomy} register_block_template.unregister_block_template register_form register_post register_sidebar register_{$post_type}_post_type_args register_{$taxonomy}_taxonomy_args registration_errors render_block_core_navigation_link_allowed_post_status render_block_{$this->name} rest_after_insert_attachment safecss_filter_attr sanitize_file_name script_handles script_loader_tag ServerSideRender site_search_columns site_status_autoloaded_options_action_to_perform site_status_autoloaded_options_limit_description site_status_autoloaded_options_size_limit skipBlockSupportAttributes style_handles templateLock template_redirect theme.json the_content the_custom_header_markup the_excerpt_embed the_excerpt_rss the_password_form the_post_navigation Twenty Eleven Twenty Fifteen Twenty Fourteen Twenty Nineteen Twenty Seventeen Twenty Sixteen Twenty Ten Twenty Thirteen Twenty Twelve Twenty Twenty Twenty Twenty-Fiver Twenty Twenty-Four Twenty Twenty-One Twenty Twenty-Three Twenty Twenty-Two TwitterAPI Update URI update_option update_term_count upgrader_source_selection user_profile_update_errors user_search_columns validate_plugin_requirements validate_theme_requirements view_script_handles WordPress4.1 WordPress4.2 WordPress4.3 WordPress4.4 WordPress4.5 WordPress4.6 WordPress4.7 WordPress4.8 WordPress4.9 WordPress5.0 WordPress5.1 WordPress5.2 WordPress5.3 WordPress5.4 WordPress5.5 WordPress5.6 WordPress5.7 WordPress5.8 WordPress5.9 WordPress6.0 WordPress6.1 WordPress6.2 WordPress6.3 WordPress6.4 WordPress6.5 WordPress6.6 WordPress6.7 WordPress6.8 WordPress6.9 wpcf7_form_tag WP Fastest Cache WP Multibyte Patch wp_add_inline_script wp_admin_canonical_url wp_after_insert_post wp_ajax_menu_quick_search_args wp_autoload_values_to_autoload wp_before_include_template wp_body_open wp_cache_get_salted wp_cache_set wp_cache_set_multiple_salted wp_content_img_tag wp_create_nonce wp_date WP_DEBUG_LOG wp_default_autoload_value wp_dequeue_script_module wp_dequeue_style wp_deregister_script_module wp_deregister_style WP_DEVELOPMENT_MODE wp_editor_set_quality wp_enqueue_script wp_enqueue_scripts wp_enqueue_script_module wp_enqueue_style wp_filesystem wp_finalized_template_enhancement_output_buffer wp_footer wp_get_attachment_image wp_get_custom_css wp_get_document_title wp_head WP_HTML_Tag_Processor wp_is_block_template_theme wp_is_block_theme wp_is_rest_endpoint wp_mail wp_mail_embed_args wp_max_autoloaded_option_siz wp_omit_loading_attr_threshold wp_plugin_dependencies_slug wp_print_styles wp_register_script wp_register_script_module wp_replace_insecure_home_url wp_resource_hints wp_script_modules wp_set_options_autoload wp_set_option_autoload wp_should_output_buffer_template_for_enhancement wp_targeted_link_rel wp_template_enhancement_output_buffer wp_template_enhancement_output_buffer_started wp_theme_files_cache_ttl wp_title wp_verify_nonce writingMode XAMPP _wp_render_title_tag {$adjacent}_post_link {$type}_template サイトエディタ フルサイト編集(FSE)
はざくみ イラストブログ

Proudly powered by WordPress | Theme: nendebcom by nendeb. | Privacy Policy