本文最后更新于79 天前
序列化值
各类型值的serialize序列化:
空字符 null -> N;
整型 -> i
浮点型 -> d
boolean型 true -> b:1;
boolean型 false -> b:0;
字符串 “Yunxi” -> s:5:“Yunxi”;
魔术命令
__toString()
以下几种情况会导致对象被当作字符串处理,从而触发 __toString
方法:
1.使用 echo
或 print
输出对象:
- 当你使用
echo
或print
输出一个对象时,PHP会调用该对象的__toString
方法。***例如:$obj = new MyClass(); echo $obj; // 这将调用 MyClass 的 __toString 方法
2.字符串拼接:
- 当对象与其他字符串进行拼接时,PHP也会调用
__toString
方法。例如:$obj = new MyClass(); $result = "对象的内容是: " . $obj; // 调用 __toString 方法
3.字符串插值:
- 在双引号字符串中嵌入对象时,也会触发
__toString
方法。例如:$obj = new MyClass(); echo "对象的内容是: $obj"; // 调用 __toString 方法
__sleep()
当一个对象被序列化时调用
格式化字符串函数:
- 一些字符串格式化函数,如
sprintf()
,在处理对象时也会调用__toString
方法。例如:$obj = new MyClass(); $formatted = sprintf("对象的内容是: %s", $obj); // 调用 __toString 方法
__construct()
__construct
是PHP中的一个魔术方法,用于定义类的构造函数。当使用new
关键字创建类的实例时,PHP会自动调用该构造函数。构造函数通常用于初始化对象的属性或执行其他必要的设置操作。
class FLAG{
public $flag_string = "HelloCTF{????}";
function __construct(){
echo $this->flag_string;
}
}
$code = $_POST['code'];
eval($code);
当FLAG被实例化,那么__construct自动调用
__invoke()
定义对象调用行为:__invoke
方法允许你定义当一个对象被当作函数使用时,该对象的行为。这使得对象可以像函数一样被调用,从而提供更灵活的编程模式。
public function __invoke(...$arguments) {
// 方法逻辑
}
__invoke在对象被当做函数应用时调用
__wakeup()
反序列化时自动调用
__call()
调用对象不可访问、不存在的方法时触发
__callStatic()
在静态上下文中调用不可访问的方法时触发
__get()
调用不可访问、不存在的对象成员属性时触发
__set()
在给不可访问、不存在的对象成员属性赋值时触发
不可访问
1. 不可访问属性
不可访问属性通常是由于以下原因:
- 私有属性(
private
):只能在定义它们的类内部访问。 - 受保护属性(
protected
):只能在定义它们的类及其子类中访问。 - 未定义属性:尝试访问一个未定义的属性。
2. 不可访问方法
不可访问方法通常是由于以下原因:
- 未定义方法:尝试调用一个未定义的方法。
- 私有方法(
private
):只能在定义它们的类内部调用。 - 受保护方法(
protected
):只能在定义它们的类及其子类中调用。
3. 不可访问对象
不可访问对象通常是由于以下原因:
- 私有构造函数:无法从类外部实例化对象。
- 单例模式:通过静态方法控制对象的创建。
私有和受保护,外界类无法访问他们,只能通过“它”的类和子类访问
绕过
__wakeup绕过
存在此漏洞的php版本:php5-php5.6.25、php7-php7.0.10;
调用unserialize()方法时会先调用__wakeup()方法,但是当序列化字符串的表示成员属性的数字大于实际的对象的成员属性数量是时,__wakeup()方法不会被触发
\^O:\d+/绕过
前提:代码通过正则匹配来绕过O:加一个类名长度
if (preg_match('/^O:\d+:/i', $var))
我们可以通过O:+4:”Test”,就是加上加号,它不符合正则匹配规则
或者用把对象放入数组绕过 serialize(array($a));
大写S绕过
表示字符串类型的s大写为S时,其对应的值会被当作十六进制解析;
Yunxi变成了\59unxi;