[webhacking.kr] 37번 문제 풀이[Race Condition]
💡 Webhacking.kr challenge(old) 37번 문제에 대한 풀이입니다.
문제
<?php
$db = dbconnect();
$query = "select flag from challenge where idx=37";
$flag = mysqli_fetch_array(mysqli_query($db,$query))['flag'];
$time = time();
$p = fopen("./tmp/tmp-{$time}","w");
fwrite($p,"127.0.0.1");
fclose($p);
$file_nm = $_FILES['upfile']['name'];
$file_nm = str_replace("<","",$file_nm);
$file_nm = str_replace(">","",$file_nm);
$file_nm = str_replace(".","",$file_nm);
$file_nm = str_replace("/","",$file_nm);
$file_nm = str_replace(" ","",$file_nm);
if($file_nm){
$p = fopen("./tmp/{$file_nm}","w");
fwrite($p,$_SERVER['REMOTE_ADDR']);
fclose($p);
}
echo "<pre>";
$dirList = scandir("./tmp");
for($i=0;$i<=count($dirList);$i++){
echo "{$dirList[$i]}\n";
}
echo "</pre>";
$host = file_get_contents("tmp/tmp-{$time}");
$request = "GET /?{$flag} HTTP/1.0\r\n";
$request .= "Host: {$host}\r\n";
$request .= "\r\n";
$socket = fsockopen($host,7777,$errstr,$errno,1);
fputs($socket,$request);
fclose($socket);
if(count($dirList) > 20) system("rm -rf ./tmp/*");
?>
문제 풀이
php 코드가 길기 때문에 핵심적인 부분만 요약을 하면 다음 부분들입니다.
#매번 요청을 할때마다 서버에서 tmp-$time 형식으로 파일을 생성하고, 파일 안에 127.0.0.1을 적는다
$p = fopen("./tmp/tmp-{$time}","w");
fwrite($p,"127.0.0.1");
fclose($p);
#사용자가 파일을 업로드 하면 해당 파일 안에는 사용자의 ip를 적는다.
$file_nm = $_FILES['upfile']['name'];
if($file_nm){
$p = fopen("./tmp/{$file_nm}","w");
fwrite($p,$_SERVER['REMOTE_ADDR']);
fclose($p);
}
#tmp-$time 파일에서 ip를 읽어와서 해당 파일에 쓰여진 ip로 플래그 정보가 포함된 get 요청을 한다.
$host = file_get_contents("tmp/tmp-{$time}");
$request = "GET /?{$flag} HTTP/1.0\r\n";
$request .= "Host: {$host}\r\n";
$request .= "\r\n";
$socket = fsockopen($host,7777,$errstr,$errno,1);
fputs($socket,$request);
이번 문제는 race condition의 개념을 이용하는 문제로, 서버가 먼저 생성한 tmp-{$time} 파일을 덮어써서 127.0.0.1이 아닌 나의 ip로 요청이 오도록 변경하는 것입니다.
결과
이를 파이썬 코드로 작성하면 다음과 같습니다.
위의 코드를 우분투 환경에서 실행하면 다음과 같이 플래그를 획득 할 수 있습니다.
댓글남기기