KEY값을 얻는 우회방법을 찾아 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.txt의 flag값을 읽어서 md5 암호화를 통해 KEY변수에 저장
guest문자열을 md5 암호화를 통해 guest_key에 저장
필터링 존재
key,cmd_input을 받아서 if문에 따라 결과 도출
- IF 문
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('/')
key값에 따라 FLAG값을 얻거나 guest로 진입하거나 이상한 값일 경우 redirect된다.
하지만 key값 입력 없이 위 if문에서 cmd 명령 전송이나, KEY값을 입력 둘중 하나만 만족하고 , 필터링에만 걸리지 않는다면 아래의 try문으로 진입할 수 있다.
try문에서는 timeout예외처리에서 KEY값을 얻을 수 있다. 따라서 try문에 진입후 timeout 조건 5초를 넘긴다면 KEY값을 얻을 수 있다.
웹상에서 직접적으로 cmd_input값을 전달할 수 없기 때문에 TRY문으로 먼저 진입하기 위해
Burp Suite를 통해 cmd_input값을 전달한다. 이때 timeout에 진입하기 위해서 cmd_input의 값은 sleep 6명령을 전송한다
위와 같이 전송한다면 Timeout! Your key: {KEY} 를 통해 KEY값을 얻을 수 있는데 처음 화면에서 KEY값을 입력하면 FLAG값을 얻을 수 있다.