WordPressのコメント機能を使用していますか?実はWordPressのコメント機能には脆弱性があります。
コメント機能を利用していないサイトだとしても、正しく設定していないと外部からリクエストを送信され攻撃対象になってしまいます。
この記事ではコメント機能の脆弱性の対策方法を解説します。
コメントを外部から送信される脆弱性
WordPressはwp-comments-post.phpにPOST送信することでコメントが送信される仕組みになっています。
通常は投稿ページからコメントを送信する設計なのですが、WordPressの初期機能では外部からのPOST送信の対策がされていません。例えば、以下のようなHTMLが悪意のあるサイトに埋め込まれてたとします。
<script>
const o = {
comment: "攻撃です",
author: "攻撃者",
email: "attack@example.com",
comment_post_ID: 688,
comment_parent: 0
};
const u = "https://blog.zaty.jp/wp-comments-post.php";
const h = {
method: "POST",
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams(o).toString()
};
fetch(u, h);
</script>
このHTMLスクリプトがあるサイトにアクセスすると、この記事に「攻撃です」というコメントが送信されます。このリクエストはそのサイトの訪問者のブラウザ・ネットワークから送信されるため、受信するのは訪問者のIPアドレスです。この攻撃をCSRF攻撃と呼びます。
この送信スクリプトを複数回送信するスクリプトに変更するだけで、DDoS攻撃のような分散された攻撃が可能になってしまいます。
この攻撃はフロントのデザイン上コメント機能を利用していない場合でも、投稿がコメントを受け付ける設定になっている場合は可能です。コメントを利用しない場合は必ずコメントを許可しない設定にするようにしましょう。
外部からのPOST送信をブロックする方法
外部からのPOST送信をブロックするためには、サーバーサイドで「トークン」と呼ぶランダム文字列を発行し、ブラウザのセッションに保存し、POST情報にもトークンを含めるようにします。
セッションに保存されているトークンとPOST送信されたトークンを比較し、一致している場合のみコメントを受け付ける仕組みを作成します。
function start_session_conditionally () {
if( is_singlar( 'post' ) && ! session_id() ) { //カスタム投稿の場合は配列で追記できます。
session_start();
}
}
add_filter( 'template_redirect', 'start_session_conditionally' );
function add_nonce_comment_form ( $fields ) {
$csrf_token = bin2hex( random_bytes(32) );
$_SESSION['csrf_token'] = $csrf_token;
$csrf_field = '<input type="hidden" name="_csrf_token" value="'. $csrf_token .'">';
$fields['comment'] = $csrf_field . $fields['comment'];
return $fields;
}
add_filter( 'comment_form_fields', 'add_nonce_comment_form' );
function verify_comment_nonce () {
if ( ! session_id() ) {
session_start();
}
if ( ! isset( $_POST['_csrf_token'] )
|| ! isset( $_SESSION['csrf_token'] )
|| $_POST['_csrf_token'] !== $_SESSION['csrf_token'] ) {
wp_die( '不正なコメント投稿が検出されました。', '不正なコメント投稿', array( 'response' => 403 ) );
}
}
add_action( 'pre_comment_on_post', 'verify_comment_nonce' );
- セッションの開始
- コメントフォームにCSRFトークンを発行
- コメント投稿時にトークン認証
3つの処理をアクションフック・フィルターフックを使用して実装しています。
この処理で外部からのコメント送信を防ぐことができます。
悪意のあるスクリプトを埋め込まれてしまう
HTML上に<script></script>
のようなスクリプトタグを入力することで、ブラウザ上でJavaScriptプログラムを記述することができます。悪意のある訪問者が、このようなコメントが入力しサイト運営者の意図しないプログラムを動かす攻撃をXSS(クロスサイトスクリプティング)攻撃と呼びます。
XSS攻撃により、以下のようなことがされてしまう可能性があります。
- ユーザーの情報やセッション情報などを盗む
- 偽のサイトに移動させる
- 他のサイトにスクリプトを送信する
特に管理画面のコメント確認部分がXSS対策されていない場合、自身のログイン情報のみならず、ユーザーの情報も流出する可能性もあります。
ログイン状態で投稿したコメントはscriptタグが除去されない設定になっています。これはXSS攻撃の可能性があるので対策しておきます。
XSS対策
WordPressではスクリプトタグなどのHTMLタグを除去するエスケープ関数 wp_kses_post()
が用意されています。これを使用し、XSS攻撃の原因になりうるHTMLを除去します。
function escape_comment_script ( $comment_content, $comment = null ) {
if ( $comment !== null && get_comment_type( $comment ) === 'comment' ) {
$comment_content = wp_kses_post( $comment_content );
}
return $comment_content;
}
add_filter( 'comment_text', 'escape_comment_script', 9, 2 );
wp_kses関数を利用することで、許可するHTMLタグを指定することも可能です。
function escape_comment_script ( $comment_content, $comment = null ) {
if ( $comment !== null && get_comment_type( $comment ) === 'comment' ) {
$allowed_post_tags = array(
'p' => array(),
'br' => array(),
'a' => array( 'href' => true ),
'b' => array(),
'code' => array()
);
$comment_content = wp_kses( $comment_content, $allowed_post_tags );
}
return $comment_content;
}
add_filter( 'comment_text', 'escape_comment_script', 9, 2 );
コメント機能を使用していないサイトの場合
コメント機能を使用していない場合は、管理画面の「設定」→「ディスカッション」→「デフォルトの投稿設定」→「新しい投稿へのコメントを許可」のチェックボックスをオフにする必要があります。
ただし、この設定は既に投稿済みの投稿には適用されません。以下の手順で全ての投稿を変更することが可能です。
- 投稿一覧
- 全てをチェック
- 一括操作を編集に変更
- 適用ボタンをクリック
- コメント部分を「許可しない」に変更
- 更新
ただしこの場合、その投稿の更新日時が全て今日の日時に変更されてしまいます。そこでアクションフックを使用することで、投稿を更新しないまま、コメント投稿全体をブロックすることが可能です。
functions.phpに以下のコードを記述します。
function block_submit_comment () {
wp_die( 'コメントを受け付けていません。', 'コメント受付禁止', array( 'response' => 403 ) );
}
add_action( 'pre_comment_on_post', 'block_submit_comment' );
まとめ
今回はWordPressのコメント機能の脆弱性とその対策方法を解説しました。
今やWordPressはブログサイトのみならずサイトコンテンツの一部として活用することも多いです。その場合コメント機能は必ずOFFにしておくか、脆弱性部分を対策しておくようにしましょう。