XSSタグの投稿


HTML エスケープなしの出力は怖い
Ktai Style 1.61-rc1に同梱した Photolog テーマは、WordPress のメディアライブラリに登録された画像を探して、投稿一覧に貼り付けるという動作をしています。こういう動作は最近人気があるようで(?)、ひろまささんが wp-kougabu に機能追加したりしています。さきほど見つけたのは「WordPressの最新の記事から画像を一覧表示する」というコードでした。
<?php query_posts('showposts=10'); if ( have_posts() ) : while ( have_posts() ) : the_post(); $files = get_children("post_parent=$id&post_type=attachment&post_mime_type=image"); if (!emptyempty($files)){ $keys = array_keys($files); $num=$keys[0]; $thumb=wp_get_attachment_thumb_url($num); print "<a href=\"".get_permalink()."\" title=\"$post->post_title\"> <img src=\"$thumb\" width=\"80\" height=\"80\" alt=\"$post->post_title\" /></a>\n"; } endwhile;else: endif;?>
しかし、このコードを見てびっくりしました。一切 HTML エスケープがされていないからです!! まあ、表示するのは「サイト運営者が入力した情報」である、投稿のパーマリンクとタイトル、画像の URL だけなので、XSS 脆弱性とは言いにくいですが……。ただし、投稿タイトルとして「大阪 -> 京都のきっぷ」というのがあれば、HTML のパースエラーが発生してしまいます。
さて、先方に連絡しようにも、当該の投稿にはコメントフォームがありません。ウェブサイトを見てもコンタクトフォームも連絡先も見つかりません。最後の手段としてピンバックが動作することを期待して、このエントリーを書いたわけです
素人ならともかく、WordPress のカスタマイズを業務として行なっている方が、こういうコーディングをしてしまうのは不安になってしまいます。HTML エスケープなんて基礎の基礎ですよ!!
さて、改善方法ですが、URL を出すところに WordPress のエスケープ関数である attribute_escape(), clean_url()
を使うのがよいですね。post_title
を出しているところは、API 関数の the_title_attribute()
を使った方がよいでしょう (ただし、事前に global $post;
しておくことが必要)。HTML を組み立てるクォート文字列もシングルクォートにしておけば、HTML 内で使うダブルクォートをバックスラッシュでエスケープしなくて済むので見通しがよくなりますね。
print '<a href="' . clean_url(get_permalink()) . '" title="' . the_title_attribute('echo=0') . '"><img src="' . clean_url($thumb) . '" width="80" height="80" alt="' . the_title_attribute('echo=0') . '" /></a>' . "\n";
WordPress のテクニックをいろいろ公開されるのは素晴しいことですが、こういうセキュリティーの甘いコードを公開するのは困りますね〜〜。せめてツッコミを入れられるようにコメントフォームを開けておいてもらえると助かります。