スポンサーリンク

バッチで,リファラを改ざんし,ユーザエージェントを改ざんし,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を使ってバイトデータを作る必要がある。