PHPでは、変数や関数を使って文字を出力(echo
)する場合、エスケープ処理を行う場合があります。
例えば、「<
」を「<
」、「&
」を「&
」に書き換えたり(HTMLエスケープ)、URL内の日本語文字を「%E6%97%A5%E6%9C%AC%E8%AA%9E
」というように書き換える処理(URLエンコード)などです。
WordPressでは、文字を適切に表示するためのエスケープ関数が用意されています。
また、セキュリティ上のリスクが高いHTMLタグやURLを処理してくれる関数もあります。
一箇所のエスケープし忘れがセキュリティ上では命取りになり兼ねないので、変数をecho
する場合には常に適切なエスケープ処理を行いましょう。
通常のテキストのエスケープ
HTMLタグを含まないテキストや、HTMLタグ自体をそのままテキストとして表示する場合には、WordPress関数のesc_html関数
を使用します。
この関数は、「<>&"'
」の各文字を実体参照形式に変換します。
1 2 3 4 |
<?php $str = '<a href="index.html">リンク</a>'; echo esc_html( $str ); ?> |
出力結果
1 |
<a href="index.html">リンク</a> |
変数や、関数の返り値をecho
する場合、通常はこの関数を使用しましょう。
WordPressのカテゴリー名は、タグの使用は一切できない、通常テキストです。
1 2 3 4 5 6 |
<?php $category = get_category(1); // カテゴリーID1は「HTML & CSS」という名前 ?> <?php echo $category->name; ?> <?php echo esc_html( $category->name ); ?> |
出力結果
1 2 |
HTML & CSS HTML & CSS |
この場合、エスケープしていない場合もした場合も、同じ出力結果になります。
WordPressのカテゴリー名は、データベースに記録される際に、実体参照へのエスケープ処理を行ってしまうからです。
しかし、すでにエスケープされているカテゴリー名を再びエスケープしても結果が同じなのは、esc_html
関数には、2重にエスケープされるのを防いでくれる機能があるからです。
カテゴリー名は既にエスケープされている、というようにシステム内の仕様を確実に把握できている場合にはエスケープ処理の必要はありません。
しかし、全ての仕様を把握するのは困難ですし、迷ったらesc_html
でエスケープしておくのが安全策です。
HTMLテキストの取扱い
テキストにHTMLタグを含んでいて、タグをブラウザの表示に反映させたい場合は、エスケープしないでecho
します。
WordPressの投稿のタイトル、本文、コメントには、HTMLタグを含めることができるので、直接echo
します。
1 2 3 4 5 6 |
<?php $title = get_the_title(1); $content = get_the_content(1); ?> <h1><?php echo $title; ?></h1> <div><?php echo $content; ?></div> |
<script>
や<iframe>
タグなど、セキュリティリスクの高いHTMLタグへの対策として、ダッシュボードから投稿する際に、一定の権限以外のユーザの投稿は、危険なタグをフィルタリングするようになっています。
※特権管理者、管理者、編集者の投稿はフィルタリングされません
一方、表示の際のセキュリティ対策は特に行われません。
特に対策を施したい場合には、リスクの高いタグを除去するwp_kses_post
関数や、全てのタグを除去するstrip_tags
を使用する事ができます。
1 2 3 |
<?php $title = the_title('', '', false); ?> <h1><?php echo wp_kses_post($title); ?></h1> // <script>タグなどを除去する <h1><?php echo wp_strip_all_tags($title); ?></h1> // 全てのタグを除去する |
カスタムフィールドの出力では常にエスケープする
カスタムフィールドでは、投稿タイトルや本文と同じようにHTMLタグを含めることができます。
しかもカスタムフィールドの場合はタイトルや本文と違い、投稿の際に危険なタグの自動除去を一切行いません。
カスタムフィールドの値をページ上に出力する場合には、何らかのエスケープを必ず行いましょう。
カスタムフィールドでは様々な用途で使用できるので、用途によってエスケープ方法を適切に選択します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<?php $meta_text = get_post_meta($post->ID, 'text', true); $meta_html = get_post_meta($post->ID, 'html', true); $meta_url = get_post_meta($post->ID, 'url', true); // 通常テキスト(HTMLタグは実体参照に変換) echo esc_html( $meta_text ); // 通常テキスト(HTMLタグは全て除去) echo esc_html( wp_strip_all_tags( $meta_text ) ); // HTMLテキスト(一部のタグを除去) echo wp_kses_post( $meta_html ); // URL echo esc_url( $meta_url ); ?> |
テキストエリアのエスケープ
テキストエリア内でのエスケープは、esc_textarea
関数を使用します。
1 |
<textarea><?php echo esc_textarea( $text ); ?></textarea> |
属性値のエスケープ
HTMLタグの属性値では、WordPressのesc_attr
関数を使います。
属性値がURLの場合は後述のesc_url
関数を使用しますが、URL以外の属性値には全てesc_attr
を使用します。
1 |
<time pubdate="<?php echo esc_attr( get_the_time('Y-n-j') ); ?>"><?php the_time('Y/n/j'); ?></time> |
URLのエスケープ
URLのエスケープには、WordPressのesc_url関数を使います。
この関数は、URLで使用できない文字の変換や除去を行い、セキュリティ的に無害化します。
1 2 |
このサイトのホーム: <?php echo esc_url( home_url() ); ?><br /> <a href="<?php echo esc_url( home_url() ); ?>">リンク</a> |
esc_url関数は、http://〜やhttps://〜などで始まる完全なURLに対して使うことができますが、相対URLや、URLの一部分に対して使うことはできません。
1 2 3 4 |
// 相対URLには使えない <a href="<?php echo esc_url( '../news/index.html' ); ?>">リンク</a> // URLの一部分だけには使えない <a href="http://my-domain.com/search?q=<?php echo esc_url( 'キーワード' ); ?>">検索</a> |
URL内の文字のエスケープ
URLでは、使用できる文字が決められていて、それ以外の文字を使用する場合にはURLエンコードというエスケープ処理を行います。
URLに、変数や関数が返す値を含めたり、パラメータに別なURLを含める場合には、必ずURLエンコードをします。
1 2 3 4 5 6 |
// URLに変数の値を含む <?php $page_name = 'メールフォーム'; ?> <a href="<?php echo esc_url( 'http://my-domain.com/' . urlencode( $page_name ) . '/' ); ?>">メールフォームへのリンク</a> // パラメータに別なURLを含む <a href="<?php echo esc_url( 'https://twitter.com/intent/tweet?url=' . urlencode( 'http://my-domain.com/' ) ); ?>">ツイート</a> |
まとめ
- テキストは、
esc_html
関数でエスケープする - HTMLは、セキュリティリスクに応じて
wp_kses_post
関数でリスクの高いタグを除去する(カスタムフィールドでは必ず行う) - テキストエリアは、
esc_textarea
関数でエスケープする - HTMLの属性値は、
esc_attr
関数でエスケープする - URLは、
esc_url
関数で無害化する - URL内の文字列は、
urlencode
関数でエスケープする
- カスタムフィールドを
echo
する際には、必ずエスケープや無害化を行う
TRACKBACKS