なぜPHPアプリにセキュリティホールが多いのか?

第20回 文字エンコーディングとセキュリティ(2)

この記事を読むのに必要な時間:およそ 3.5 分

文字エンコーディングを誤認識させる(誤認識を利用する)攻撃

文字エンコーディングを誤認識させる方法は,クロスサイトスクリプティング脆弱性の危険性を指摘したCA-2000-02でも指摘しているのは既に紹介した通りです。もっとも分かりやすい例は,UTF-7エンコーディングを利用した攻撃方法です。UTF-7の場合,HTMLの特殊文字である<,>がエンコードされ,別の文字列に変換されます。

UTF-7エンコーディングへの変換

<?php echo mb_convert_encoding('< >', 'UTF-7');?>

出力

+ADw +AD4-

UTF-7に変換後には<,>がないので,UTF-7エンコーディングの文字列データをhtmlentities/htmlspecialchars関数などでエスケープ処理しても意味がありません。UTF-7はASCIIデータと変わらないので,不正な文字エンコーディングを検出していても役に立ちません。UTF-7以外で記述されたページに,UTF-7の文字列データを送り,ブラウザなどが誤ってUTF-7文字エンコーディングと認識してまうと不正なスクリプトやHTMLタグの埋め込みが可能となります。

Webブラウザには文字エンコーディングの自動識別機能があります。そして,多くのユーザは文字エンコーディングの自動識別機能を有効に設定しています。このため,攻撃者はWebアプリケーションにUTF-7でエンコードした文字列を送るだけで,簡単に攻撃が成功してしまう場合もあります。

2000年のクロスサイトスクリプティング脆弱性のアドバイザリ(CA-2000-02)「すべての動的に生成されたWebページは明示的に適切な文字コードセットを設定しなければならない」としているのは,この種の攻撃を防ぐために記述されています。

対策:
明示的に文字エンコーディングを指定する。例えば,HTTPヘッダのcharset属性でアプリケーションが利用する文字エンコーディングを指定する。

HTTPヘッダで文字エンコーディングを設定している場合,本来であればWebブラウザはエンコーディングの自動識別を行うべきではありません。しかし,自動識別を行っているブラウザではHTTPヘッダの指定を無視して,自動的に文字エンコーディングを識別してしまうブラウザもあります。追加の対策としてMETAタグでも文字エンコーディングを指定するほうがよいでしょう。

METAタグでの文字エンコーディング指定例(UTF-8)

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

PHPでHTTPヘッダのContent-Typeヘッダのcharset属性で文字エンコーディングを指定する場合は,ini_set関数でdefault_charsetを設定するか,php.iniのdefault_charsetを設定します。

ini_set関数

ini_set('default_charset', 'UTF-8');

php.ini

default_charset="UTF-8"

JSPやASPでWebアプリケーションを作ったことがある方は,お約束として文字エンコーディングを記載するようになっているサンプルコードが多いです。その結果として正しい文字エンコーディングの取り扱いとなっているアプリケーションが多いですが,PHPの場合,php.iniで設定できるのでアプリケーションで設定していないことが少なくありません。

筆者はphp.iniファイルの規定値としてdefault_charsetに何らかの文字エンコーディングを指定すべきだと考えていますが,ソース版のPHPに付属するphp.iniにはdefault_charsetが設定されていません。多くのPHPアプリケーションがdefault_chaset設定を変更していないので,php.iniで設定するか,アプリケーションの初期化ファイルなどに手を加えない限り脆弱な状態になってしまっています。

文字エンコーディングの誤認識を利用した攻撃を防ぐには,先ほど紹介した対策である「文字エンコーディングが正しいエンコーディングかチェックする」対策も重要です。Webサイトを参照したユーザが「文字化けかな?」と思って,使用する文字エンコーディングを切り替えた時に不正なJavaScriptを実行させる攻撃手法もよく知られています。

ブラウザの文字エンコーディングの自動認識機能を無効にしてWebサイトを利用していると,比較的有名なサイトでも文字エンコーディングの取り扱いに不備があることに気が付くことが少なくありません。この記事を読まれる方は開発者の方とは思いますが,普段Webページを参照するエンドユーザとしてのセキュリティ対策として「ブラウザの文字エンコーディング自動認識機能は無効にする」ことをお薦めします。より安全にブラウジングできるだけでなく,自分の構築しているサイトが誤った処理をしていないかチェックするためにも役立ちます。

まとめ

すべての文字エンコーディングを利用した攻撃については解説できませんでしたが,文字エンコーディングと文字列を厳格に取り扱う必要性は理解頂けたと思います。次回も文字エンコーディングを用いた代表的な攻撃の手法の解説を続けます。

著者プロフィール

大垣靖男(おおがきやすお)

University of Denver卒。同校にてコンピュータサイエンスとビジネスを学ぶ。株式会社シーエーシーを経て,エレクトロニック・サービス・イニシアチブ有限会社を設立。
オープンソース製品は比較的古くから利用し,Linuxは0.9xのころから利用している。オープンソースシステム開発への参加はエレクトロニック・サービス・イニシアチブ設立後から。PHPプロジェクトでは,PostgreSQLモジュールのメンテナンスを担当している。

URLhttp://blog.ohgaki.net/

著書