はまやんはまやんはまやん

hamayanhamayan's blog

.innerHTMLのサニタイジングをバイパスするテク

CTFtime.org / redpwnCTF 2020 / Viper
この問題の解説に出てきた「innerHTMLのサニタイジングをバイパスするテク」を覚書しておく。
ちゃんと試してないから動かんかったらごめん。
出典:CTFtime.org / redpwnCTF 2020 / Viper / Writeup

どういう場面の話か

こんなHTMLコードになってて、中身にインジェクションできるとする。

<p id="url">[injection]</p>

それで、javascriptコードで

fetch(document.getElementById("url").innerHTML)

となっているときに、

http://example.com/?id=admin&pass=pass

をインジェクションすれば、ちゃんとここにアクセスしてくれるように見える。
しかし、これはうまくいかない。以下のサニタイジング機能が走るからである。

.innerHTMLのサニタイジング

element.innerHTML - Web API | MDN
ここを見ると、&<>の文字を含むテキストの子ノードを持っている場合、 HTMLエンティティに変換しちゃうようで、
つまり、インジェクションしたURLの&がこれに引っかかって変換されるからうまくいかない。

バイパス方法

結論から言うと、

http://example.com/?dummy=<!--&id=admin&pass=pass#-->

とすれば解決できる。
コメントにすれば、コメント内部はその変換を逃れることができることができるみたい。
<!--<が逃れられてるのかは試してないので知らない)
こうすれば、&がそのままの状態でfetch関数に渡せる。
よーく眺めると、これで、もともと達成したかったことは実現できている。
一応以下に理解が進むようメモ書きしておく。

  • GETパラメタは以下のように解釈される
    • dummy=<!--
    • id=admin
    • pass=pass
  • passの後の#を使うことで末尾の-->を無視している
  • 最初の<!--はdummyキーを使って吸収している
  • これでhttp://example.com/に対してid,passパラメタを送ることは達成できている