nodejs应用中的权限绕过漏洞—一个赏金漏洞的故事
字数 1265 2025-08-27 12:33:37
Node.js应用中的权限绕过漏洞分析与利用
概述
本文详细分析了一个Node.js应用中发现的权限绕过漏洞,该漏洞存在于身份验证机制中,允许攻击者通过精心构造的请求绕过正常的认证流程。漏洞发现于一个私有SRC(安全响应中心)项目,并通过漏洞赏金计划报告。
漏洞发现方法论
1. 初始侦察
- 子域名枚举:使用工具发现潜在攻击目标
- 端口扫描:检查常见web端口(80, 443, 8080, 8443等)
- Aquatone工具:生成可视化报告,识别活跃web服务
2. 目标分析
- 源代码审查:检查HTML/JS/CSS文件寻找隐藏目录和API端点
- Wappalyzer:识别技术栈(Node.js, ExpressJS等)
- 静态分析:使用工具分析JavaScript代码寻找客户端验证逻辑
3. 功能测试
- Burp Suite:拦截和修改请求测试各种功能点
- 修改Content-Type(application/json, application/xml)
- 尝试不同HTTP方法(GET, POST, PUT等)
- 观察服务器响应差异
- wfuzz:使用自定义字典(约45,000条目)寻找隐藏目录和文件
漏洞发现过程
初始观察
登录接口的典型请求:
POST /api/auth/login HTTP/1.1
Content-Type: application/json;charset=UTF-8
{"username":"bl4de","password":"secretpassword"}
服务器响应:
HTTP/1.1 401 Unauthorized
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
{"result":"User with login [bl4de] was not found.","resultCode":401,"type":"error"}
关键发现:用户名被包含在方括号中返回,暗示服务器可能将用户名作为数组处理。
测试异常输入
-
发送空数组:
{"username":[],"password":"secretpassword"}服务器返回不同错误,确认数组处理逻辑
-
发送空对象:
{"username":{},"password":"secretpassword"}服务器返回错误:
TypeError: val.replace is not a function表明服务器尝试在对象上调用字符串方法
-
嵌套数组测试:
{"username":[[]],"password":"secretpassword"}触发SQL语法错误:
ER_PARSE_ERROR: You have an error in your SQL syntax...
SQL注入尝试
-
数组索引测试:
{"username":[0],"password":"secretpassword"}返回不同错误,表明可以访问ID为0的用户
-
多索引测试:
{"username":[1,2,3],"password":"secretpassword"}成功枚举其他用户,但密码验证仍失败
密码验证绕过
-
使用false作为密码:
{"username":[0],"password":false}返回"用户名或密码缺失"错误
-
使用true作为密码:
{"username":[0],"password":true}成功绕过密码验证
漏洞原理分析
服务器端处理逻辑
-
用户名处理:
- 服务器将用户名作为数组元素处理
- 直接拼接到SQL查询的IN()子句中
- 允许通过数组索引枚举用户
-
密码验证:
- 密码验证存在逻辑缺陷
false被视为缺失值true被接受为有效凭证
技术根本原因
- 类型混淆:服务器未严格验证输入类型
- 不安全的直接拼接:用户输入直接用于构建SQL查询
- 宽松的布尔处理:密码验证逻辑存在缺陷
漏洞利用限制
-
不完全绕过:
- 系统还要求PIN码进行二次验证
- 无法完全登录系统
-
SQL注入限制:
- 输入经过基本过滤
- 特殊字符被拦截
防御措施
输入验证
-
严格类型检查:
if (typeof username !== 'string' || typeof password !== 'string') { return res.status(400).json({error: 'Invalid input types'}); } -
参数化查询:
const [user] = await db.query( 'SELECT * FROM users WHERE id = ? LIMIT 1', [userId] );
认证增强
-
多重验证:
- 保持PIN码验证作为第二因素
- 实现速率限制防止枚举攻击
-
错误处理:
- 使用通用错误消息
- 避免泄露实现细节
总结
该漏洞展示了Node.js应用中常见的几类安全问题:
- 不安全的输入处理
- 类型混淆漏洞
- 不完善的认证逻辑
通过系统的测试方法和深入的分析,可以发现并利用这类漏洞。防御此类漏洞需要开发者实施严格的输入验证、使用安全的数据库访问模式,并避免泄露系统内部信息。