Kodokon kodokon.com

HTML側のセキュリティ: XSS、sandbox、noopener、CSP

マークアップに固有のXSSベクトルを特定し、HTMLのネイティブな防御手段(sandbox、noopener、Content Security Policy)を展開します。

11 分 · 3 問

このレッスンを Kodokon で開く

エスケープのコンテキストがすべての違いを生みます。テキストノードでは無害な値が、属性の中では実行可能になります。引用符なしの属性は最悪のケースです。注入されたデータ中のたった1つのスペースが、たとえばonmouseoverハンドラーのような新しい属性を作り出すのに十分だからです。適切に引用符で囲まれていても、値は機微なシンクの中では危険なままです。hrefsrcjavascript:スキームを受け入れ、formactionはフォームの送信先を乗っ取り、srcdocはデコードされるとそのエンティティをHTMLとして解釈します。

HTML
<!-- userName = x onmouseover=alert(1) -->
<img src="avatar.png" alt=x onmouseover=alert(1)>
<!-- The unquoted attribute lets a handler in -->
引用符なしの属性の中でエスケープされていないデータはコードになります。

iframeのsandbox属性はすべての特権を剥奪し、その後あなたが一つずつそれらを付与し直します。allow-scriptsallow-formsallow-popupsなど。allow-same-originがなければ、埋め込まれたドキュメントは不透明なオリジンを受け取ります。クッキーもストレージも親DOMへのアクセスもなく、たとえそれがあなた自身のドメインから配信されていてもです。

HTML
<iframe
  src="https://widget.example.com"
  sandbox="allow-scripts allow-forms"
  referrerpolicy="no-referrer">
</iframe>
スクリプトを実行できるが、不透明なオリジンに閉じ込められたサードパーティのウィジェット。

target=_blankリンクは歴史的に、開かれたページにあなたのタブへのwindow.opener参照を与えていました。それはあなたのページをフィッシングのクローンにリダイレクトできました。タブナビングとして知られる攻撃です。現代のブラウザは今ではtarget=_blankに暗黙的にnoopenerを適用しますが、それを明示的に書き出すことは、JavaScriptのwindow.openのために、そして意図を文書化するために依然として不可欠です。Refererヘッダーも抑制するにはnoreferrerを追加しましょう。

HTML
<a href="https://external.example"
   target="_blank"
   rel="noopener noreferrer">
  View the external resource
</a>
開かれたページはwindow.opener === nullを受け取ります。

Content Security Policyは実行可能コードのソースを制限し、注入が成功した場合でさえ、ほとんどのXSSを無力化します。<meta http-equiv>タグを通じて宣言されますが、それでも盲点があります。frame-ancestorsreport-urisandboxディレクティブはそこでは無視され、HTTPヘッダーを必要とします。ドメインの許可リストよりも、レスポンスごとに再生成されるnonceを優先しましょう。許可リストはいずれにせよstrict-dynamicディレクティブが時代遅れにします。

HTML
<meta http-equiv="Content-Security-Policy"
      content="default-src 'self';
               script-src 'self' 'nonce-r4nd0m'">
サーバーのnonceを持つスクリプトだけが実行されます。

理解度チェック

このレッスンの要点をしっかり覚えているか確認しましょう。

  1. 同一オリジンのiframeでallow-scriptsallow-same-originを組み合わせると、なぜサンドボックスが無効になるのですか?
    • 埋め込まれたドキュメントは、スクリプト実行可能で隔離もされていないため、親DOMに到達してsandbox属性を自身で削除できる
    • この2つのトークンは互換性がなく、ブラウザは属性全体を無視する
    • allow-same-originが自動的に他のすべてのトークンを無効化する
  2. rel=noopenerはどの攻撃から保護しますか?
    • 開かれたページによるセッションクッキーの窃取
    • 開かれたページへのスクリプト注入
    • タブナビング: 開かれたページがwindow.openerを使ってあなたのタブをフィッシングサイトにリダイレクトする
  3. CSPが<meta http-equiv>を通じて宣言されたとき、どのディレクティブが無視されますか?
    • script-src
    • frame-ancestors
    • default-src
    • img-src