WordPressでエスケープ処理が必要な関数と処理方法

この記事は約 9 分で読めます

ワードプレスに限らず、すべての Web アプリケーションには脆弱性が少なからずあります。ワードプレステーマ制作をするのであればエスケープは必須の知識です。

このページでは POCO の制作を通じてわかったエスケープ処理の考え方と具体的な方法についてまとめました。

WordPressのエスケープ処理とは何か

ワードプレスではブラウザを介したデータ入出力の安全性を確保するために、サニタイズ処理とエスケープ処理をそれぞれ定義しています。

  • サニタイズ (sanitize) :入力データをデータベースに保存する前に不必要なコードを取り除く(無害化)する。
  • エスケープ (escape) :ブラウザが予期しない動作(表示崩れや求めていないスクリプトの実行)をしないように、ブラウザに出力する文字やコードを置換(回避)する。

外部リンク:Data Sanitization/Escaping | Theme Developer Handbook | WordPress Developer Resources (ワードプレスが推奨しているサニタイズ処理とエスケープ処理について、英語)

ワードプレスブログの出力は html です。 html の出力に、タグと誤解されそうなカッコ (<, >) やスクリプトが入った場合、ユーザーのブラウザで予期しない動作をする可能性があります。

その結果、表示が崩れるだけでなく、下記に示すような事態が発生する可能性があります。

  • 個人情報が抜き取られる
  • 知らないサイトに勝手に誘導される
  • コンピュータウィルスが入る可能性がある

このような Web アプリケーションを介した攻撃を「クロスサイトスクリプティング」と呼びます。テーマ制作者はワードプレスの推奨するエスケープ処理を実装したうえでユーザーにサービスを提供する責任があります。

エスケープ処理として、例えば “<” をhtml の特殊文字 &lt; に置き換えます。カッコが別の記号列になることで、ブラウザがタグやスクリプトと誤認するリスクを「回避」することができます。

外部リンク:クロスサイトスクリプティング – Wikipedia

エスケープの関数は3つだけ覚えよう

エスケープする関数はいくつかありますが、ワードプレスのテーマ自作で使用するのは以下の3つです。

  • esc_html
  • esc_attr
  • esc_url

この 3 つの関数をどう使い分けるべきか?私はよくわからず混乱しました。

しかし POCO の制作を通じて、以下に示すフローチャートのように判断すればよいという結論に達しました。紹介します。

エスケープ関数の選択フロー

最初の判断は「出力するコードが URL か、それ以外か」です。

パーマリンクやホーム URL などのコードであれば、 esc_url 関数でエスケープ処理をします。出力するコードが URL 以外であれば次の判断に行きます。

2 番目の判断基準は「開始タグ内の属性値かどうか?」です。開始タグの中には “content, description” などの属性値が入ります。この部分を php で生成する場合は esc_attr 関数でエスケープ処理をしてください。

ただし、出力したいコードが URL の場合は esc_url を使うことを説明済みです。例えば a タグの開始タグ内の属性に href 、 img タグの開始タグ内に属性 src などがあります。これらは開始タグ内の属性ですが URL です。 URL に関わるコードについてはとにかく esc_url で統一します。

上記ふたつに該当しないすべての処理は esc_html 関数でエスケープ処理をします。

注意:WordPress Codex によると esc_url, esc_attr, esc_html 以外にもエスケープ関数はあります。しかしテーマ制作という観点では上記の内容を最低限理解すれば、他のエスケープ処理も応用できます。

エスケープが必要な関数一覧

それではどの呼び出しに対してエスケープ処理が必要なのでしょうか?大まかな判断基準はこのように言われています。

  • the_で始まる関数はエスケープ処理済み
  • 上記以外、特に get_ で始まる関数はエスケープ処理の実装が必要

ワードプレスの開発者(既に紹介したエスケープ処理の外部リンク)によると、ほとんどのワードプレス関数(テンプレートタグ)はエスケープ処理がしてあると主張しています。

基本的な考え方としてはそうですが、ワードプレス関数(テンプレートタグ)はたくさんあります。具体的にどの関数がエスケープ処理済みで、どの関数をエスケープ処理すべきか、整理された情報を見つけることができませんでした。

そこで、 PHP Code Sniffer というツールを使って、私が制作したテーマ POCO のソースコード (php) をすべてチェックしました。

動作確認したソフトのバージョン
PHP Code Sniffer: 3.4.1
WordPress Coding Standard (GitHub): 2.0.0

Code Snifferでエスケープ処理のし忘れをチェック

Code Sniffer (+ WordPress Coding Standard) は、ワードプレスのコード規約に沿っていない処理(空白の入れ方が違うだけでもエラーになる)に対して容赦なくエラーや警告を吐き出すツールです。

このツールで 1 ファイル最大約 500 件の指摘(エラーと警告の合計)をいただき、すべてつぶしました。その結果をシェアします。

これでもすべての関数は網羅していないと思われます。しかしブログテーマ制作という観点であれば必要な関数はカバーしているはずです。

注意: Code Sniffer のインストールと使い方については取り上げません。恐れ入りますが他のサイトを参照願います。

エスケープ処理が「不要」な関数

  • bloginfo()
  • bloginfo_rss()
  • the_archive_description()
  • the_archive_title()
  • the_author()
  • the_category()
  • the_content()
  • the_content_feed()
  • the_date()
  • the_ID()
  • the_modified_date()
  • the_permalink()
  • the_permalink_rss()
  • the_post_thumbnail()
  • the_posts_pagination()
  • the_tags()
  • the_title()
  • the_title_attribute()

エスケープ処理が「必要」な関数

  • get_bloginfo()
  • get_category_link()
  • get_lastpostdate()
  • get_permalink()
  • get_stylesheet_uri()
  • get_template_directory_uri()
  • get_the_archive_title()
  • get_the_archive_description()
  • get_the_category()
  • get_the_content()
  • get_the_excerpt()
  • get_the_modified_date()
  • get_the_modified_time()
  • get_the_post_thumbnail_url()
  • get_the_time()
  • get_the_title()
  • get_the_title_rss()
  • home_url()
  • mysql2date()

エスケープ処理が「必要」なはずだがエラーにならなかった関数

以下の関数はルール上エスケープ処理が必要なはずです。しかし Code Sniffer でもエラーが出ませんでした。念のためエスケープ処理の実装をお勧めします。

  • category_description()
  • tag_description()
  • get_the_date()
  • get_the_author()
  • get_the_post_thumbnail()

もしかしたら WordPress Coding Standard で検証(実装)漏れの可能性が高いです。今後のバージョンアップで改善されるかもしれませんが、まずはシェアさせていただきます。

Code Sniffer でエラーが出なかったから OK だと安心せず、ソースコードレビューを必ず実施することをお勧めします。

エスケープ処理をする際の注意点

最後にエスケープ処理を実装する際に気がついた点をシェアします。やみくもにエスケープ処理を実装すると処理が増えて表示速度が遅くなるかもしれないので注意してください。

定数と変数に対してもエスケープする

定数や変数もエスケープ処理が必要

エスケープ処理の原則は、データベースから呼び出した値に対して処理することです。直接文字列をソースコードに書いた部分(ハードコーディング)はエスケープ処理の対象ではありません。

しかし実際には、関数 (API) で取り出した値をさらに処理することがあります(例えば、日時のフォーマットを変えるなど)。その場合は変数にコード(文字列)をキープしていることになります。

何らかの処理後の変数にイレギュラーな記号が混入する恐れもあります。したがって変数にもエスケープ処理が必要になります。

定数も変数の兄弟(値が変えられない変数)なのでエスケープ処理は必要です。

上の図では以下の出力に対してエスケープ処理をしています。

  • get_bloginfo (関数の戻り値、サイト名の文字列)
  • URL_SITE_LOGO_IMAGE (定数、サイトロゴの URL )
  • $image_size (変数、画像サイズのピクセル値)

上記の関数、定数、変数のどれについてもエスケープ処理を省略すると、 Code Sniffer で検査した際にエラーが表示されます。

エスケープ処理は echo 時に実装

echo時にエスケープ処理する

エスケープ処理を実装するタイミングは echo で html 化する直前です。

このページの最初に説明した通り、ブラウザにコードを渡した(出力した)後にクロスサイトスクリプティングが起こります。そのため html になる直前、 echo する関数・変数・定数についてエスケープ処理を実装します。水際対策に相当しますでしょうか?

実際に、 Code Sniffer でも echo 文についてエスケープ処理の有無を判定しているようです。私が使ってみた感覚ではそうでした。

逆に言うと、 echo せずに処理が終わる文字列についてはエスケープ処理が不要ということです。余計な実装を防げますね。

補足ですが、 esc_attr と esc_html の違いが分かる例があるので上図の青文字で示しました。

$date_modified という変数が一行で 2 回出てきます。最初の出力は time タグの開始タグ内の属性なので esc_attr を使っています。 2 回目は開始タグ内の出力ではないので esc_html を使っています。

このように使い分けてみるといいでしょう。

まとめ

エスケープ処理はテーマ制作で最も苦戦した内容のひとつです。少しでもお役にたてれば嬉しいです。

このページの内容をまとめましょう。

  • ワードプレスの関数(テンプレートタグ)のほとんどはエスケープ処理がされているらしいが、関数名 (the_, get_ ) でエスケープ処理を実装するべきかどうか判断すること。
  • URL, 開始タグ内の属性値、それ以外でエスケープ処理関数を区別して使うこと。
  • PHP Code Sniffer と WordPress Coding Standard でエスケープ処理が必要かどうか検査できる。ただしこのツールでも検査漏れが起きる可能性があるのでコードレビューも実施することが望ましい。
  • 関数 (API) だけでなく変数や定数にもエスケープ処理は必要。
  • エスケープ処理を実装するタイミングは echo 文にて。ブラウザに出力する直前に処理をすること。