[webhacking.kr] 41번 문제 풀이[PHP]

1 분 소요

💡 Webhacking.kr challenge(old) 41번 문제에 대한 풀이입니다.

문제

image

<?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를 통해서 파일을 업로드 한 후, 패킷을 캡처하여 다음과 같이 파일 명을 임의로 매우 길게 전송하여 서버쪽에서 오류를 유발시킵니다.

image

다음과 같이 오류 메시지에는 {$upload_dir}/{fn}정보가 표시되어 {$upload_dir}를 알아낼 수 있습니다.

image

정상적인 파일인 b2.png 파일을 업로드 한 뒤에, 다음과 같이 해당 경로로 경로로 접근하면 플래그를 획득할 수 있습니다.

image

댓글남기기