문제분석 & 풀이
Admin page에 로그인창이 있다.
이번 문제는 admin 계정으로 로그인하는 문제인 것 같다.
오른쪽에 보니 소스가 있어서 소스를 분석했다.
1) id, pw 값을 POST로 받는다. (2번줄)
2) id의 경우 addslashes() 를 통해 이스케이프 처리를 하고 pw는 md5()로 암호화 한다.
3) sql 쿼리를 실행하여 결과 값을 받고 결과값이 존재하면 문제가 클리어된다.
결과값이 존재만 해도 되는 것으로 봐서는 예상대로 admin 계정으로 로그인하는 문제다.
2)번 설명을 보면 id는 이스케이프 처리되기 때문에 인젝션이 불가능 할 것 같다.
이어서 pw는 md5()로 암호화가 되는데 특이점은 5번줄을 보면 md5() 안에 true라는 인자가 추가되어있다.
그렇다면 md5 함수의 두번째 인자에 대해 알아보자.
md5 함수의 두번째 인자의 경우 필수는 아니며 기본적으로는 false가 들어간다.
false가 들어가는 경우 우리가 아는 평범한 32자리의 md5 해시값이 생성된다.
그러나 두 번째 인자에 true 가 들어가면 원래 생성되는 해시값을 바이너리 형태로 생성한다.
바이너리 형태를 보면 !#등 문자의 형태를 띄는 것을 확인 할 수 있다.
그렇다면 이러한 문자의 형태를 띄는 특성을 이용해 sql 쿼리가 참이 되는 결과를 완성시키면 어떨까?
select id from chall51 where id='admin' and pw='1' or '1'
위 쿼리는 SQLi를 통해 "admin" 계정으로 로그인하는 예제다.
이와 같은 쿼리를 만들 수 있다면 pw 부분에서 or 기준 뒷 부분에 '1' 이 참이기 때문에 결과적으로 where문이 참이되고 따라서 id가 "admin"인 데이터를 가져올 것이다!
즉, 결론적으로 md5() 함수 true 인자에 의해 문자 형태의 바이너리 값이 생성되는 특성을 이용해 pw 부분에 '1' or '1' 이 나오게해서 원하는 결과를 만들겠다는 것이다.
그렇다면 해싱의 결과로 1' or '1 이 되는 입력값을 찾아야 한다.
사실 입력값을 찾는 것은 코딩을 이용한 노가다의 과정이 필요하지만 필자는 인터넷에서 그 값을 우연히 찾아서 참고했다.
이제 찾은 값을 입력하여 admin의 계정으로 로그인을 해보자!
클리어!!
test.py
import hashlib
str = "admin"
result = hashlib.md5(str.encode()).hexdigest()
print("admin ==>",result)
result = hashlib.md5(str.encode()).digest()
print("바이너리 admin ==>",result)
md5 암호화시 결과값을 확인하는 코드다.