技术分享-硬编码导致的前台上传漏洞
字数 868 2025-08-30 06:50:35
硬编码导致的前台上传漏洞分析
一、漏洞概述
本漏洞是一个由于硬编码密钥导致的前台文件上传漏洞,攻击者可以利用硬编码在数据库中的密钥绕过身份验证,实现未授权文件上传。
二、技术背景
该漏洞存在于基于ThinkPHP框架开发的系统中,ThinkPHP的典型路由格式为:/index.php/controller/method。通过分析登录数据包可以确定相关路由。
三、漏洞分析
漏洞位置
漏洞文件位于:app/controller/Api.php文件的upload方法中。
关键代码分析
$key = $request->param("key");
if (!$key || $key == 'undefined' || $key == null) {
return $this->create([], '未登陆或密钥key为空', 400);
}
if ($_FILES["file"]["error"] > 0) return $this->create([], '上传出错', 400);
$max_size = SystemModel::where('key', "upload_max")->value("value");
if ($_FILES["file"]['size'] > $max_size * 1024 * 1024) {
return $this->create(null, '图片大小超出限制', 400);
}
$user = UserModel::where("Secret_key", $key)->find();
if (!isset($user) || $user['state'] == 0) return $this->create(null, '用户不存在或被停用', 400);
$allSize = ImagesModel::where('user_id', $user['id'])->sum('size');
if ($allSize + $_FILES["file"]['size'] > $user['capacity']) {
return $this->create(null, '您的存储配额不足', 400);
}
漏洞成因
- 系统首先检查传入的
key参数是否为空 - 然后使用
key查询用户信息:UserModel::where("Secret_key", $key)->find() - 问题在于这个
key是硬编码在管理员账户下的默认值(存储在数据库中的硬编码) - 当攻击者获取到这个硬编码的
key后,可以绕过身份验证 - 查询到的用户
role_id为1(管理员),系统会实例化UploadClass并调用其create方法 $role['storage_id']的值为1000,导致存储类型为local,直接上传文件
四、漏洞利用
利用条件
- 获取到硬编码在数据库中的
Secret_key值 - 系统未对上传文件类型进行严格限制
利用步骤
- 构造上传请求,包含硬编码的
key参数 - 上传任意文件
- 系统验证
key后会认为请求来自管理员账户 - 文件被直接上传到服务器
五、修复建议
- 移除硬编码密钥:不应在代码或数据库中存储固定的认证密钥
- 加强身份验证:上传功能应使用完整的会话验证机制,而非简单的密钥验证
- 最小权限原则:即使使用密钥验证,也不应默认赋予管理员权限
- 文件类型限制:严格限制可上传的文件类型
- 密钥轮换机制:如果必须使用密钥,应实现定期自动轮换机制
六、总结
该漏洞展示了硬编码凭证带来的安全风险,即使是存储在数据库中的固定值也可能被攻击者利用。开发时应避免任何形式的硬编码凭证,并实施严格的身份验证和授权机制。