[webhacking.kr] 41번 문제 풀이[PHP]
💡 Webhacking.kr challenge(old) 41번 문제에 대한 풀이입니다.
문제
<?php
if(isset($_FILES['up']) && $_FILES['up']){
$fn = $_FILES['up']['name'];
$fn = str_replace(".","",$fn);
$fn = str_replace("<","",$fn);
$fn = str_replace(">","",$fn);
$fn = str_replace("/","",$fn);
$cp = $_FILES['up']['tmp_name'];
copy($cp,"./{$upload_dir}/{$fn}");
$f = @fopen("./{$upload_dir}/{$fn}","w");
@fwrite($f,$flag);
@fclose($f);
echo("Done~");
}
?>
문제 풀이
php 에서 $_FILES 변수는 파일을 업로드 할 때 사용하는 변수로, $_FILES[‘이름’][‘속성’]형태로 이루어져 있습니다.
해당 문제에서는 html에서 다음과 같이 데이터를 post 방식으로 보내기 때문에 서버에서는 $_FILES[‘up’][변수] 형태로 자료를 처리합니다.
<form method=post enctype="multipart/form-data">
<input type=file name=up><input type=submit value='upload'>
</form>
우선 php 코드를 분석해 보면 다음과 같습니다.
<?php
#파일이 전성되었는지 확인
if(isset($_FILES['up']) && $_FILES['up']){
# $_FILES['up']['name']은 클라이언트가 전송한 파일의 이름이 담긴 변수
$fn = $_FILES['up']['name'];
$fn = str_replace(".","",$fn);
$fn = str_replace("<","",$fn);
$fn = str_replace(">","",$fn);
$fn = str_replace("/","",$fn);
# $_FILES['up']['tmp_name']은 클라이언트가 전송한 파일이 php 서버에 임시로 저장되는 위치이다.
# ex) php\tmp\php16D5.tmp 이런식으로 저장되며 클라이언트가 전송한 파일이 해당 파일에 저장된다.
$cp = $_FILES['up']['tmp_name'];
# 클라이언트가 전송한 파일의 내용을 ./{$upload_dir}/{$fn}에 저장한다.
copy($cp,"./{$upload_dir}/{$fn}");
# ./{$upload_dir}/{$fn} 에는 클라이언트가 전송한 파일의 내용이 있었는데, 다음과 같이 $flag정보로 덮어쓴다.
$f = @fopen("./{$upload_dir}/{$fn}","w");
@fwrite($f,$flag);
@fclose($f);
echo("Done~");
}
?>
이번 문제에서 Flag를 얻기 위해서는 {$upload_dir}/{$fn}
위치로 접근해서 플래그를 읽어야 합니다.
기본적으로 가능한 접근 방법은 다음 2가지 방법이 있습니다.
- $upload_dir 값을 알아내서 직접 접근
- $fn 에 directory traversal 방식을 이용해서 $upload_dir 를 몰라도 접근 가능하도록 하기
이번 문제에서는 2번째 케이스인 directory traversal을 막기 위해서 필터링을 수행하고 있기 때문에 ${upload_dir}값을 알아내야 합니다.
본 문제는 일부러 오류를 발생시켜서 오류에서 나오는 데이터를 토대로 답을 획득할 수 있습니다.
burp suite를 통해서 파일을 업로드 한 후, 패킷을 캡처하여 다음과 같이 파일 명을 임의로 매우 길게 전송하여 서버쪽에서 오류를 유발시킵니다.
다음과 같이 오류 메시지에는 {$upload_dir}/{fn}
정보가 표시되어 {$upload_dir}를 알아낼 수 있습니다.
정상적인 파일인 b2.png 파일을 업로드 한 뒤에, 다음과 같이 해당 경로로 경로로 접근하면 플래그를 획득할 수 있습니다.
댓글남기기