js有没有 类似php 的 __autoload?

详解PHP反序列化漏洞

  • 反序列化中常见的魔术方法
  • 利用16进制绕过字符过滤
  • 利用不同的引擎来处理session文件
  • PHP原生类反序列化利用

序列化(串行化):是将变量转换为可保存或传输的字符串的过程;
反序列化(反串行化):就是在适当的时候把这个字符串再转化成原来的变量使用;
这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性;



注意点:当访问控制修饰符(publicprotectedprivate)不同时,序列化后的结果也不同 public 被序列化的时候属性名 不会更改 private 被序列化的时候属性名 会变成 %00类名%00属性名
  1. __call(),在对象中调用一个不可访问方法时调用
  2. __callStatic(),用静态方式中调用一个不可访问方法时调用
  3. __get(),获得一个类的成员变量时调用
  4. __set(),设置一个类的成员变量时调用
  5. __toString(),类被当成字符串时的回应方法
  6. __invoke(),调用函数的方式调用一个对象时的回应方法
  7. __clone(),当对象复制完成时调用

通过值的引用可以使$a的值与$b的值相等

利用16进制绕过字符过滤

  • 利用加号绕过(注意在url里传参时+要编码为%2B)
  • serialize(array(a)); a为要反序列化的对象(序列化结果开头是a,不影响作为数组元素的$a的析构)

PHP在反序列化时,底层代码是以 ; 作为字段的分隔,以 } 作为结尾(字符串除外),并且是根据长度判断内容的,同时反序列化的过程中必须严格按照序列化规则才能成功实现反序列化,当序列化的长度不对应的时候会出现报错
字符逃逸的本质其实也是闭合,但是它分为两种情况,一是字符变多,二是字符变少


  • 参数name多传入一个x导致溢出导致反序列化失败



  • 参数name少传入一个x导致溢出导致反序列化失败

    由于xx会被替换成x,所以我们输出的66个x会变成33个x,由于";s:3:"way";s:15:"Web_Crypto_Misc部分一共33个字符,所以它会被参数name吃进去当成它的属性值,而我们写入的恶意字符串";s:3:"way";s:7:"Hacker!";}就能够正常的解析并执行反序列化操作

当用户的请求在传给反序列化函数unserialize()之前没有被正确的过滤时就会产生漏洞。因为PHP允许对象序列化,攻击者就可以提交特定的序列化的字符串给一个具有该漏洞的unserialize函数,最终导致一个在该应用范围内的任意PHP对象注入

  • 代码里有定义一个含有魔术方法的类,并且该方法里出现一些使用类成员变量作为参数的存在安全问题的函数

在代码运行结束后会调用_destruct函数,同时会覆盖变量name输出Gyan

PHP里的session主要是指客户端浏览器与服务端数据交换的对话,从浏览器打开到关闭,一个最简单的会话周期

会话的工作流程很简单,当开始一个会话时,PHP会尝试从请求中查找会话 ID (通常通过会话 cookie),如果发现请求的Cookie、Get、Post中不存在session id,PHP 就会自动调用php_session_create_id函数创建一个新的会话,并且在http

会话开始之后,PHP 就会将会话中的数据设置到 $_SESSION 变量中,如下述代码就是一个在 $_SESSION 变量中注册变量的例子


代码的意思就是如果不存在session那么就创建一个session
也可以用如下流程图表示

php.ini里面有如下六个相对重要的配置

  • session.auto_start --指定会话模块是否在请求开始时启动一个会话,默认值为 0,不启动

如phpstudy下上述配置如下:

上文中提到了 PHP session的存储机制是由session.serialize_handler来定义引擎的,默认是以文件的方式存储,且存储的文件是由sess_sessionid来决定文件名的,当然这个文件名也不是不变的,都是sess_sessionid形式

打开看一下全是序列化后的内容

PHP内置了多种处理器用于存储$_SESSION数据时会对数据进行序列化和反序列化,常用的有以下三种,对应三种不同的处理格式:


我们到session存储目录查看一下session文件内容


为了更能直观的体现出格式的差别,因此这里设置了键值长度为 35,35 对应的 ASCII 码为#,所以最终的结果如下


a:1表示$_SESSION数组中有 1 个元素,花括号里面的内容即为传入GET参数经过序列化后的值

    1. 知道session文件存放路径,可以尝试默认路径
    1. 具有读取和写入session文件的权限

可以发现,存在一个文件包含漏洞,但是找不到一个可以包含的恶意文件;其实,我们可以利用session.upload_progress将恶意语句写入session文件,从而包含session文件;前提需要知道session文件的存放位置

利用条件主要是存在session反序列化漏洞

  • 整个代码没有参数可控的地方,通过什么方法来进行反序列化利用
    这里,利用PHP_SESSION_UPLOAD_PROGRESS上传文件,其中利用文件名可控,从而构造恶意序列化语句并写入session文件;另外,与文件包含利用一样,也需要进行竞争

在代码里加个代理,利用burpsuite抓包

  • PHPSESSID必须要有,因为要竞争同一个文件
  • filename可控,但是在值的最前面加上|,因为最终目的是利用session的反序列化,PHP_SESSION_UPLOAD_PROGRESS只是个跳板;其次把字符串中的双引号转义,以防止与最外层的双引号冲突
  • filename值中出现汉字时,会出错,所以在利用脚本前,一定要修改python源码

把exp.py中的代理去掉,直接跑exp.py,效果如下

利用不同的引擎来处理session文件

|会被当成键值对的分隔符,在特定的地方会造成反序列化漏洞
我们创建一个session.php,用于传输session值,里面代码如下


再创建一个hello.php,里面代码如下


用如下代码来复现一下session的反序列化漏洞


因为session是php_serialize处理器,所以允许|存在字符串中,所以将这段代码序列化内容前面加上|传入session.php中
现在来看一下存入session文件的内容

一个php应用程序往往是由多个文件构成的,如果能把他们集中为一个文件来分发和运行是很方便的,这样的列子有很多,比如在window操作系统上面的安装程序、一个jquery库等等,为了做到这点php采用了phar文档文件格式,这个概念源自java的jar,但是在设计时主要针对 PHP 的 Web 环境,与 JAR 归档不同的是Phar归档可由 PHP 本身处理,因此不需要使用额外的工具来创建或使用,使用php脚本就能创建或提取它。phar是一个合成词,由PHP和 Archive构成,可以看出它是php归档文件的意思(简单来说phar就是php压缩文档,不经过解压就能被 php 访问并执行)
phar文件本质上是一种压缩文件,会以序列化的形式存储用户自定义的meta-data;当受影响的文件操作函数调用phar文件时,会自动反序列化meta-data内的内容

php中一些常见的流包装器如下:

  • file:// — 访问本地文件系统,在用文件系统函数时默认就使用该包装器
  • glob:// — 查找匹配的文件路径模式
  • manifest:也就是meta-data,压缩文件的属性等信息,以序列化存储
  • signature:签名,放在文件末尾
  • phar文件要能够上传到服务器端
  • 要有可用的魔术方法作为“跳板”
  • 文件操作函数的参数可控,且:、/、phar等特殊字符没有被过滤

漏洞成因:phar存储的meta-data信息以序列化方式存储,当文件操作函数通过phar://伪协议解析phar文件时就会将数据反序列化


 

可以很明显看到manifest是以序列化形式存储的

有序列化数据必然会有反序列化操作,php一大部分的文件系统函数在通过phar://伪协议解析phar文件时,都会将meta-data进行反序列化
受影响的函数如下,参考链接


 
 
 
 
 
 
 
 

当环境限制了phar不能出现在前面的字符里,还可以配合其他协议进行利用

GIF格式验证可以通过在文件头部添加GIF89a绕过

  • 如果在代码审计中有反序列化点,但是在原本的代码中找不到可利用的类时,可以考虑使用php中的一些原生类
  • 需要有soap扩展,且不是默认开启,需要手动开启
  • 需要调用一个不存在的方法触发其__call()函数
  • WSDL用来描述如何访问具体的接口
  • SOAP是连接web服务和客户端的接口
  • 简单地说,SOAP 是一种简单的基于 XML 的协议,它使应用程序通过 HTTP 来交换信息
第一个参数是用来指明是否是wsdl模式 如果为null,那就是非wsdl模式,反序列化的时候会对第二个参数指明的url进行soap请求 如果第一个参数为null,则第二个参数必须设置location和uri uri是SOAP服务的目标名称空间
  • 正常情况下的SoapClient类,调用一个不存在的函数,会去调用__call方法,发出请求
  • 如果是GET请求,就简单得多,只需要构造好location就可以了
  • 需要注意的是,SoapClient只会发出请求,而不会收到响应

  • 适用于php5、7版本

从使用$pattern构造一个新的目录迭代

 

前提:需要有sqlite3扩展,且不是默认开启,需要手动开启


}

举个例子就可以看懂了:

spl_autoload_register() 提供了一种更加灵活的方式来实现类的自动加载(同一个应用中,可以支持任意数量的加载器,比如第三方库中的)。

}

我要回帖

更多关于 php调用不存在的类 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信