관리 메뉴

Bull

[Dreamhack] simple_sqli_chatgpt WriteUp 본문

Wargame/Dreamhack

[Dreamhack] simple_sqli_chatgpt WriteUp

Bull_ 2023. 3. 21. 00:08

문제 파악

주어진 문제의 홈페이지를 들어가보니 userlevel을 입력 받을 수 있는 홈페이지가 있다.

문제에서 챗지피티와 함께 풀어보라고 힌트(?)가 주어진다.

 

파일에서 로그인 입력을 받는 라우팅 부분은 다음과 같다.

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
        return render_template('login.html')
    else:
        userlevel = request.form.get('userlevel')
        res = query_db(f"select * from users where userlevel='{userlevel}'")
        if res:
            userid = res[0]
            userlevel = res[2]
            print(userid, userlevel)
            if userid == 'admin' and userlevel == 0:
                return f'hello {userid} flag is {FLAG}'
            return f'<script>alert("hello {userid}");history.go(-1);</script>'
        return '<script>alert("wrong");history.go(-1);</script>'

챗지피티에게 그대로 물어본다.


접근 방법 with GPT(?)

GPT는 정확하게 뭘 넣어야 하는지 정확히는 답변이 안나오지만, admin이나 '1'='1'과 같은 문장을 사용하여
접근할 수 있다는 사실을 알 수 있다.


풀이

SQL를 공부하기 위해 하나하나 해석해가며 정석으로 풀어보겠다.

 

res = query.db(select * from users where userlevel='0' and userid='admin')라고 할 때 해석해보면
users 테이블에 칼럼이 userlevel='0'이고 칼럼이 userid='admin'인 것을 찾아서 res변수에 넣으라는 뜻이다.

 

표로 나타내면 다음과 같다.

 

 

users 테이블

userlevel userid
0 admin
1 guest1
2 guest2
... ...

 

 

따라서 res변수에 데이터베이스형태로 userlevel='0'과 userid='admin'이 저장될 것이고,

 if res:
            userid = res[0]
            userlevel = res[2]
            print(userid, userlevel)
            if userid == 'admin' and userlevel == 0:

res에 값이 존재할때:

userid = res[0]  # '0'이 들어가게 될것이고

userlevel = res[2]  # 'admin'이 들어가게 될 것이다. 숫자는 몇 번째 칼럼인지 나타내는 거 같다. (신경안써도됨.)

 

 

따라서 해당 로직을 통해 admin의 값을 알아내고자 한다면,

변수가 userlevel인 곳에 입력값 그대로를

res = query_db(f"select * from users where userlevel='{userlevel}'") 를 통해서
res 변수에 넣기 때문에,

 select * from users where userlevel='0' and userid='admin' 과 같은 쿼리가 입력된다면 아래에 있는

if userid == 'admin' and userlevel == 0:

에 의해 플래그가 출력될 것이다.

따옴표 기호를 생각하여 입력값은 다음과 같다.

 

 

0' and userid='admin

 

 

너무나도 당연하지만, userlevel의 변수를 입력 받을 수 있는 곳은 로그인 창인데, 이것은 개발자 도구를 활용하여 확인할 수 있다.

name이 userlevel인 것을 get메서드로 통신한다는 것은 코드를 통해서 알 수 있다.