Security of HTTPHeader 2007 年 10 月 30 日 Ver. 1.2
目 次 1 WebAppli で 使 う HTTP ヘッダ 作 成 関 数 の 安 全 な 使 い 方 2 1.1 本 文 書 の 目 的 3 2 HTTP ヘッダ インジェクションの 概 要 4 2.1 HTTP ヘッダ インジェクションの 概 要 5 2.2 HTTP ヘッダ インジェクションへの 対 策 6 3 HTTP ヘッダ インジェクションの 具 体 的 な 安 全 策 7 3.1 CGI の 場 合 8 3.2 Perl + CGI.pm の 場 合 8 3.2.1 Perl5.6.1/CGI.pm2.752 + PlamoLinux3.0 の 場 合 8 3.2.2 Perl5.005_03/CGI.pm2.46 の 場 合 14 3.3 IIS + ASP の 場 合 16 3.4 ASP.NET の 場 合 18 3.5 JavaServlet の 場 合 20 3.6 PHP5.2.0 の 場 合 22 3.7 AzaraC0.3.0 の 場 合 25 4 執 筆 者 など 27 4.1 本 文 書 の 免 責 事 項 28 4.2 執 筆 者 28 4.3 更 新 履 歴 28 4.4 本 文 書 の 最 新 バージョン 28 4.5 HTTP ヘッダ 名 29 1
1 WebAppli で 使 う HTTP ヘッダ 作 成 関 数 の 安 全 な 使 い 方 2
1.1 本 文 書 の 目 的 本 文 書 は Web アプリケーションで 利 用 されている 各 種 HTTP ヘッダ 作 成 用 関 数 の 安 全 な 使 い 方 について 検 討 する 本 文 書 で 対 象 としている 脅 威 は 主 に 以 下 である HTTP ヘッダ インジェクション (HTTP Response Splitting[ ]) HTTP ヘッダ インジェクションというより H TTP Response-Splitting 攻 撃 の 方 が 有 名 であ ろう しかしながら どの 関 数 が 改 行 コードを 許 しているのかを 調 査 している 文 献 が 見 受 けられなかっ た 一 方 で [システム 開 発 者 プログラマ]にとっては このような 情 報 が 必 要 な 情 報 であると 感 じ 本 文 書 を 作 成 した [ ] HTTP Response Splitting, Web Cache Poisoning Attacks, and Related Topics https://www.watchfire.com/securearea/whitepapers.aspx?id=8 3
2 HTTP ヘッダ インジェクション の 概 要 4
2.1 HTTP ヘッダ インジェクションの 概 要 Web で 使 用 している HTTP は テキスト 形 式 の 通 信 プロトコルであり 空 行 を 挟 み 前 段 を HTTP ヘッダ 後 段 を HTTP ボディ と 分 ける 構 造 となっている また HTTP ヘッダ は ヘッダ 情 報 を 一 行 に 一 つを 基 本 形 式 としている Web ブラウザと Web アプリケーション 間 でのクッキー 情 報 の 交 換 や Web ページのリダイレク ト 先 を 示 す URI の 情 報 交 換 などに HTTP ヘッダは 用 いられている そして ほとんどの Web アプリケーションには HTTP ヘッダを 操 作 する 関 数 が 用 意 されている Web アプリケーションプログラマが 一 般 的 に 利 用 するのは 以 下 の 3 つであると 思 われる クッキーを Web ブラウザへ 送 信 する 関 数 Web ページのリダイレクトを 命 令 する 関 数 任 意 の HTTP ヘッダを[ 追 加 上 書 ]する 関 数 これらの 関 数 に 汚 染 データ[ ]を 渡 した 場 合 汚 染 データ 中 に 改 行 コード(ヘッダ 情 報 の 区 切 りが 改 行 コードであるため)を 挿 入 することによって 任 意 の HTTP ヘッダを 挿 入 されてしまうという のが HTTP ヘッダ インジェクションである また クッキー 情 報 の 各 プロパティは ;(セミコロン) をデリミタとしているため ; を はさ んで 任 意 のプロパティを 指 定 される 危 険 性 もある 脅 威 は 任 意 の HTTP ヘッダを 挿 入 される クッキー 情 報 に 任 意 のプロパティを 挿 入 される HTTP Response Splitting などであるが 現 実 的 な 深 刻 度 はそれほど 高 くない しかし Web アプリケーションを 開 発 する[システム 開 発 者 プログラマ]の 方 々には このような それほど 深 刻 度 が 高 くないセキュリティ 問 題 といえども 放 置 せずに 適 切 なプログラミングを 行 うことを 希 望 する [ ] 汚 染 データ ここでは 利 用 者 から Web アプリケーションへ 入 力 された 安 全 な 書 式 であると 検 証 されていない データと 定 義 する 汚 染 されているかも 知 れないデータ とした 方 がより 正 確 であるような 気 が する 5
2.2 HTTP ヘッダ インジェクションへの 対 策 HTTP ヘッダを 操 作 する 関 数 に 汚 染 データを 与 える 場 合 改 行 コードについてサニタイズ 処 理 を 実 施 する ASP/ASP.NET や PHP では URL エンコードを 実 施 している もし 読 者 が 利 用 している Web アプリケーション 用 の 開 発 環 境 の HTTP ヘッダ 作 成 関 数 内 部 で サニタイズ 処 理 を 行 っていないのであれば ASP/ASP.NET や PHP の 方 法 を 模 倣 して Web ア プリケーションプログラマがそれらの 関 数 を 用 いる 前 に URL エンコードを 実 施 すればよいだろ う また クッキー 情 報 の 各 プロパティは ;(セミコロン) をデリミタとしている 利 用 する 関 数 内 部 でサニタイズ 処 理 していなければ Web アプリケーションプログラマ 自 身 が 事 前 に ;(セミコ ロン) を URL エンコードすればよいだろう 以 下 の 章 で 明 らかとなるが ASP/PHP と Java とでは 異 なるサニタイズ 処 理 がおこなわれてい た どちらが 正 しいのだろうか 6
3 HTTP ヘッダ インジェクション の 具 体 的 な 安 全 策 7
3.1 CGI の 場 合 CGI では HTTP ヘッダも 含 めて HTTP リクエスト 全 体 (HTTP ヘッダ+HTTP ボディ)を CGI プ ログラマが 作 成 する 必 要 がある よって HTTP ヘッダを 作 成 中 に 汚 染 データを 使 う 場 合 汚 染 データ 中 の 改 行 コードに 注 意 する 必 要 がある また クッキー 情 報 の 各 プロパティは ;(セミコロン) をデリミタとしているため クッキー 情 報 の HTTP ヘッダを 作 成 する 際 は ;(セミコロン) もサニタイズ 処 理 する 必 要 がある 3.2 Perl + CGI.pm の 場 合 Perl には 標 準 で CGI.pm というモジュールがある このモジュールにある CGI.header() 関 数 CGI.redirect() 関 数 CGI::Cookie オブジェクトなどを 使 う 場 合 も 多 いのではないだろうか CGI.pm での HTTP ヘッダ 操 作 は 以 下 の 関 数 がよく 使 われる 関 数 名 CGI.header() CGI.redirect() CGI::Cookie 操 作 内 容 HTTP ヘッダ 生 成 Web ページのリダイレクト 要 求 クッキー 情 報 の 作 成 これらの 関 数 に 汚 染 データが 配 置 されるようなテストプログラム()を 作 成 し Netcat を 使 ってど のような HTTP レスポンスが 返 るかを 観 察 した 3.2.1 Perl5.6.1/CGI.pm2.752 + PlamoLinux3.0 の 場 合 この 章 では PlamoLinux3.0(Linux2.4.19) + Perl5.6.1/CGI.pm 2.752 を 実 験 環 境 として 使 用 した 結 果 である 図 3.2.1-1~ 図 3.2.1-2では CGI.Cookie オブジェクトでクッキーオブジェクトを 作 り それ をそのまま 出 力 する 場 合 である 8
Cookie の 値 として 含 まれている 改 行 (Lf) クッキー 属 性 のデリミタである ;(セミコロン) が URL エンコード 処 理 が 行 なわれている このようなコードを Perl プログラマが 書 く 場 合 改 行 や ;(セミコロン) を 特 に 意 識 せずに 記 述 しても 安 全 であるということである #! /usr/local/bin/perl use strict; use CGI; use CGI::Cookie; my ${cgi} = new CGI; my ${str} = "test; nnewheader:value"; my ${myc} = new CGI::Cookie( -name=>'cookiename', -value=>${str} ); print "Set-Cookie: ${myc} n"; printf("content-type: text/html n n"); printf("${str} n"); printf(${cgi}->version()); printf(" n"); END 図 3.2.1-1 : Cookie をそのまま 出 力 するテストスクリプト #./cgimod-test.pl Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/ Content-Type: text/html test; newheader:value 2.752 # echo "HEAD /cgi-bin/cgimod-test.pl HTTP/1.0 n n" nc -nvv 127.0.0.1 80 (UNKNOWN) [127.0.0.1] 80 (?) open 9
HTTP/1.1 200 OK Date: Fri, 30 Mar 2007 06:27:19 GMT Server: Apache/2.0.47 (Unix) mod_ssl/2.0.47 OpenSSL/0.9.6f DAV/2 Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/ Connection: close Content-Type: text/html sent 40, rcvd 226 図 3.2.1-2 : 図 3.2.1-1の 実 行 結 果 直 接 実 行 しても Apache 経 由 でも URL エンコードが 行 なわれている 図 3.2.1-3~ 図 3.2.1-4では Cookie オブジェクトを CGI.header() 関 数 経 由 で 出 力 する 場 合 で ある 図 3.2.1-4を 見 て 分 るとおり クッキーの 値 は URL エンコードされていることが 確 認 できる このようなコードを Perl プログラマが 書 く 場 合 改 行 や ;(セミコロン) を 特 に 意 識 せずに 記 述 しても 安 全 であるということである #! /usr/local/bin/perl use strict; use CGI; use CGI::Cookie; my ${cgi} = new CGI; my ${str} = "test; nnewheader:value"; my ${myc} = new CGI::Cookie( -name=>'cookiename', -value=>${str} ); print ${cgi}->header( -cookie=>${myc} ); printf("${str} n"); printf(${cgi}->version()); printf(" n"); END 図 3.2.1-3 : Cookie を CGI.header() 関 数 経 由 で 出 力 するテストスクリプト 10
#./cgimod-test.pl Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/ Date: Fri, 30 Mar 2007 04:53:21 GMT Content-Type: text/html; charset=iso-8859-1 test; newheader:value 2.752 # echo "HEAD /cgi-bin/cgimod-test.pl HTTP/1.0 n n" nc -nvv 127.0.0.1 80 (UNKNOWN) [127.0.0.1] 80 (?) open HTTP/1.1 200 OK Date: Fri, 30 Mar 2007 04:53:49 GMT Server: Apache/2.0.47 (Unix) mod_ssl/2.0.47 OpenSSL/0.9.6f DAV/2 Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/ Connection: close Content-Type: text/html; charset=iso-8859-1 sent 40, rcvd 246 図 3.2.1-4 : 図 3.2.1-3の 実 行 結 果 URL エンコードされたためヘッダインジェクションは 発 現 しない 図 3.2.1-5~ 図 3.2.1-6では CGI.redirect() 関 数 を 使 ったテストスクリプトである 図 3.2.1-6を 見 て 分 るとおり ローカルからの 実 行 時 には (ダブルクォート) で 囲 まれつつも Lf インジェクションに 成 功 しているが Apache 経 由 では Location ヘッダ 自 体 が HTTP レスポ ンスに 含 まれていないことが 分 る よって CGI.redirect() 関 数 を 使 う 限 りにおいて Lf インジェクションは 気 にする 必 要 がないと 考 えられる 11
#! /usr/local/bin/perl use strict; use CGI; my ${cgi} = new CGI; my ${str} = "test; nnewheader:value"; print ${cgi}->redirect(${str}); printf("${str} n"); printf(${cgi}->version()); printf(" n"); END 図 3.2.1-5 : CGI.redirect() 関 数 を 使 うテストスクリプト #./cgimod-test.pl Status: 302 Moved location="test; newheader:value" test; newheader:value 2.752 # echo "HEAD /cgi-bin/cgimod-test.pl HTTP/1.0 n n" nc -nvv 127.0.0.1 80 (UNKNOWN) [127.0.0.1] 80 (?) open HTTP/1.1 302 Moved Date: Fri, 30 Mar 2007 05:07:09 GMT Server: Apache/2.0.47 (Unix) mod_ssl/2.0.47 OpenSSL/0.9.6f DAV/2 Connection: close Content-Type: text/html; charset=iso-8859-1 sent 40, rcvd 189 図 3.2.1-6 : 図 3.2.1-5の 実 行 結 果 ローカル 実 行 した 時 は (ダブルクォート) で 囲 まれながらも Lf インジェクションに 成 功 しているが Apache 経 由 では HTTP レスポンスに 含 まれていない ローカルで で 囲 まれているところ 名 と 値 の 境 界 が : でなくて = になっているところが 興 味 深 い 12
図 3.2.1-7~ 図 3.2.1-8では CGI.header() 関 数 を 使 ったテストスクリプトである 図 3.2.1-8を 見 て 分 るとおり ローカルからの 実 行 時 には (ダブルクォート) で 囲 まれつつも Lf インジェクションに 成 功 しているが Apache 経 由 では 500 エラーとなっていることが 分 る よって CGI.header() 関 数 を 使 う 限 りにおいて Lf インジェクションは 気 にする 必 要 がないと 考 えられる #! /usr/local/bin/perl use strict; use CGI; my ${cgi} = new CGI; my ${str} = "test; nnewheader:value"; print ${cgi}->header( ); -myheader=>${str} printf("${str} n"); printf(${cgi}->version()); printf(" n"); END 図 3.2.1-7 : CGI.header() 関 数 を 使 うテストスクリプト #./cgimod-test.pl myheader="test; newheader:value" Content-Type: text/html; charset=iso-8859-1 test; newheader:value 2.752 # echo "HEAD /cgi-bin/cgimod-test.pl HTTP/1.0 n n" nc -nvv 127.0.0.1 80 (UNKNOWN) [127.0.0.1] 80 (?) open 13
HTTP/1.1 500 Internal Server Error Date: Fri, 30 Mar 2007 05:19:21 GMT Server: Apache/2.0.47 (Unix) mod_ssl/2.0.47 OpenSSL/0.9.6f DAV/2 Connection: close Content-Type: text/html; charset=iso-8859-1 sent 40, rcvd 205 図 3.2.1-8 : 図 3.2.1-7の 実 行 結 果 ローカル 実 行 した 時 は (ダブルクォート) で 囲 まれながらも Lf インジェクションに 成 功 しているが Apache 経 由 では HTTP レスポンスに 含 まれていない ローカルで で 囲 まれているところ 名 と 値 の 境 界 が : でなくて = になっているところが 興 味 深 い また Apache 経 由 の 時 500 エラーが 返 されている 結 論 : CGI.pm モジュールの header() 関 数 redirect() 関 数 を 介 して HTTP レスポンスを 作 る 限 りにお いて Perl プログラマは CrLf インジェクションについて 気 にかける 必 要 はない また クッキー 情 報 を CGI::Cookie オブジェクトで 操 作 するかぎりにおいて 本 項 で 指 摘 してる 改 行 ;(セミコロン) について 気 にかける 必 要 はない 3.2.2 Perl5.005_03/CGI.pm2.46 の 場 合 この 章 では 筆 者 の ISP 環 境 (Perl5.005_03/CGI.pm2.46)を 実 験 環 境 として 使 用 した 結 果 である 3.2.1と 同 一 の 結 果 であった C: >type a.txt HEAD /~example/cgi-bin/cgimod-test.pl HTTP/1.0 Host: www.example.com C: >nc www.example.com 80 < a.txt HTTP/1.1 500 Internal Server Error // ここは CGI.header() の 結 果 である 14
Date: Fri, 30 Mar 2007 05:59:58 GMT Server: Apache/1.3.9 (Unix) Connection: close Content-Type: text/html // ここは CGI.redirect() の 結 果 である C: >nc www.example.com 80 < a.txt HTTP/1.1 302 Moved Date: Fri, 30 Mar 2007 06:01:49 GMT Server: Apache/1.3.9 (Unix) Connection: close Content-Type: text/html // ここは CGI.header() 経 由 の CGI::Cookie オブジェクトの 結 果 である C: >nc www.example.com 80 < a.txt HTTP/1.1 200 OK Date: Fri, 30 Mar 2007 06:05:43 GMT Server: Apache/1.3.9 (Unix) Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/~example/cgi-bin/ Connection: close Content-Type: text/html // ここは CGI.header() 経 由 しないの CGI::Cookie オブジェクトの 結 果 である C: >nc www.example.com 80 < a.txt HTTP/1.1 200 OK Date: Fri, 30 Mar 2007 06:07:10 GMT Server: Apache/1.3.9 (Unix) Set-Cookie: cookiename=test%3b%0anewheader%3avalue; path=/~example/cgi-bin/ Connection: close Content-Type: text/html 図 3.2.2-1 : ISP の 環 境 なので ローカルから 実 行 した 結 果 は 不 明 だが 3.2.1 章 と 同 一 の 結 果 となった 15
3.3 IIS + ASP の 場 合 IIS + ASP での HTTP ヘッダ 操 作 は 以 下 の 関 数 がよく 使 われる 関 数 名 Response.Redirect Response.Cookies Response.AddHeader 操 作 内 容 Web ページのリダイレクト 要 求 クッキー 情 報 の 送 信 任 意 ヘッダの 追 加 これらの 関 数 に 汚 染 データが 配 置 されるようなテストプログラム( 図 3.3-1)を 作 成 し Netcat を 使 ってどのような HTTP レスポンスが 返 るかを 観 察 した MS-WindowsServer2003 SP1( 日 本 語 版 )を 実 験 環 境 として 使 用 した <% Option Explicit Dim str str =Request.QueryString("inputData") Response.AdHeader "TestHeader",str Response.Cokies("TestCookie") =str Response.Redirectstr %> 図 3.3-1 : ASP のヘッダ 送 信 関 数 の 実 験 プログラム 16
図 3.3-2 : 図 3.3-1の 結 果 結 果 は 図 3.3-2のように AddHeader() 関 数 以 外 は 関 数 内 部 で 改 行 コードのサニタイズ 処 理 が 行 われていることが 確 認 された よって ASP で 上 記 の 関 数 を 使 う 場 合 AddHeader() 関 数 以 外 は HTTP ヘッダ インジェクシ ョンに 気 を 使 わずにコーディングを 行 うことができる また AddHeader() 関 数 を 使 用 する 際 には ASP プログラム 内 で 改 行 コードをサニタイズ 処 理 ( 他 の 関 数 との 関 係 も 考 えれば URL エンコードが 妥 当 だろう)することがセキュリティ 対 策 上 必 要 な 対 策 である ということである 蛇 足 : 図 3.3-2のように ASP では 改 行 コード(Cr と Lf)などが URL エンコードされている Location ヘッダには 汚 染 データそのものが 与 えられている 汚 染 データに 別 サイトの URL を 指 定 される 必 要 がない 場 合 は その 対 策 が 別 途 必 要 である クッキー 情 報 の 箇 所 では ; がサニタイズ 処 理 されている( ; が URL エンコードされ %3B になっている) よって ASP.NET とは 異 なり クッキー 情 報 の 値 をセットする 際 には と くにセキュリティ 対 策 を 考 慮 しなくてもよい ということになる 17
3.4 ASP.NET の 場 合 ASP.NET での HTTP ヘッダ 操 作 は 以 下 の 関 数 がよく 使 われるだろう 関 数 名 操 作 内 容 Response.RedirectLocation Web ページのリダイレクト 要 求 Response.Cookies.Add クッキー 情 報 の 送 信 Response.AddHeader 任 意 ヘッダの 追 加 Response.AppendHeader これらの 関 数 に 汚 染 データが 渡 るようなテストプログラム( 図 3.4-1)を 作 成 し Netcat を 使 ってど のような HTTP レスポンスが 返 るかを 観 察 した MS-Windows2000 SP4( 日 本 語 版 ) 上 の WebMatrix0.6.812 +.Net Framework1.1SP1(1.1.4322) を 実 験 環 境 として 使 用 した // ヘッダ 追 加 用 メソッド Response.AddHeader("myAdHeader",TextBox1.Text); Response.AppendHeader("myApendHeader",TextBox1.Text); // クッキー 送 出 用 メソッド HttpCokie MyCokie =new HttpCookie("myAdCokie"); MyCookie.Value = TextBox1.Text; Response.Cookies.Add(MyCookie); // リダイレクト 用 メソッド Response.RedirectLocation =TextBox1.Text; 図 3.4-1 : ASP.NET のヘッダ 送 信 関 数 の 実 験 プログラム (C#) 18
図 3.4-2 : 図 3.4-1の 結 果 結 果 は 図 3.4-2のように 関 数 内 部 で 改 行 コードのサニタイズ 処 理 が 行 われていることが 確 認 さ れた よって ASP.NET で 上 記 の 関 数 を 使 う 場 合 は HTTP ヘッダ インジェクションに 気 を 使 わず にコーディングを 行 うことができる 蛇 足 : 図 3.4-2のように ASP.NET では 改 行 コード(Cr と Lf)が URL エンコードされている Location ヘッダには 汚 染 データそのものが 与 えられている 汚 染 データに 別 サイトの URL が 指 定 される 必 要 がない 場 合 は その 対 策 が 別 途 必 要 である クッキー 情 報 の 箇 所 では ; がサニタイズ 処 理 されていない よって クッキー 情 報 の 値 以 外 のプロパティ(Domain や Expires など)を 汚 染 データによってセットされる 危 険 性 がある 他 の 関 数 との 関 係 も 考 えれば ; % 3b に 置 換 する URL エンコード 処 理 を ASP.NET プログラマは 行 う 必 要 がある 19
3.5 JavaServlet の 場 合 JavaServlet での HTTP ヘッダ 操 作 は 以 下 の 関 数 がよく 使 われるだろう 関 数 名 操 作 内 容 response.sendredirect Web ページのリダイレクト 要 求 response.addcookie クッキー 情 報 の 送 信 response.addheader 任 意 ヘッダの 追 加 これらの 関 数 に 汚 染 データが 渡 るようなテストプログラム( 図 3.5-1)を 作 成 し Netcat を 使 ってど のような HTTP レスポンスが 返 るかを 観 察 した MS-WindowsXP SP2( 日 本 語 版 ) 上 の Tomcat5.5.17 JDK1.5.0_06 Eclipse3.1.2 を 実 験 環 境 とし て 使 用 した protectedvoiddoget(httpservletrequestrequest,httpservletresponseresponse)throwsserv letexception, IOException { StringmyAddStr; StringIsRedirect; request.setcharacterencoding("windows-31j"); myaddstr = request.getparameter("addstr"); IsRedirect =request.getparameter("isredirect"); // HTTP ヘッダの 追 加 response.addheader("myadheader",myaddstr); // クッキーの 追 加 CookiemyCokie= newcokie("mycookie",myaddstr); response.addcookie(mycookie); // location ヘッダの 追 加 // redirect to JSP if(isredirect.equals("1") = true){ d(request,response); getservletconfig().getservletcontext().getrequestdispatcher("/result.jsp").forwar }else{ response.sendredirect(myaddstr); } } 図 3.5-1 : JavaServlet のヘッダ 送 信 関 数 の 実 験 プログラム 20
図 3.5-2 : 図 3.5-1の 結 果 (パケットキャプチャを 行 うと 改 行 コードが 0x20 に 置 換 されていることが 分 かる) 結 果 は 図 3.5-2のように 関 数 内 部 で 改 行 コードのサニタイズ 処 理 が 行 われていることが 確 認 さ れた よって JavaServlet で 上 記 の 関 数 を 使 う 場 合 は HTTP ヘッダ インジェクションに 気 を 使 わ ずにコーディングを 行 うことができる 蛇 足 : 改 行 コード(Cr と Lf)がどのコードに 置 換 されるかというものは パケットキャプチャをした 結 果 半 角 スペース(0x20) に 置 換 されることを 確 認 した Location ヘッダの 左 側 の 赤 線 にあるように 自 動 で 自 サイトの URL を 先 頭 に 挿 入 するよう である この 現 象 は 汚 染 データを 使 った URL リダイレクトを 自 Web アプリケーション 内 に 限 定 できる ということである クッキー 情 報 の HTTP ヘッダでは 入 力 データを で 囲 むことが 図 3.5-2で 確 認 できる また は で エ スケープするようであるが エスケープ 文 字 はエスケープしな くてもいいようである 21
3.6 PHP5.2.0 の 場 合 PHP での HTTP ヘッダ 操 作 は 以 下 の 関 数 がよく 使 われるだろう 関 数 名 header( Location: << 入 力 データ>> ) setcookie setrawcookie header 操 作 内 容 Web ページのリダイレクト 要 求 クッキー 情 報 の 送 信 任 意 ヘッダの 追 加 リダイレクトには header() 関 数 を 使 って Location ヘッダを 作 成 するという 方 法 を 用 いる setrawcookie() 関 数 は URL エンコードしないという 点 で setcookie() 関 数 と 同 一 であるとマニ ュアルには 記 載 されている これらの 関 数 に 汚 染 データが 渡 るようなテストプログラム( 図 3.6-1)を 作 成 し Netcat を 使 ってど のような HTTP レスポンスが 返 るかを 観 察 した MS-WindowsServer2003 SP1( 日 本 語 版 ) 上 の PHP5.2.0 を 実 験 環 境 として 使 用 した <? $str =$_REQUEST["inputData"]; setcookie('cookiename', $str, time()+ 60); setrawcookie('rawcookiename', $str, time()+ 60); header("myheader: $str");?> 図 3.6-1 : PHP のヘッダ 送 信 関 数 の 実 験 プログラム 22
図 3.6-2 : 図 3.6-1の 結 果 クッキーへの 出 力 は URL エンコードされている(setcookie) setrawcookie() 関 数 ではエラーになる 図 3.6-3 : 図 3.6-1の 結 果 header() 関 数 に 改 行 コードを 与 えるとエラーになる 結 果 は 図 3.6-2~ 図 3.6-3のように setcookie() 関 数 では URL エンコードされ またそれ 以 外 の setrawcookie() 関 数 header() 関 数 では エラーとなることが 確 認 された よって PHP で 上 記 の 関 数 を 使 う 場 合 は HTTP ヘッダ インジェクションに 気 を 使 わずにコー ディングを 行 うことができる 23
蛇 足 : setrawcookie() 関 数 header() 関 数 に 改 行 コードを 与 えることでエラーとなる エラーにならないようにするには PHP プログラム 中 で 改 行 コードを 事 前 に URL エンコ ードするなど PHP プログラマが 明 示 的 に 処 理 することで 対 処 する 必 要 がある setcookie() 関 数 は 改 行 コードだけではなく クッキー 情 報 のプロパティのデリミタである ;(セミコロン) も URL エンコードされることが 確 認 できる 24
3.7 AzaraC0.3.0 の 場 合 AzaraC は C++ 用 の CGI テンプレートである これについても 調 査 してみた AzaraC では クラス azarac::httpresponse のメソッドとして 以 下 が 提 供 されている メソッド 名 操 作 内 容 addheader(キー 名, 値 ) 任 意 ヘッダの 追 加 setheader (キー 名, 値 ) 任 意 ヘッダの 上 書 き addcookie(クッキークラス) クッキー 情 報 の 送 信 クッキークラスとは azarac::cookie クラスのインスタンスを 指 定 する これらの 関 数 がどのような HTTP ヘッダを 送 信 するかを 以 下 で 確 認 してみた 利 用 したソフトウェアは RedHat7.3 g++ 2.96 AzaraC 0.3.0 である #include <iostream> #include "azarac.h" using namespaceazarac; intmain(){ if (display("./headertest.tpl")<0)cout<what(); } 図 3.7-1 : headertest.cpp (ロジック 部 の C++ ソース) <%@page Content-Type="text/html;" %> <% response.addheader("abc","xyz"); %> <% response.setheader("abc","lmn r nstu");%> <% response.addheader("xyz","abc r nlmn");%> <% response.addheader("test","end");%> <% Cokie new_cookie("mycokie","atai;crlf r nva=lue"); response.adcokie(new_cookie); response.adheader("zzz","last"); %> <html><body>helo,world!</body></html> 図 3.7-2 : headertest.tpl (デザイン 部 のテンプレート) 25
Set-Cokie: mycookie=atai %3BCRLF%0D%0Ava%3Dlue; Content-Type: text/html; abc: lmn stu test: end xyz: abc lmn zzz: last <html><body>helo,world!</body></html> 図 3.7-3 : 図 3.7-1と 図 3.7-2を g++で-lazarac オプションでコンパイルした 実 行 ファイルを 実 行 結 果 Cookie に 関 しては URL エンコードされているが setheader()/addheader()メソッドで 指 定 した 部 分 は 改 行 コードがそのままである 結 果 は 図 3.7-3のように addheader() / setheader()メソッド 関 数 共 に 関 数 内 部 で 改 行 コードの サニタイズ 処 理 が 行 われていないことが 確 認 された しかしながら Cookie に 関 しては URL エンコードが 行 なわれていることが 確 認 できる よって AzaraC の addheader()/setheader()メソッドを 使 う 場 合 アプリケーション プログラ マが 改 行 コードのサニタイズ 処 理 をしたうえで 呼 び 出 す 必 要 がある 26
4 執 筆 者 など 27
4.1 本 文 書 の 免 責 事 項 本 文 書 に 記 述 されてる 情 報 の 利 用 は 読 者 の 責 任 に 帰 するものとする 本 文 書 で 行 った 実 験 は 執 筆 者 の 実 験 環 境 で 確 認 したものである モジュールの 細 かいバージョ ンなどの 状 況 によっては 現 象 が 異 なる 可 能 性 がある 4.2 執 筆 者 active@window.goukaku.com 4.3 更 新 履 歴 最 初 のバージョン : 2007 年 03 月 05 日 ver1.1 : 2007 年 03 月 30 日 3.2, 3.2.1, 3.2.2 を 追 加 した ver1.2 : 2007 年 10 月 30 日 3.7 を 追 加 した 4.4 本 文 書 の 最 新 バージョン http://rocketeer.dip.jp/secprog/index.htm 28
4.5 HTTP ヘッダ 名 本 文 書 では 除 外 しているが HTTP ヘッダ 名 に 汚 染 データを 割 り 当 てる 場 合 は ヘッダ 名 とヘッ ダ 値 のデリミタが :(コロン) である そのような 場 面 では :(コロン) のサニタイズ 処 理 が 必 要 である また クッキー 情 報 では クッキー 名 とクッキーの 値 が =(イコール) で 区 切 られている クッ キー 名 に 汚 染 データが 入 るような 場 合 は =(イコール) がどのように 処 理 されるかシステム 開 発 前 に 事 前 に 観 察 しておく 必 要 がある 以 上 29