[Dreamhack] BypassIF
1. Intro
Dreamhack 링크: https://dreamhack.io/wargame/challenges/1151
2. Code
2.1. /index
코드 접기/펼치기
<form action="/flag" method="POST">
<div class="row">
<div class="col-md-6 form-group">
<br/><input type="text" class="form-control" placeholder="your key" name="key" pattern="[A-Za-z0-9\s]{2,35}" required>
</div>
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
/flag페이지로key값을 POST 형식으로 요청한다.
2.2. /flag
코드 접기/펼치기
@app.route('/flag', methods=['POST'])
def flag():
# POST request
if request.method == 'POST':
# 파라미터 key, cmd_input를 받음
key = request.form.get('key', '')
cmd = request.form.get('cmd_input', '')
# cmd 값이 없고 key가 admin이면 flag 보여줌
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}")
# cmd 값이 있거나 key가 admin이면
if cmd != '' or key == KEY:
# filter에 안 걸렸으면
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'))
# timeout 에러 발생 시 admin 키를 보여줌
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')
key,cmd_input을 받아온다.cmd입력이 없을 때key를 비교해 admin, guest를 구분한다. admin이면 flag를 보여준다.cmd입력이 있거나key가 admin일 때filter_cmd(cmd)에 걸리지 않았다면- 쉘 스크립트를 실행한다.
- timeout(5초)일 경우 admin 키를 보여준다.
- 쉘 스크립트 에러 발생했을 경우 에러 메시지를 보여준다.
2.3. filter_cmd(cmd)
코드 접기/펼치기
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
- cmd에
flag,cat,chmod,head,tail,less,awk,more,grep가 있을 경우 → True - 알파벳 소문자, 공백, 숫자가 아닐 경우 → True
3. Vuln
- 불충분한 인증
- 조건문 로직 결함 - 타임아웃을 이용한 키 유출
4. Payload
guest의 md5 해시값을 넣어본다.

- request 요청에
cmd_input을 추가한다.- 기본 폼에는
key만 있지만, 백엔드 코드에서request.form.get('cmd_input', '')로 인자를 받기 때문에 POST 요청할 때cmd_input파라미터를 임의로 추가해준다.

- 기본 폼에는
ls를 입력한다.

sleep 6을 입력한다.subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)로 인해 명령어가 5초 이상 실행되면TimeoutExpired예외가 발생한다.- 예외 처리 구문에서
f'Timeout! Your key: {KEY}'를 반환한다. 즉,sleep 6를 통해 타임아웃을 유발해 admin key를 획득하는 것이다.

admin의 키를 입력한다.
- flag를 획득했다.

Comments