본문 바로가기

WarGame/webhacking.kr

[webhacking.kr] Challenge 29 :: SQL Injection (subquery)


▼ Challenge 29는 다음과 같습니다.



갑자기 php 코드를 보여주질 않으니, 어렵게 느껴지고 많은 인내를 요구하는 문제였습니다.


파일명을 입력 받고, 화면에 출력하고 있습니다. 

그러므로 INSERT 구문과 SELECT 구문으로 이뤄져 있다는 것을 추측할 수 있습니다.


 추측 해본 SQL 구문은 다음과 같습니다.


1
2
3
INSERT INTO c29_tb (time, ip, file) VALUES ('$time''$_SERVER[REMOTE_ADDR]''$fime_name');
 
SELECT time, ip, file FROM c29_tb WHERE ip='$_SERVER[REMOTE_ADDR]';
cs


여기서 SELECT 구문에 WHERE 이하 절을 대충 생각하고 넘어가는 경우가 있는데, 파일명이나 다른 것이 아니라 IP 입니다.

INSERT 구문에서 자신의 IP가 아닌 다른 것을 넣으면 파일 업로드가 성공되어도, 파일명이 출력이 되질 않습니다.


처음 시도에서 test') 과 같은 파일명으로 업로드하면 "upload error"가 뜹는 것을 보실 수 있습니다.

지난 번 글에서, "이제 webhacking.kr 환경은 항상 magic_quotes_gpc가 on되어 있다고 생각해야 겠습니다." 라고 말한 적이 있어서 

당연히 Single Quotes가 안 먹히나 생각했습니다. 하지만 그 문제가 아니였습니다. 

이로 인해, 많은 시간을 잡아 먹었네요.


※ 이 부분은 다시 알아본 결과, magic_quotes_gpc는 GET,POST,COOKIE로 날라온 값에만 적용이 됨으로, 

   파일명으로 전송하는, 즉 배열로 전송하는 부분에서는 magic_quotes_gpc가 적용되지 않습니다.

   참고 : Challenge 61 (http://limjunyoung.tistory.com/73)


처음에 간과 했던 것이, Column의 순서 입니다.

'$file_name'의 위치가 과연 끝이 맞는 것일까?


 여러 시도 끝에, 다음과 같이 파일명을 전송하니, 이제 파일명이 출력이 됩니다.

sample', 'time', char(본인 IP))#

( 여기서 char()함수를 사용한 이유는 $file_name에서 "."을 ""으로 치환하기 때문입니다. Hex값을 사용하셔도 됩니다. )


 그러니깐, 다시 SQL문을 정의해 보면 다음과 같습니다.


1
INSERT INTO c29_tb (file, time, ip) VALUES ('$fime_name''$time''$_SERVER[REMOTE_ADDR]');

cs


INSERT 구문에서 file, time, ip 순으로 Column명이 기재되어 있었던 것 입니다.


이제 INSERT 구문은 완전히 추측이 가능해 졌고, 이제 문제에 hint에도 있듯이, password를 SELECT하기만 하면 될 것 같습니다.

이 부분은 지금까지 Challenge를 점수 순서대로 푸셨다면 크게 어렵지 않으실 겁니다.


이미 여러 Challenge에서 다중 Records 삽입에 대해서 알아 보았고, 

MySQL을 다뤄보셨던 분들은 Subquery에 대해서도 알고 있을 겁니다.

subquery의 개념은 크게 어려운 것이 아니니 넘어가도록 하겠습니다.


 보라색 형광펜으로 칠한 것과 같이 다중 Records 삽입 부분에 subquery를 이용하면 password를 출력하실 수 있습니다.


1
INSERT INTO c29_tb (file, time, ip) VALUES (sample_file', 'time', 'char(ip)'), ((SELECT password FROM c29_tb), 'time', 'char(ip)'))#, '$time', '$_SERVER[REMOTE_ADDR]');
cs