这是一道代码审计与绕过题所以我们先看代码我们发现一个核心就是v0is_numeric(v1)andisnumeric(v1) and is_numeric(v1)andisnumeric(v2) and is_numeric(v3);if(v3); if(v3);if(v0){if(!preg_match(“/\\|/|~||!||#|\$|%|^|*|)|-|_|||{|[|”|‘|,|.|;|?|[0-9]/“, $v2)){if(!preg_match(”/\\|/|~||!||#|\$|%|^|*|(|-|_|||{|[||’|,|.|?|[0-9]/“,KaTeX parse error: Expected }, got EOF at end of input: … eval(v2(‘ctfshow’)$v3”);}这里看似要求v1、v1、v1、v2、v3必须全部为数字。但这其实是一个经典的PHP优先级陷阱赋值运算符的优先级高于逻辑运算符and。因此这行代码在实际执行时等价于(v3 必须全部为数字。但这其实是一个经典的 PHP 优先级陷阱 赋值运算符 的优先级高于逻辑运算符 and。 因此这行代码在实际执行时等价于 (v3必须全部为数字。但这其实是一个经典的PHP优先级陷阱赋值运算符的优先级高于逻辑运算符and。因此这行代码在实际执行时等价于(v0 is_numeric(v1))andisnumeric(v1)) and is_numeric(v1))andisnumeric(v2) and is_numeric($v3);所以只要v1为数字$v0就是true我们要利用v2v3来构造payload但是代码对v2v3进行了严格的正则匹配过滤我们观察发现v2过滤了但是没过滤v3过滤了但是没过滤现在我们的目的就是构造一个合法的php语句既然提示说了 flag in class ctfshow并且代码本身已经实例化了该类$ctfshow new ctfshow();。我们需要通过某些反射、命名空间或输出函数来把这个对象的内容打印出来。在 PHP 中像 var_dump、print_r 这样的函数由于包含了下划线 _被v2过滤了无法直接使用。我们可以选择使用echo或getdefinedvars但含有下划线不可用或者直接利用类名与特殊函数。构造方法一利用ReflectionClass反射类PHP的ReflectionClass可以直接输出一个类的完整结构包括属性和静态变量。我们希望最终eval执行的语句是echonewReflectionClass(′ctfshow′);对照拼接模板v2 过滤了无法直接使用。 我们可以选择使用 echo 或 get_defined_vars但含有下划线不可用或者直接利用 类名与特殊函数。 构造方法一利用 ReflectionClass反射类 PHP 的 ReflectionClass 可以直接输出一个类的完整结构包括属性和静态变量。 我们希望最终 eval 执行的语句是echo new ReflectionClass(ctfshow); 对照拼接模板v2过滤了无法直接使用。我们可以选择使用echo或getdefinedvars但含有下划线不可用或者直接利用类名与特殊函数。构造方法一利用ReflectionClass反射类PHP的ReflectionClass可以直接输出一个类的完整结构包括属性和静态变量。我们希望最终eval执行的语句是echonewReflectionClass(′ctfshow′);对照拼接模板v2(‘ctfshow’)$v3我们令$v2 echo new ReflectionClass$v3 ;检查过滤$v2echo new ReflectionClass没有数字没有被过滤的特殊字符。满足条件v3;v3;v3;v3 的黑名单里没有分号 ;。满足条件所以我们构造的payload为:?v11v2echo new reflectionclassv3;这里发现flag格式跟之前不同首先把0x2d改为-因为在 ASCII 编码中十进制 45 对应字符 -连字符/减号然后再套上一层ctfshow{}外壳在 PHP 中使用 echo new ReflectionClass(‘ctfshow’); 能够直接输出 flag是因为 PHP 的“反射机制” 具有直接透视对象内部结构的能力并且触发了 PHP 的 自动字符串转换__toString 魔术方法。为了让你彻底明白我们可以把它拆解为两个核心原理什么是 ReflectionClass反射类在正常的面向对象编程中如果你想看一个类里面的内容你必须先知道它的属性名或方法名然后去调用它。如果类里的变量是私有的private 或 protected外部甚至无法直接访问。而 ReflectionClass 是 PHP 自带的一个内置“上帝视角”工具。它的作用是逆向工程。只要你把类名‘ctfshow’传给它它就会把这个类的所有秘密全部提取出来。无论是公共属性、私有属性、静态变量、方法还是类中定义的常量Flag 通常藏在这里都会被它一览无余地抓取到内存中。为什么配合 echo 就能直接打印出来通常情况下echo 只能用来打印字符串比如 echo “hello”;。如果你尝试 echo 一个普通的对象PHP 会直接报错Object of class X could not be converted to string。但是PHP 的内置 ReflectionClass 内部实现了一个特殊的魔术方法__toString()。运作流程实例化new ReflectionClass(‘ctfshow’) 创建了一个反射对象里面包含了 ctfshow 类的所有结构信息。触发转换当你对这个反射对象执行 echo 时PHP 会自动去调用这个对象内部的 __toString() 方法。格式化输出ReflectionClass 的 __toString() 被设计得非常智能它会自动把这个类的结构格式化为一个排版漂亮的纯文本字符串
ctf show web入门101
这是一道代码审计与绕过题所以我们先看代码我们发现一个核心就是v0is_numeric(v1)andisnumeric(v1) and is_numeric(v1)andisnumeric(v2) and is_numeric(v3);if(v3); if(v3);if(v0){if(!preg_match(“/\\|/|~||!||#|\$|%|^|*|)|-|_|||{|[|”|‘|,|.|;|?|[0-9]/“, $v2)){if(!preg_match(”/\\|/|~||!||#|\$|%|^|*|(|-|_|||{|[||’|,|.|?|[0-9]/“,KaTeX parse error: Expected }, got EOF at end of input: … eval(v2(‘ctfshow’)$v3”);}这里看似要求v1、v1、v1、v2、v3必须全部为数字。但这其实是一个经典的PHP优先级陷阱赋值运算符的优先级高于逻辑运算符and。因此这行代码在实际执行时等价于(v3 必须全部为数字。但这其实是一个经典的 PHP 优先级陷阱 赋值运算符 的优先级高于逻辑运算符 and。 因此这行代码在实际执行时等价于 (v3必须全部为数字。但这其实是一个经典的PHP优先级陷阱赋值运算符的优先级高于逻辑运算符and。因此这行代码在实际执行时等价于(v0 is_numeric(v1))andisnumeric(v1)) and is_numeric(v1))andisnumeric(v2) and is_numeric($v3);所以只要v1为数字$v0就是true我们要利用v2v3来构造payload但是代码对v2v3进行了严格的正则匹配过滤我们观察发现v2过滤了但是没过滤v3过滤了但是没过滤现在我们的目的就是构造一个合法的php语句既然提示说了 flag in class ctfshow并且代码本身已经实例化了该类$ctfshow new ctfshow();。我们需要通过某些反射、命名空间或输出函数来把这个对象的内容打印出来。在 PHP 中像 var_dump、print_r 这样的函数由于包含了下划线 _被v2过滤了无法直接使用。我们可以选择使用echo或getdefinedvars但含有下划线不可用或者直接利用类名与特殊函数。构造方法一利用ReflectionClass反射类PHP的ReflectionClass可以直接输出一个类的完整结构包括属性和静态变量。我们希望最终eval执行的语句是echonewReflectionClass(′ctfshow′);对照拼接模板v2 过滤了无法直接使用。 我们可以选择使用 echo 或 get_defined_vars但含有下划线不可用或者直接利用 类名与特殊函数。 构造方法一利用 ReflectionClass反射类 PHP 的 ReflectionClass 可以直接输出一个类的完整结构包括属性和静态变量。 我们希望最终 eval 执行的语句是echo new ReflectionClass(ctfshow); 对照拼接模板v2过滤了无法直接使用。我们可以选择使用echo或getdefinedvars但含有下划线不可用或者直接利用类名与特殊函数。构造方法一利用ReflectionClass反射类PHP的ReflectionClass可以直接输出一个类的完整结构包括属性和静态变量。我们希望最终eval执行的语句是echonewReflectionClass(′ctfshow′);对照拼接模板v2(‘ctfshow’)$v3我们令$v2 echo new ReflectionClass$v3 ;检查过滤$v2echo new ReflectionClass没有数字没有被过滤的特殊字符。满足条件v3;v3;v3;v3 的黑名单里没有分号 ;。满足条件所以我们构造的payload为:?v11v2echo new reflectionclassv3;这里发现flag格式跟之前不同首先把0x2d改为-因为在 ASCII 编码中十进制 45 对应字符 -连字符/减号然后再套上一层ctfshow{}外壳在 PHP 中使用 echo new ReflectionClass(‘ctfshow’); 能够直接输出 flag是因为 PHP 的“反射机制” 具有直接透视对象内部结构的能力并且触发了 PHP 的 自动字符串转换__toString 魔术方法。为了让你彻底明白我们可以把它拆解为两个核心原理什么是 ReflectionClass反射类在正常的面向对象编程中如果你想看一个类里面的内容你必须先知道它的属性名或方法名然后去调用它。如果类里的变量是私有的private 或 protected外部甚至无法直接访问。而 ReflectionClass 是 PHP 自带的一个内置“上帝视角”工具。它的作用是逆向工程。只要你把类名‘ctfshow’传给它它就会把这个类的所有秘密全部提取出来。无论是公共属性、私有属性、静态变量、方法还是类中定义的常量Flag 通常藏在这里都会被它一览无余地抓取到内存中。为什么配合 echo 就能直接打印出来通常情况下echo 只能用来打印字符串比如 echo “hello”;。如果你尝试 echo 一个普通的对象PHP 会直接报错Object of class X could not be converted to string。但是PHP 的内置 ReflectionClass 内部实现了一个特殊的魔术方法__toString()。运作流程实例化new ReflectionClass(‘ctfshow’) 创建了一个反射对象里面包含了 ctfshow 类的所有结构信息。触发转换当你对这个反射对象执行 echo 时PHP 会自动去调用这个对象内部的 __toString() 方法。格式化输出ReflectionClass 的 __toString() 被设计得非常智能它会自动把这个类的结构格式化为一个排版漂亮的纯文本字符串