Wargame/Lord of SQL Injection

<Lord of SQL Injection> zombie

지우친구 웅이 2021. 12. 5. 16:23

zombie

GET 방식으로 전달받은 pw에서 rollup, join, ace, @를 필터링한다.

 

?pw=' or 1=1%23을 입력하면

쿼리가 참임에도 불구하고 아무것도 출력되지 않는다.

이를 통해 prob_zombie 테이블이 비어있음을 짐작할 수 있다.

그런데 전달받은 pw와 쿼리의 결과로 나온 pw의 값과 타입이 모두 같아야 문제가 풀린다.

 

앞서 풀었던 'ouroboros'문제와 같음을 알 수 있다.

하지만 'ouroboros'문제에서는 'replace'를 사용하여 quine query를 통해 문제를 해결할 수 있었지만,

이 문제에서는 'ace'를 필터링하기 때문에 'replace'를 사용할 수 없다.

 

이 문제의 경우 메타데이터를 활용하여 풀 수 있다.

MySQL은 메타데이터들을 종류별로 묶어 테이블을 만들고, 테이블을 모아 데이터베이스를 만들다.

이 데이터베이스가 information_schema이다.

 

information_schema 데이터베이스에는 processlist 테이블이 존재한다.

processlist 테이블에는 User, Host, db, Command, Time, State, Info, ID 컬럼이 존재한다.

 

이 processlist 테이블의 Info 컬럼에는 현재 특정 사용자가 실행 중인 쿼리가 저장되어있다.

이를 활용하여 사용자 명을 확인해야 하는데, MySQL에서는 user()를 통해 사용자명을 찾을 수 있다.

따라서, ?pw=' union select user()%23을 입력하면

사용자명이 zombie임을 알 수 있다.

 

앞서 얘기한 Info 컬럼에는 사용자가 실행 중인 쿼리가 저장되어있다.

이를 이용해 

?pw=' union select info from information_schema.processlist where user='zombie'%23를 입력하면

"select pw from prob_zombie where pw=''

union select info from information_schema.processlist where user='zombie'%23"를 출력한다.

 

즉, 입력된 query 그대로 출력하는 것을 확인할 수 있다.

그럼 GET 방식으로 전달 되는 pw는 "' union ..."으로 시작하기 때문에 substr로 필요한 부분만 잘라 출력하면 된다.

 

?pw=' union select substr(info, 38, 92) from information_schema.processlist where user='zombie'%23를 입력하면

GET으로 전달한 pw와 출력하는 pw의 값과 타입이 모두 같아 문제를 해결할 수 있다.