webhacking => Plz Solveme 

 

please_solve_me.zip
0.00MB

 

위 파일을 다운받고 run.py 라는 파일의 소스코드를 보면 GET 방식으로 exp 라는 변수의 값을 받게 된다.

 

# flag in /flag
from flask import Flask, render_template, request, session, redirect, url_for
from multiprocessing import Process
import re
import time
import shutil
import tempfile

app = Flask(__name__)

FLAG = 'flag is HCAMP{flag in real server, this is not flag}'

@app.route('/', methods=['GET'])
def main():
	exp = request.args.get('exp')
	if exp is None:
		return 'read source'
	rm_list =  ['system', 'import', 'os', 'exec', 'sys', '__', 'read', 'open', 'flag', 'FLAG']
	for rm in rm_list:
		if rm in exp:
			return 'No Hack'
	res = ''
	try:
		res = str(eval(exp))
	except:
		res = 'error'
	return exp + ' => ' + res

app.run(host='0.0.0.0', port=2222, threaded=True)#, debug=True)

 

24번줄에 exp 값을 eval 함수로 실행을 하는데, 18번줄에서 몇몇의 문자열을 필터링하고 있다.

이 문제의 최종 목표는 11번줄에 있는 FLAG 라는 변수의 값을 출력 시키는 것이다.

일단 GET 방식으로 ?exp=rm_list 라고 입력을 하면 다음과 같이 rm_list 변수에 들어있는 값들이 출력 되는 것을 볼 수 있다.

 

 

그렇다면 FLAG 라고 GET 방식으로 보내면 FLAG 값을 볼 수 있지만, 필터링을 하고 있다.

우회하는 방법은 많지만 python 에서 문자열을 더하는 방법은 “FL”+”AG” 이라고 GET으로 보내면 eval() 함수에 의해 문자들이 더해져서 FLAG 라는 단어가 완성이 된다.
(+는 %2B로 넘겨야함)

 

 

하지만 위 방법은 eval 함수를 이용해 문자들끼리 더한 뒤 출력 값인 FLAG 라는 단어를 출력했다.

FLAG 라는 필터를 우회 했지만 변수 값을 얻지 못했으니, 여기서 한번더 생각해보면!

필터 리스트에는 eval 함수를 필터링 하지 않고 있다.

즉, “FL”+”AG” 에서 eval( “FL”+”AG”) 로 GET으로 넘기면 된다. 총 두개의 eval () 함수가 사용되는데, 첫번째 eval() 함수는 문자들끼리 더해주어 FLAG 라는 단어를 완성 시키고, 기존 소스코드에 있던 eval() 함수를 통해 FLAG 라는 변수 값을 출력하게 된다.

?exp=eval(%27FL%27%2B%27AG%27)

 

 

 

HCAMP{please_solve_laeasy_judge!!}