Blog to Blog

[WebHacking] TG:HACK 2020 WriteUp - Bobby 본문

Hacking/Writeup

[WebHacking] TG:HACK 2020 WriteUp - Bobby

kookhh0827 2020. 4. 11. 19:03

문제설명

 

지난 4월 8일부터 4월 11일까지 진행된 TG:HACK 2020의 Bobby라는 문제입니다.

 

문제 설명에서는 딱히 중요한 정보를 얻을 수 없고,

Bobby라는 친구가 로그인 할 수 있도록 도와주면 된다는 것 같습니다.

 

구글에서 후원하는 대회 답게 서버도 총 3군데를 열어놓고 진행하네요.

 

간단한 로그인창

 

문제 사이트를 들어가 보면, 먼저 8분 내로 문제를 풀어야 한다는 경고가 나옵니다.

 

서버에 과부하를 주지 않도록, 또한 무작위 대입 공격을 막기 위해서 그런 것 같습니다.

8분이 지나면 다시 사이트에 재 접속해야 문제를 계속 풀 수 있습니다.

 

아마 8분마다 아이디랑 비밀번호가 바뀌든지 하는 것으로 추정됩니다.

 

비밀번호 변경 창

 

어차피 로그인은 해도 안되니 비밀번호 변경 창을 건드려 보고자 합니다.

 

일단 기본적으로 달리 공격할 부분이 없으니, SQL 공격을 해야 할 것 같습니다.

 

그래서 먼저 ' or sleep(10) -- 이라는 값을 대입해 봤습니다.

 

sleep이라는 함수가 없다고 나온다

sleep이라는 함수가 없다고 나오네요

 

해당 경고문을 토대로 검색해본 결과 SQLite로 db가 동작하고 있는 것 같습니다.

 

다음으로 어느 부분에서 취약점이 터지는지 알기 위해서

username이나 old password와 new password 부분을 번갈아 가며 값을 대입해 본 결과,

 

new password 부분에서 취약점이 터진다는 것을 알게 되었습니다.

 

UPDATE [TABLE] SET [COLUMN] = [VALUE], [COLUMN] = [VALUE], ... WHERE [Condition];

 

당연히 update 문을 사용할 것이라 생각했고,

SQLite에서는 위와 같은 문법을 사용하기 때문에 이 양식에 맞춰서 공격하면 될 것 같습니다.

 

먼저 blind sql injection을 시도해 보려고 했는데,

sleep 함수가 없고 달리 조건에 따른 출력 메시지의 차이로 알아낼 만한 부분이 없어 보였습니다.

 

또한, 제일 중요한 것은 table 명이나 column 명을 알아야 하는데, 이를 알 방법이 없었습니다.

 

에러 메시지를 통해 칼럼명을 알아냈다

문법에 맞지 않도록 유도를 했더니,

 

에러 메시지를 그대로 되돌려 줬습니다.

 

유저 아이디 칼럼명은 user, 패스워드 칼럼명은 pass였습니다.

 

그렇다면 update 문은 다음과 같이 있을 것이라 추측할 수 있습니다.

 

update users set pass = '[new password]' where user='[username]' and pass'[old password]';

 

그러므로 new password 부분을 적절하게 바꿔서

테이블 내의 모든 행의 아이디와 비밀번호를 바꿔버리면,

 

내가 원하는 아이디와 비밀번호로 로그인 할 수 있을 것이라 생각했습니다.

 

그래서 password에

', user='a', pass='a' where 1 --

라는 값을 넣어봤습니다.

 

인자의 개수가 잘못 되었다고 나온다

 

문법에는 이상이 없는데 이상한 오류가 나옵니다.

 

해당 오류를 검색해 보니, 파이썬에서 SQLite 모듈을 사용할 때 물음표 특수기호로 포매팅을 하기 때문에, 아마 다음과 같이 소스코드가 작성되어 있을 것이라 추측해 볼 수 있었습니다.

 

sql = "update users set pass = '{}' where user='?' and pass'?';".format(new_password)
conn.execute(sql, (username, old_password))

그러므로 주석 처리로 뒤에 있던 물음표들이 날아가 버리면,

username과 old_password라는 인자들이 필요가 없어지기 때문에

 

0개의 인자를 받아야 하는데 2개의 필요없는 인자들이 들어왔다고 에러가 나는 것입니다.

 

그러므로 다음과 이 형식에 맞춰 보내주면 끝입니다.

 

', user=?, pass=? where 1 --

 

new password에 위를 보내고,

user name과 old password에는 아무거나 넣으면 됩니다.

 

 정상적으로 비밀번호가 바뀌었다고 나온다

 

그렇다면 이제 테이블 내의 모든 아이디와 비밀번호가 a, a가 되었기 때문에

 

이를 통해 로그인 하면 됩니다.

 

로그인 하면 플래그를 준다.

 

FLAG : TG20{bobby_knows_his_sql}

 

pysqlite의 특성과, sqlite의 문법을 다시 한번 공부할 수 있는 좋은 문제였습니다.

 

이상으로 TG:HACK 2020 - Bobby의 Writeup을 마칩니다.

Comments