문제분석 & 풀이
페이지에 접속하면 빈칸과 코드가 주어져있다.
코드를 분석해보자.
1) phone, id 파라미터가 있는지 검증한다. (3번줄)
2) phone, id 파라미터가 존재하면 다음을 수행한다. (4~9번줄)
2-1. phone 값에 * , / , = , select , - , # , ; 가 들어가면 프로그램을 강제종료한다. (4번줄)
2-2. id 값이 5자리를 넘으면 안된다. (5번줄)
2-3. id 에 admin이 들어가면 프로그램이 강제종료된다. (6번줄)
2-4. 위 3가지 검증을 모두 넘기면 sql 쿼리를 실행하여 새로운 레코드를 DB에 넣는다. (7번줄)
3) sql 쿼리를 실행하여 ip값을 가져와 $isAdmin 에 저장한다. (11번줄)
4) isAdmin['ip'] 값이 클라이언트의 ip와 같으면 문제가 해결된다. (12~14번줄)
5) 5번의 조건을 만족하지 않으면 클라이언트 ip에 해당되는 레코드를 DB에서 가져와 id와 phone 값을 화면에 출력한다. (17~23번줄)
결론적으로 4번의 조건을 만족하면 문제가 해결된다.
4번의 조건을 만족하기 위해서는 id가 'admin' 이면서 ip가 내 PC IP주소인 레코드가 존재해야 해결된다.
id값이 최대 5자리로 제한과 동시에 'admin'을 사용할 수 없기 때문에 정상적인 방법으로는 id가 'admin'인 레코드를 생성 할 수는 없을 것이다.
id가 'admin'인 레코드를 생성하기 위해서는 2-4번에서 sql 쿼리를 실행할때 인젝션을 해서 조작하여 원하는 레코드 값을 넣어야 할 것 같다.
우선 id 값의 경우 위에서 말한 이유 때문에 인젝션이 힘들 것 같고 phone을 이용해서 인젝션을 시도해보자.
insert 문의 경우 , 를 이용하여 여러 개의 레코드를 한 번의 명령으로 생성할 수 있기 때문에 이를 이용하여 인젝션 쿼리를 짜보자.
insert into chall35(id,ip,phone) values('guest','{$_SERVER['REMOTE_ADDR']}',1),('admin','[IP 주소]',123)
위 쿼리처럼 인젝션을 시도하면 phone 값을 검증하는 정규표현식에도 걸리지 않고 우리가 원하는 id가 'admin'인 레코드를 생성할 수 있다!
phone에 넣을 값을 생각했으니 이제 URL을 통해 직접 값을 보내보자.
정상적으로 레코드가 생성되면 문제가 클리어 될 것이다!