发现在ctf中,关于PHP几大魔法函数的考点还是很多的,也是很基础的,也有很多的安全问题也是这些魔法函数造成的,简单记录一下关于魔法函数的理解以及在发现安全过程中遇到后怎么进行绕过。
1、__wakeup()
__wakeup()是在反序列化操作中起作用的魔法函数,当unserialize的时候,会检查时候存在__wakeup()函数,如果存在的话,会优先调用__wakeup()函数。举个简单例子:
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
print("this is __wakeup()");
}
}
$test = new xctf();
$t = serialize($test);
unserialize($t);
?>
这样在最后反序列化的时候,直接就调用了__wakeup()这个函数:
放上这个ctf原型,简单记录一下:
<?php
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
}
//?code=
?>
这是题目的代码,一个非常简单的绕过。在code后面输入serialize过后的代码,然后会进行反序列化,如果调用了__wakeup()就会直接退出,所以需要绕过__wakeup()函数。
回到第一个例子:
他的序列化后的字符串是:
O:4:"xctf":1:{s:4:"flag";s:3:"111";}
里面有个数字 1 ,这个 1 代表的是对象的属性个数,这里只有$flag这一个属性。
而__wakeup()函数漏洞就是与对象的属性个数有关,如果序列化后的字符串中表示属性个数的数字与真实属性个数一致,那么i就调用__wakeup()函数,如果该数字大于真实属性个数,就会绕过__wakeup()函数。
2、__construct()
实例化对象时被调用。__construct()是构造函数,同时当函数名和类名相同的时候,也是构造函数,构造函数有两种表达方式。
但是当__construct和以类名为函数名的函数同时存在的时候,__construct将被调用,而以类名作为函数名的构造函数不被调用。
3、__destruct()
当删除一个对象或对象操作终止时被调用。
4、__call()
当对象调用某个方法的时候,若方法存在,则直接调用;若不存在,则会去调用__call函数。
5、__get()
读取一个对象的属性时,若属性存在,则直接返回属性值;若不存在,则会调用__get函数。
6、__set()
设置一个对象的属性时,若属性存在,则直接赋值;若不存在,则会调用__set函数。
7、__toString()
打印一个对象的时被调用。如 echo $obj ,或 print $obj;
8、__clone()
克隆对象时被调用。如:$t=new Test(),$t1=clone $t;
9、__sleep()
serialize之前被调用。若对象比较大,想删减一点东东再序列化,可考虑一下此函数。
10、__isset()
检测一个对象的属性是否存在时被调用。如:isset($c->name)。
11、__unset()
unset一个对象的属性时被调用。如:unset($c->name)。
12、__set_state()
调用var_export时,被调用。用__set_state的返回值做为var_export的返回值。
13、__autoload()
实例化一个对象时,如果对应的类不存在,则该方法被调用。
很多时候关于php魔法函数爆出的安全问题,其实很多都是他们之间的一个组合的过程中忽略了它们之间的关系而造成的绕过,从而形成的安全问题。
这里先记录一下这些魔法函数的作用,关于他们在ctf中,以及在代码审计中出现的安全问题,后续遇到会再做补充。
文章不足之处请多包涵。