문제화면이다.
키를 찾아 FLAG를 받는 느낌이다.
뭐 아무것도 없으니 코드를 한번 봐야겠다.
#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template, redirect, url_for
import string
import os
import hashlib
app = Flask(__name__)
try:
FLAG = open("./flag.txt", "r").read()
except:
FLAG = "[**FLAG**]"
KEY = hashlib.md5(FLAG.encode()).hexdigest()
guest_key = hashlib.md5(b"guest").hexdigest()
# filtering
def filter_cmd(cmd):
alphabet = list(string.ascii_lowercase)
alphabet.extend([' '])
num = '0123456789'
alphabet.extend(num)
command_list = ['flag','cat','chmod','head','tail','less','awk','more','grep']
for c in command_list:
if c in cmd:
return True
for c in cmd:
if c not in alphabet:
return True
@app.route('/', methods=['GET', 'POST'])
def index():
# GET request
return render_template('index.html')
@app.route('/flag', methods=['POST'])
def flag():
# POST request
if request.method == 'POST':
key = request.form.get('key', '')
cmd = request.form.get('cmd_input', '')
if cmd == '' and key == KEY:
return render_template('flag.html', txt=FLAG)
elif cmd == '' and key == guest_key:
return render_template('guest.html', txt=f"guest key: {guest_key}")
if cmd != '' or key == KEY:
if not filter_cmd(cmd):
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
except subprocess.CalledProcessError:
return render_template('flag.html', txt="Error!")
return render_template('flag.html')
else:
return redirect('/')
else:
return render_template('flag.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)
필터링이 존재한다 리눅스 명령어 파일을 읽어 들이는 명령어이다.
flag 함수 소스코드만 봤을 때는 POST로 요청처리를 key, cmd_input 필드의 값을 가져오는 거 같다.
key는 그대로 가져가지만 cmd_input 은 cmd로 가져가는 거 같다.
cmd 가 비어 있고 key 가 KEY와 일치할 때는 flag를 보여주는 거 같다.
그러면 키가 어디서 나오는지 확인을 해보면...
if cmd != '' or key == KEY:
if not filter_cmd(cmd):
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
except subprocess.CalledProcessError:
return render_template('flag.html', txt="Error!")
return render_template('flag.html')
else:
return redirect('/')
else:
return render_template('flag.html')
이 부분에서 나온다 일단은 /bin/sh 쉘을 사용하는 거 보니 명령어를 따로 보내는 문제인 거 같다.
명령어 실행이 타임아웃이 된다면 KEY를 호출해 준다 (왜지?)
여하튼 그러면 타임아웃을 먼저 시켜보도록 하자
명령어를 사용하기 위해서는 아까 본 필터링을 주의하면서 cmd_input을 보내보도록 하자
or이니 cmd 만 입력해도 되는 거 같다.
원래는 key 가 있지만 명령어를 보내야 하기에 cmd_input <- cmd를 통해서 ls 명령어를 보내보자
화면에 admin이라 뜨고 ls를 Submit 해봤는데 친절히 보여준다 cat을 사용했으면 바로 flag를 읽을 수 있었겠지만
현재 필터링에 의해 막힌 상태이다.
그럼 이제 아까 봤듯이 타임아웃을 실행시키면 key 값을 알려준다고 하니 한번 해보자
몇 초 잠재우니까 key를 뱉어낸다.
이제 다시 dream 계정으로 가서 확인해 보면...
admin으로 로그인되면서 플래그 값이 나온다.
'DreamHack > CTF' 카테고리의 다른 글
(CTF 출제) amocafe (2) | 2024.09.05 |
---|---|
(CTF 출제) Whis-is-my-ip (0) | 2024.09.04 |
(CTF 출제) Random-Test (0) | 2024.09.04 |
(CTF출제) mongoboard (1) | 2024.09.04 |
(CTF출제) Type c-j (0) | 2024.09.03 |