CTF Reviewed & Writeups/WACON CTF

2022 Wacon CTF 본선 복기

반응형
SMALL

2022 Wacon CTF 본선 참가 후기

Wacon 대회장 티오리(Theori) 박세준 대표님과 사진! (블로그 게시 허락 받았습니다.)

이번 2022년도 7월 15일 ~ 7월 16일 까지 개최된 Wacon CTF 본선을 참가하게 되었습니다.

본선은 서울 더케이호텔 3층 거문고홀에서 약 36시간동안 진행되었는데, 국내 최대 규모로 열린 CTF를 오프라인으로 참가하니 굉장히 안쪽도 웅장하고 여러가지 이벤트도 많이 진행되었던 것 같습니다.

청소년부 부터 성인부까지 굉장히 해킹씬에서 유명하신분들이 이번 Wacon 대회에서 전부 모이셔서 나름대로 많은 분들을 새롭게 만나뵙고 제가 현재 소속되어 있는 TeamH4C 청소년 팀원분들을 처음 만나게 되어서 굉장히 재밌고 인상깊었습니다.

또한 제가 평소부터 굉장히 존경하고 국내 최고 수준급의 화이트 해커시자 현 티오리(https://theori.io/) 대표님이신 박세준 대표님과 사진을 찍을 수 있어서 너무 영광스러웠던것 같습니다!!

코로나 19 바이러스로 인해 항상 온라인으로 진행되던 CTF에서 이렇게 오프라인으로 참가하니 온라인보다 훨씬 재밌고 유명한 분들을 많나뵈니 더 인상깊었던 것 같습니다.

문제 난이도를 생각해보면, 이번에 진행된 본선 CTF에서는 문제가 굉장히 어려웠습니다.. WEB 분야 문제를 한문제도 못풀고 한 14시간 가까이 잡고 있었던 문제도 풀지 못하였습니다.

이렇게 문제가 엄청 어려웠음에도 불구하고 수상을 하신 팀들은 진짜 저랑 어나더 레벨이란 생각도 많이들고, 제가 아직은 많이 부족하고 배울게 많은 학생임을 직감할 수 있었습니다.

이번 대회에서 긴장해서 그런지 실수도 많이하고 문제도 많이 못풀어서 아쉬운 마음도 많이 들지만 제가 풀었던 문제와 풀지 못했던 문제 총 2문제를 Writeup 작성해보면서 복기해보고 다음에 이와 같은 대회에 참가할때는 실력을 더 많이 쌓고 실수를 하지 않도록 노력해야겠다는 생각을 해볼 수 있었던 좋은 경험이었던것 같습니다.

Wacon 2022 MISC (query-master)

Writeup - Analysis

:eyes:

문제 설명에는 별다른 것이 없었습니다.

#!/usr/bin/python3
import random
import string
import subprocess

def randName():
    return ''.join([random.choice(string.hexdigits) for i in range(16)])

dbpath = f'/tmp/{randName()}.db'

query = input("Query >> ")

ban = ['.', 'lo', ';']

for x in ban:
    if x in query:
        print("Filtered..")
        exit()

proc = subprocess.Popen(["sqlite3", dbpath, query], stdout=subprocess.PIPE)
(out, err) = proc.communicate()

print(out.decode())

위는 문제 파일에서 app.py 코드를 가져온 것입니다.

dbpath, query, "sqlite3" 와 같은 변수를 보아 해당 문제는 sqlite3와 관련된 문제임을 짐작할 수 있었습니다.

문제에서는 ".", "lo", ";"와 같은 3가지 키워드를 필터링하고 있으며 만약 query 변수에 다음과 같은 키워드가 존재하면 "Filtered.."라는 문자열을 출력하고 프로그램을 종료하는것을 확인할 수 있습니다.

만약 필터링에 걸리지 않게 되면 subprocess 모듈 중 Popen 함수를 이용해 다음과 같이 명령어를 커멘드에 입력하고 실행결과를 print 함수를 이용해 출력해줍니다.

Writeup - Vulnerability

여기서는 결국 sqlite3를 이용해서 커멘드에 명령을 입력받고 실행하는 결과를 알려주기 때문에 저는 아래와 같이 2가지 취약점을 예상해볼 수 있었습니다.

1. Sql injection
2. Command injection

Command injection을 예상해본 이유는 현재 코드를 보면 일반적인 sql injection 문제와는 다른점이 존재합니다.

일반적인 sql injection 문제라면 sqlite3 내장 함수를 이용해 입력을 받고 쿼리를 실행하는 작업이 있겠지만 해당 문제에서는 subprocess 모듈을 이용해서 sqlite3 명령어를 실행시키니 뭔가 이를 우회하고 command injection을 일으실 수도 있겠다라는 생각이 들었습니다. (Popen 함수에서 입력값만 조작한다면 커멘드 명령어를 실행시킬수도 있기 때문)

즉, 이와 같은 취약점을 생각하다보니 자연스럽게 Popen 함수가 어떻게 인자가 들어가는지 확인하고 싶었습니다.

subprocess Popen 함수의 파라미터는 아래와 같습니다.

class subprocess.Popen(args, bufsize=-1, excutable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=None, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restoreflags=0, restore_signals=True, start_new_session=False, pass_fds=() )

여기서 저는 args 파라미터를 유심히 살펴보았습니다, 조금 더 살펴보니 아래와 같은 코드를 발견 할 수 있었습니다.

import subprocess
proc = subprocess.Popen(
    ['echo', 'Hello world'],
    stdout=subprocess.PIPE
    )
out, err = proc.communicate()
print(out)
print(out.decode('utf-8'))

# result
# b'Hello world\n'
# Hello world

args 값에 ['echo', 'Hello world']와 같이 값을 넣으니 출력이 Hello world가 나온것을 보고 배열의 인덱스 순서로 명령어가 합쳐져서 실행됨을 알 수 있었습니다.

['echo', 'Hello world'] == 'echo Hello world'

이를 이용해서 문제에서 Popen 함수는 다음과 같이 동작됨을 예측할 수 있었습니다.

dbpath = '/tmp/test.db'
query = 'select 1'

proc = subprocess.Popen(["sqlite3", dbpath, query], stdout=subprocess.PIPE)

# command : sqlite3 /tmp/test.db select 1
# result : 1

즉, 이것을 통해 sqlite3 쿼리문이 이와 같은 형식으로 처리될 수도 있다는 사실을 알게되었고, 문제에서는 flag 값을 sqlite3 데이터베이스에 따로 저장해놓은것이 아닌 flag.txt 파일로 저장된것을 보아 sqlite3에서 파일을 읽는 함수를 찾아서 필터링을 우회하고 쿼리문을 실행하면 flag를 읽을 수 있을것 같았습니다.

Writeup - Payload

저는 위와 같은 사실을 모두 알아낸 후 sqlite3에서 파일을 읽을 수 있는 함수를 찾아보기 시작했습니다.

하지만 sqlite3 모듈은 내장함수도 그렇고 구글링을 해봐도 자료가 많지가 않았습니다.

한 3시간정도를 계속해서 구글링을 해보다보니 readfile 이라는 함수를 찾아낼 수 있었습니다.

readfile : sqlite3 내에서 파일을 읽는 함수

ex : select readfile('test.txt'); // test.txt = hello world
result : hello world

해당 함수를 찾았으므로 아래와 같은 payload를 만들어 낼 수 있었습니다.

select readfile('flag.txt')

하지만 문제에서는 "." 키워드를 필터링하고 있기 때문에 위 payload를 바로 실행하면 필터링에 걸리게 되어서 flag.txt 파일을 읽을 수 없었습니다.

여기서 저는 flag.txt라는 문자열을 16진수로 변환하는 방법을 생각해냈습니다.

하지만 sqlite3에서 16진수를 ascii로 변환하는 함수가 무엇인지 몰라서 또 한참을 구글링했습니다.

구글링 결과, 따옴표 앞에 x라는 문자를 붙여서 실행하게 되면 자동으로 16진수가 ascii로 변환되는것을 알아낼 수 있었습니다.

ex : select x'666C61672E747874'
result : flag.txt

이제 이를 모두 조합하여 쿼리문을 실행하면 flag를 얻어낼 수 있습니다.

Writeup - Exploit

payload : select readfile(x'666C61672E747874')

위 payload를 입력값에 입력하고 실행해보면 flag가 출력됩니다.

FLAG : WACon{zz_lol_you_read_documentation}

Wacon 2022 WEB (holes)

Writeup - Analysis

holes... holes everywhere... :((((( Flag format is flag{}

해당 문제는 제가 대회장에서 약 14시간 가까이 잡고 있었다가 결국 풀지 못하였던 문제입니다.

집에 와서 writeup을 보고 결국 풀긴하였지만 그래도 가장 인상깊었던 문제여서 writeup을 작성해보겠습니다.

일단, 해당 문제에서는 cli 서비스와 http 서비스 2가지가 돌아가고 있습니다.

먼저 http 서버인 app.py 서버파일부터 확인해보겠습니다.

#!/usr/bin/env python3
import os
import hashlib
import re
from flask import Flask,request,send_from_directory

def getUserFolderDir(userUUID):
    r = os.path.dirname(os.path.abspath(__file__))
    r += '/files/'+hashlib.md5(userUUID.encode()).hexdigest()
    return r
    
app = Flask(__name__)

@app.route('/', defaults={'path': ''})
@app.route('/<path:path>')
def index(path):
	pathes = path.split('/')
	userUUID = pathes[0]
	del pathes[0]
	path = '/'.join(pathes)

	if(not re.match('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',userUUID)):
		return "Incorrect UUID",400,{'Content-Type': 'text/plain;charset=utf-8'}

	if('..' in path):
		return "Dangerous path",400,{'Content-Type': 'text/plain;charset=utf-8'}

	if(path == ''):
		path = 'index.html'

	userDir = getUserFolderDir(userUUID)+'/'+path
	if(not os.path.exists(userDir)):
		return 'Folder not found :? Create one with the management console',404,{'Content-Type': 'text/plain;charset=utf-8'}

	try:
		with open(userDir) as f:
			content = f.read()
			if('flag' in content):
				return 'ᕙ(^▿^-ᕙ)',400,{'Content-Type': 'text/plain;charset=utf-8'}
			return content,200,{'Content-Type':'text/html'} 
	except:
		return 'Smth bad happened',500

if(__name__ == '__main__'):
	app.run(host='0.0.0.0',port=8000)

간단하게 요약하자면, /uuid/filename으로 라우터를 받고 uuid와 일치하는 폴더에서 filename과 일치하는 파일을 가져와서 읽습니다, 만약 여기서 파일 내용에 'flag'라는 문자가 존재할 시, 열람할 수 없다는 뜻의 문자를 출력하고, 만약 아니라면 읽은 파일 내용을 화면상으로 출력해줍니다.

웹쪽에서 하는 역할은 정리하면 uuid와 일치하는 폴더에서 일치하는 파일명을 가지고 읽어서 웹 페이지로 출력해주는 역할입니다.

이번에는 cli.py 파일을 확인해보겠습니다.

#!/usr/bin/env python3
import re
import os
import base64
import hashlib
import uuid
from jinja2 import Template

def checkFilename(s):
    if('/' in s or not 5 < len(s) < 30):
        raise 'Bad filename'

def printMenu():
    print('1. Create')
    print('2. Rename')
    print('3. List')
    print('4. Compile')
    print('5. Flag')
    print('6. Exit')

def handleCreateFile():
    filename = input('Filename > ')
    fileContent = base64.b64decode(input('Base64 encoded content > '))

    checkFilename(filename)
    if(len(fileContent) > 500):
        raise 'too large'

    with open('./'+filename,'wb') as f:
        f.write(fileContent)

    print('Created the file!')

def handleRenameFile():
    sFilename = input('From filename > ')
    tFilename = input('To filename > ')
    
    checkFilename(sFilename)
    checkFilename(tFilename)

    os.rename(sFilename,tFilename)
    print('Renamed the file!')

def handleCompile():
    tFilename = input('Enter template filename > ')
    oFilename = input('Enter output filename > ')
    checkFilename(tFilename)
    checkFilename(oFilename)

    with open('./'+tFilename) as f:
        fileContent = f.read()
        if('(' in fileContent or '.' in fileContent):
            raise 'Ahh not allowed sorry!'
        t = Template(fileContent).render()
        with open(oFilename,'w') as ff:
            ff.write(t)
    print('Template compiled!')

def handleFlag():
    with open('./flag.txt','w') as f:
        f.write(open('/flag').read())
    print('Wrote the flag file!')

def handleListdir():
    print('\n'.join(os.listdir()))


def getUserFolderDir(userUUID):
    r = os.path.dirname(os.path.abspath(__file__))
    r += '/files/'+hashlib.md5(userUUID.encode()).hexdigest()
    return r
    
if(__name__ == '__main__'):
    inp = input('Enter your uuid or ENTER to create a new environment: ')
    userUUID = None

    if(len(inp) == 0):
        userUUID = uuid.uuid4().__str__()
        print(f'Your UUID is {userUUID}')
    else:
        if(not re.match('^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$',inp)):
            print('Incorrect UUID')
            exit(0)
        userUUID = inp

    cwdDir = getUserFolderDir(userUUID)
    if(not os.path.exists(cwdDir)):
        os.makedirs(cwdDir)

    os.chdir(cwdDir)

    handlers = [handleCreateFile,handleRenameFile,handleListdir,handleCompile,handleFlag,exit]
    while(1):
        printMenu()
        handlers[int(input('Input Selection\n> '))-1]()

여기서도 마찬가지로 정리하면 총 5가지의 역할을 수행합니다.

먼저, 처음 cli 서비스에 접속하게 되면 uuid를 생성합니다, 생성한 uuid 명과 같은 폴더를 만들고 해당 폴더내에서 작업을 시작합니다. (접속자별로 파일이 중복되는것을 방지하기 위함)

첫번째 역할은 파일을 생성하는 역할입니다, 파일명을 입력받고 해당 파일안에 입력받은 내용을 씁니다.

여기서 만약 파일 내용의 길이가 500자를 초과하면 파일을 생성하지 않습니다.

1. Create
File name : test.txt
File content : aGVsbG8gd29ybGQ= (base64 encoded)

##### test.txt #####
hello world

두번째 역할은 파일명을 변경하는 역할입니다.

변경 대상 파일명과 변경할 파일명을 입력하면 파일명에 "/" 가 들어가는지 파일명의 길이가 5글자 이내거나 30글자 초과인지 검사를 거친후 파일명을 변경합니다.

2. Rename
File name : test.txt
Change File name : test2.html

##### test2.html #####
hello world

새번째 역할은 목록역할입니다.

현재 폴더안에있는 모든 파일을 출력해줍니다.

3. List
test.txt
test2.html
flag.txt

네번째 기능은 컴파일기능입니다, 해당 역할은 먼저 대상 파일명과 출력 결과를 저장할 파일명을 입력받습니다.

그런다음 대상 파일명에 있는 파일 내용을 가져온 뒤 파일 내용에 "("와 "."가 들어가있는지 검사 후 jinja2 템플릿의 클래스인 Template 클래스를 이용해 해당 파일을 랜더링합니다.

그리고 출력된 결과를 아까 지정한 출력 결과를 저장할 파일명에 저장합니다.

4. Compile
##### test.html #####
{{ 7 * 7 }}

input file : test.html
out file : o.html

##### o.html #####
49

마지막 역할은 flag 값을 flag.txt에 입력하는 역할입니다.

5. Flag
##### flag.txt #####
flag{secret-flag}

Writeup - Vulnerbaility

cli 서비스에서는 먼저 하나의 취약점을 간단히 파악할 수 있습니다.

cli.py 파일에서 Compile 기능의 함수만 가져온 것 입니다. 

def handleCompile():
    tFilename = input('Enter template filename > ')
    oFilename = input('Enter output filename > ')
    checkFilename(tFilename)
    checkFilename(oFilename)

    with open('./'+tFilename) as f:
        fileContent = f.read()
        if('(' in fileContent or '.' in fileContent):
            raise 'Ahh not allowed sorry!'
        t = Template(fileContent).render()
        with open(oFilename,'w') as ff:
            ff.write(t)
    print('Template compiled!')

여기서 유심히 봐야할 것은 Template 클래스입니다, 보통 평균적으로 jinja2 템플릿은 flask에서 template_render와 같은 함수에서만 가능한 것으로 알고 있는데, 위와 같이 Template 클래스를 이용해서 랜더링하는 방식으로도 똑같이 jinja2 템플릿을 사용할 수 있습니다.

또한 파일명을 가지고 올때 확장자 검사가 따로 없고, 파일 내용을 검사할때도 "{", "}" 와 같은 키워드를 일체 필터링하지 않기 때문에 Compile 함수에서 SSTI 취약점이 발생하는 것을 알아볼 수 있습니다.

여기까지 보고 난 후 저는 아래와 같은 Exploit 시나리오를 생각했습니다.

1. cli 5번 기능을 사용해서 flag.txt 파일 생성 
2. SSTI를 이용해 python os 모듈을 호출한 후 system 명령어를 이용해서 "cat flag.txt" 명령어 실행
3. 커멘드에서 flag 값 확인가능 (os system 명령어는 출력결과를 따로 파일에 저장하는 것이 아닌 바로 커멘드를 이용해 실행이 가능하기 때문) 

하지만 문제는 2번에서 터졌습니다, python os 모듈을 불러오는 것 까지는 원활하게 수행되었지만 소괄호가 필터링되어 있기 때문에 아무리 시도를 해봐도 system 함수를 실행시킬 수 있는 방법이 떠오르지 않았습니다.

저는 이부분에서만 삽질을 한 6~8시간 정도를 하였습니다..

그 이후 너무 시도가 안되어서 두번째 Exploit 시나리오를 생각해봤습니다.

1. cli 5번 기능을 사용해서 flag.txt 파일 생성
2. SSTI를 이용해 flag.txt 파일 내용을 'flag' 문자가 없어지게 끔 할 수 있는 방법을 고안
3. flag.txt 파일명 다른 파일명으로 변경
4. 웹 서비스에서 다른 파일명으로 변경된 flag.txt 파일 실행해서 flag 읽기

하지만 사실상 2번 부분이 가능할리가 없었습니다..

결국 SSTI 부분에서 더 이상 진도를 못나가고 대회가 끝날때까지 풀지 못하였습니다.

Writeup을 확인해보니 python에서 Traceback Error를 이용하는것을 확인할 수 있었습니다.

##### python Traceback #####
Python에서 역추적은 특정 지점에서 코드에서 수행된 함수 호출을 포함하는 보고서입니다. 즉, 오류가 발생하면 역추적해야 합니다. 
코드에 예외가 발생할 때마다 트레이스백은 코드에서 무엇이 잘못되었는지에 대한 정보를 제공합니다. Python 트레이스백에는 코드에서 무엇이 잘못되었는지 찾는 데 도움이 되는 훌륭한 정보가 포함되어 있습니다. 
이러한 트레이스백은 다소 지루해 보일 수 있지만, 이를 분해하여 보여주려는 내용을 확인하면 매우 도움이 될 수 있습니다.

즉, 정리해보면 python에서 traceback Error는 오류가 발생할때마다 어디부분에서 오류가 발생하였는지 역추적을 해줍니다, 또한 코드에서 무엇이 잘못되었는지 여부도 확인이 가능하도록 해줍니다.

SSTI를 이용해 python에서 임의로 traceback 오류를 내보겠습니다.

{{ a[10] }}

위 코드는 현재 a라는 변수가 존재하지 않는 상황에서 a의 10번째 인덱스의 값을 접근하려고 하기 때문에 오류가 발생하게 됩니다.

해당 코드를 아래와 같은 시나리오로 실행해보겠습니다.

1. Create
##### test.html #####
{% set a = 10 %}
{{ a[10] }}

2. Compile
input : test.html
out : o.html

##### result #####
Traceback (most recent call last): File "/app/cli.py", line 95, in <module> handlers[int(input('Input Selection\n> '))-1]() File "/app/cli.py", line 54, in handleCompile t = Template(fileContent).render() File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 1301, in render self.environment.handle_exception() File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 936, in handle_exception raise rewrite_traceback_stack(source=source) File "<template>", line 1, in top-level template code File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 466, in getitem return obj[argument] jinja2.exceptions.UndefinedError: 'a' is undefined

예상대로 o.html에 실행결과가 저장되지 않고 오류가 발생하였습니다.

여기서 별다른 문제가 없어보이지만 한부분의 에러 내용이 약간 이상합니다.

"/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 936, in handle_exception raise rewrite_traceback_stack(source=source) File "<template>"

지금 확인해보면 File 이름이 "<template>"입니다. 기본적인 파일명이 아닙니다.

또한 위의 오류는 어디 라인에서 어떤 오류가 발생하는지 알려주고 있는데 지금 위 에러 메시지는 어디 라인인지도, 어떤 오류인지도 알려주지 않습니다.

뭔가 실제로 <template> 파일명의 파일이 실행된것만 같은 느낌이듭니다.

자세히 알아보기 위해 /usr/local/lib/python3.8/site-packages/jinja2/environment.py 파일을 살펴보았습니다.

source_hint = None
        try:
            if isinstance(source, str):
                source_hint = source
                source = self._parse(source, name, filename)
            source = self._generate(source, name, filename, defer_init=defer_init)
            if raw:
                return source
            if filename is None:
                filename = "<template>"
            return self._compile(source, filename)
        except TemplateSyntaxError:
            self.handle_exception(source=source_hint)

위와 같은 내용이 존재합니다.

여기서, filename이 None이라면 filename에 "<template>"을 저장하고 내부 compile 함수로 해당 파일명의 파일을 실행해버립니다.

만약 filename이 None이라면 다른 오류를 발생시켜야 정상이지만 python에서 "<template>"이라는 파일명은 존재하지 않을것이라 판단해 filename에 "<template>" 문자열을 저장하고 compile로 코드를 실행한 것 같습니다.

즉, traceback error가 발생할때, /usr/local/lib/python3.8/site-packages/jinja2/environment.py 파일에서 검사가 취약한 부분이 존재하여 "<tempalte>"이라는 파일명의 파일이 실행되버리는 취약점이 존재합니다.

Writeup - Payload

위의 analysis 파트에서 확인하셨다 싶이 cli 서비스에서는 rename이라는 역할이 존재합니다.

특정 파일명을 원하는 파일명으로 바꾸는 함수입니다.

여기서 Traceback 에러를 이용해 아래와 같은 Exploit 시나리오를 작성해볼 수 있습니다.

1. cli 5번 기능을 사용해서 flag.txt 파일 생성
2. flag.txt 파일명 <template>로 변경
3. SSTI traceback 에러가 발생하는 코드 주입
4. Compile을 이용해 traceback 오류를 발생시킴

현재 파일명을 변경해주는 rename 함수에서는 확장자 검사, "<", ">" 키워드 필터링 모두 진행하고 있지 않기 때문에 flag.txt 파일명이 <template>로 변경되게되면 traceback 에러가 발생되면서 <template> 파일명의 파일을 실행하기 때문에 flag 값이 출력될 수 있습니다.

Writeup - Exploit

5. Flag 
##### flag.txt #####
flag{secret-flag}

2. Rename
input filename : flag.txt
to filename : <template>

3. Create
##### ex.html #####
{{ a[10]  }}

4. Compile
input : ex.html
out : out.html

##### result #####
Traceback (most recent call last): File "/app/cli.py", line 95, in <module> handlers[int(input('Input Selection\n> '))-1]() File "/app/cli.py", line 54, in handleCompile t = Template(fileContent).render() File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 1208, in __new__ return env.from_string(source, template_class=cls) File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 1105, in from_string return cls.from_code(self, self.compile(source), gs, None) File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 768, in compile self.handle_exception(source=source_hint) File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 936, in handle_exception raise rewrite_traceback_stack(source=source) File "<unknown>", line 1, in template flag{this-time-i-didn't-use-envs-hopefully-no-unintendeds} jinja2.exceptions.TemplateSyntaxError: Encountered unknown tag 'a'.

성공적으로 Exploit이 되고 flag 값이 출력됩니다.

FLAG : flag{this-time-i-didn't-use-envs-hopefully-no-unintendeds}

최종 느낀점

Wacon 2022 본선에 참가하게 되면서 제 처음으로 본선에 출제된 문제를 풀어보게 되었는데, 문제 난이도가 굉장히 어려웠고, 제가 지금까지 경험하지 못한 유형의 문제가 나와서 나름대로 많이 당황스러웠던 것 같습니다.

비록 이번 Wacon 대회에서 1문제 밖에 제가 풀지 못했지만 다음 Wacon 대회가 열리게 된다면 그때는 제 부족한 부분을 이번 대회에서 파악하였으니 더 열심히 부족한 부분을 메꾸고 Web, Pwnable에 대한 지식을 더 많이 쌓은 다음 꼭 수상권에 드는 것을 목표로 열심히 공부하겠습니다!

반응형
LIST