WordPressでよく見かけるけどよくわからない関数 esc_urlについて

esc_urlについて

先日とある勉強会で
「WordPressの配布されてるテーマでは結構使われているようなんですけれど、esc_urlという関数って何のためにあるのですか?」
という質問を頂きました。
「エ、エスケープする関数なんで適当に使ったらいいですよ!」
なんていう答えにならない答えを返してしまったので反省して調べておきます。

WordPressに標準で付いてくるデフォルトテーマにはesc_urlがふんだんに使われています。
たとえばtwenty fifteenではheader.phpに使われていて

<?php echo esc_url( get_template_directory_uri() );

といったように、テンプレートディレクトリを出力する際に間に挟んで利用しています。

どうしてこのように出力をするためにつかっているのか、なぜそのまま出力するといけないのかについて調べてみました。

マニュアルを調べてみた

まずは公式の説明について調べてみました。
幸い日本語訳がありましたのでそちらを紹介します。

テキストや属性などのURLを無害化する時に用いる関数です。ホワイトリストに登録されているプロトコル (デフォルトでは、http, https, ftp, ftps, mailto, news, irc, gopher, nntp, feed, telnet) 以外のURLを拒絶し、無効なキャラクタを除外し、危険なキャラクタを削除します。 この関数はキャラクタをHTMLエンティティとしてエンコードし、 (X)HTML または XML ドキュメントを作成する時に用います。アンド記号 (&) とシングルクォート (') はそれぞれ (&#038, &#039) という形に変換します。 この関数は非推奨となった clean_url() の代わりに用いるものです。

なるほど、ホワイトリストに登録されているプロトコル以外を拒否し、また使ってはダメな文字をURLから省いたり変換したりするもの、なのですね。

実際に動かしてみる

それでは早速どのような動きになるか試してみました。

$urls = array(
  'http://www.example.com/hogehoge',
  'https://www.example.com/hogehoge',
  'tel://example.com',
  'tel://0120000000',
  'http://.$,;:&=?!*[email protected]#_()',
  'http://\"\'|*`^><)(}{][',
);
foreach($urls as $url) {
  echo $url."<br />\n";
  echo esc_url($url)."<br />";
}

出力はこうなります

元テキスト esc_url変換後
http://www.example.com/hogehoge http://www.example.com/hogehoge
www.example.com/hogehoge http://www.example.com/hogehoge
https://www.example.com/hogehoge https://www.example.com/hogehoge
tel://example.com tel://example.com
tel://0120000000 tel://0120000000
hoge://0120000000
http://.$,;:&=?!*[email protected]#_()’| http://.$,;:&=?!*[email protected]#_()’|
http://\”`^><{}[] http://
http://ほげふがぴよ http://ほげふがぴよ

なるほど、色々と変化していますね。
httpやhttpsはそのまま出力されていますね。
またtel:も出力されているようです。マニュアルにtelというのは無いのですが、どうやら出力されるようです。
ログなどを追いかけてみると(#18268, #21081, src)WordPress3.4あたりで「telやfaxといったプロトコルも追加してくれ」という要望があがったそうで、それに対応する形で追加れたようです。
他には記号系が削除されるようですね。これはURLで利用してもよい文字とそうでは無い文字がありまして、そのルールに沿って削除されるようです。

esc_urlの目的

さて、このesc_urlの目的なのですがなぜ必要なのかについて考えてみました。
まずはURLとして無効な文字を防ぐことですね。
URLに利用して良い文字というのはIETFがRFC1738として定義しています。一般の利用者が「この文字は使える、これはダメ」と調べるのは大変ですから、esc_urlを利用する事でこの違反を防ぐことができます。
またプロトコルのホワイトリストについては、インジェクション攻撃などに対応する目的があるでしょう。例えばコメントの「ウェブサイト」の部分にtelで110番を書かれてしまうと、携帯電話ユーザがクリックした際、いきなり110番が掛かってしまったりします。今ではウェブサイトやメールから通話する際には警告がでますが、そういった対処の無かったガラケー全盛期に流行った手法ですね。
telプロトコルの許可については許可されていると書きましたが、調べたところコメントでは不許可のようです。
プロトコルのホワイトリストについてはテーマ作成者がちゃんと管理できるようになっているので、例えばお店紹介サイトであれば「どこでもtelプロトコルを許可したい」、といった要望にも応えることができます。
基本的にesc_urlの目的としては、「意図しないURLの誤った誘導を防ぐ」ことだと思っています。ですのでテーマを作成する際にURLを出力する箇所でesc_urlを埋め込むことで不正なURLが吐き出されることを防いでくれます。

まとめ

esc_urlを使うと不正なURLを防いでくれます。またコメント(本文ではないところ)などURLが入ってくる箇所でesc_urlを挟む事でインジェクション攻撃を防ぐことにもなります。
ですのでURLが入る箇所では積極的にesc_urlを使っていきたいですね。

コメントを残す