バッチで,リファラを改ざんし,ユーザエージェントを改ざんし,POSTリクエストを自動発行しよう (HTTPリクエストヘッダを自由に生成)
Webアプリケーションのセキュリティチェックや自動テストを行なうために,
WebサーバやAPサーバに対して,「任意のHTTPリクエスト」を手軽に発行したい。
「任意のHTTPリクエスト」とは,例えば・・・
- リファラ(リンク元)改ざん
- ⇒画面遷移のロジックが不整合を起こさないか試験する
- ユーザエージェント(ブラウザ種別)改ざん
- ⇒携帯用のページとかがちゃんと表示されるか,実機を全く使わずに試験する
- POSTリクエスト自動発行,大量発行
- 簡易的な負荷試験
など,異常ルート寄りのもの。
こういった攻撃(というより,現実のネットワークで起こりうる事柄)に,
サーバが耐えられるかどうかを知っておきたい。
以下では,こういった「好き勝手なHTTPリクエスト」を手軽に発生させるために,
- (1)XmlHttpRequestを使う場合
- (2)IEオートメーションを使う場合
の2パターンを考える。
WSHのスクリプトなので,何もインストールする必要はない。
(1)XmlHttpRequestを使う場合
GETリクエストの場合:
get.js
var xhr = WScript.CreateObject("MSXML2.XMLHTTP"); // GETリクエストを準備 xhr.open("GET", "http://www.yahoo.co.jp/"); // ユーザエージェントを書き換える xhr.setRequestHeader( "User-Agent", "Mozilla/4.08 (F903iX;FOMA;C500;TB)" ); xhr.send(); while( true ) { WScript.Sleep(100); if( xhr.readystate == 4 ) { // HTMLを表示 WScript.Echo( xhr.getResponseHeader('Content-Type') ); WScript.Echo( xhr.status ); WScript.Echo( xhr.responseText ); WScript.Quit(); } }
POSTリクエストを送りたい場合:
post.js
var xhr = WScript.CreateObject("MSXML2.XMLHTTP"); // POSTリクエストを準備 xhr.open("POST", "サイトのURL"); xhr.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" ); // ユーザエージェントを書き換える xhr.setRequestHeader( "User-Agent", "hoge" ); // パラメータを準備 var params = "a=b&c=d"; // 送信 xhr.send( params ); while( true ) { WScript.Sleep(100); if( xhr.readystate == 4 ) { // HTMLを表示 WScript.Echo( xhr.responseText ); WScript.Quit(); } }
これをfor文でループし,その全リクエストに対して,サーバがresponse内で正常なステータスを返せるかどうかを試してみる。
というやり方がある。
(jMeter*1より手軽だろう。)
参考URL
WSHでXmlHttpRequestを使う:
コマンドプロンプトを,Webブラウザとして使おう (WSH・JScriptでXmlHttpRequest)
http://language-and-engineering.hatenablog.jp/entry/20100806/p1
AjaxでPOSTリクエスト:
XMLHttpRequestまとめ
http://archiva.jp/web/javascript/XNLH...
- POSTメソッドを使って送信する場合、必ずContent-Typeヘッダを設定
- req.setRequestHeader( "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" );
- 送信パラメータは必要ならencodeURIComponent()する
クエリストリングから情報が漏れる
http://www.ipa.go.jp/security/awarene...
- GET/POSTに関わらず,HTTP requestの送信パラメータのセットはクエリ・ストリングの形態をとる
- GETの場合はURLの末尾にクエリ文字列が来る
- POSTの場合はHTTPリクエストのボディにクエリ文字列が来る
UAを偽装する方法:
JavaScriptのXHRでUser-Agentを偽装するサンプル
http://f32.aaa.livedoor.jp/~azusa/?t=...
- xmlhttp.setRequestHeader("User-Agent","hoge 1.5.1");
ユーザーエージェント文字列の例
http://ja.wikipedia.org/wiki/%E3%83%A...
リファラを偽装する方法:
昔はできた。
IE で JScript を利用して外部コンテンツを取得する際に Referer ヘッダを変更することはできませんか?
http://cyclon.s11.xrea.com/mt/#000036
- "Referer:" のようにコロンをつけて指定すると Referer ヘッダとして、指定した値が送られます。これは IE のセキュリティホールのようです。したがってそのうち patch が出るかもしれません。
最近はセキュリティがきつくなり不可能。
XMLHttpRequestでRefererをセットする(エラーになる)
http://d.hatena.ne.jp/brazil/20080416...
- readyState == 1になってからsetRequestHeaderしているサンプル
Test that setRequestHeader cannot be used to alter security-sensitive headers.
http://www.browsertests.org/tests/Lay...
- CONSOLE MESSAGE: line 1: Refused to set unsafe header "REFERER"
そういうわけで,XmlHttpRequestを使うとリファラが自由に設定できず,限界がある。
(2)IEオートメーションを使う場合
IEを使う方法なら
- リファラ改ざん
- UA改ざん
- POSTリクエスト自動発行
のいずれも可能。
ie.js
// ----- 設定項目 ----- // リクエスト送信対象のURL var target_url = "http://d.hatena.ne.jp/language_and_engineering/"; // POST用のクエリ文字列 var original_post_parameters = "a=b&c=d"; // リクエストヘッダのカスタマイズ(リファラを改ざん) var request_header = "Referer: http://www.google.co.jp/search?hl=ja&source=hp&q=WSH&aq=f&aqi=g6g-r4&aql=&oq=&gs_rfai="; // リクエストヘッダのカスタマイズ(ユーザエージェントを改ざん) request_header += "\r\nUser-Agent: hoge"; // ----- POSTリクエストのパラメータを準備 ----- // バイトデータに変換 var ado = WScript.CreateObject("ADODB.Stream"); ado.Open(); ado.Charset = "Shift_JIS"; ado.WriteText( original_post_parameters ); ado.Position = 0; ado.Type = 1; var byte_post_parameters = ado.Read(-1); ado.Close(); // ----- リクエスト発行 ----- // IEを起動 var ie = WScript.CreateObject("InternetExplorer.Application") ie.Visible = true; // POSTリクエストを発行 var optional_flags = null; var target_frame_name = null; ie.Navigate( target_url, optional_flags, target_frame_name, byte_post_parameters, request_header );
はてなダイアリーは,Googleの検索結果画面から飛んできた場合は,該当する検索キーワードが,日記上部の検索ボックスに表示される。
このコードで,確かにリファラを「偽装」できていることがわかるだろう。
参考URL
IEオートメーションの基礎:
JScript / VBScript (WSH)で,IEを自動操作しよう
http://language-and-engineering.hatenablog.jp/entry/20090713/p1
header書き換え:
Navigate Method
http://msdn.microsoft.com/en-us/libra...
- object.Navigate( url As String, [Flags As Variant,] [TargetFrameName As Variant,] [PostData As Variant,] [Headers As Variant])
IEオートメーション時に,リファラを偽造する
http://nossie.blog71.fc2.com/blog-ent...
- WSHからXmlHttpRequestを使う場合はReferrerを変えられないのでIEを立ち上げる
HSP3掲示板 ブラウザがサーバーに送る情報を変更したい
http://hsp.tv/play/pforum.php?mode=pa...
- HTTP headersを複数追加するときには,CRLFの改行区切り
POSTデータの生成:
VBScript - IE.Navigate does not POST
http://social.msdn.microsoft.com/Foru...
- You have to convert your vPOST to a byte array.
http://www.roy.hi-ho.ne.jp/mutaguchi/...
- ただの配列としてPOSTデータを作成すると,VarType(postdat)が、8209(=vbArray Or vbByte)ではなく、8204(=vbArray Or vbVariant)になってしまう。
- データ型を間違えた場合には,GET扱いになってしまう。
- なので,BASP21か,またはADODBを使ってバイトデータを作る必要がある。