基于数据的越权检测思路
字数 1063 2025-08-15 21:32:16
基于数据的越权检测技术详解
1. 背景与问题概述
随着Web安全技术的发展,业务逻辑漏洞尤其是越权问题日益突出。传统检测方法存在以下问题:
- 黑盒测试:产生大量脏数据,影响测试环境
- 白盒扫描:误报率高,难以接受
- 代码审计:效率低下,难以规模化
2. 核心检测思路
通过分析请求与数据库交互的SQL语句,判断是否存在越权漏洞,主要流程:
- 捕获正常用户请求流量
- 记录请求对应的SQL语句
- 替换身份信息重放请求
- 比较两次请求执行的SQL语句差异
- 根据差异判断是否存在越权
3. 技术实现细节
3.1 数据流处理
需要处理三类信息:
- HTTP请求信息(headers、URL、method、body等)
- 执行的SQL语句
- SQL执行返回的对象信息
使用requestID作为唯一标识关联这三类信息。
3.2 SQL语句处理关键点
- 记录SQL语句:拦截并存储每个请求执行的所有SQL
- SQL比对:比较原始请求与测试请求的SQL差异
- SQL拦截:防止测试产生脏数据
3.3 MySQL拦截实现
以mysql-connector-java-8.0.13.jar为例,关键拦截点在:
com.mysql.cj.NativeSession.execSQL()
通过修改NativePacketPayload对象实现SQL拦截和修改。
3.4 关键代码实现
3.4.1 SQL拦截转换器
public class SqlTransformer2 implements ClassFileTransformer {
@Override
public byte[] transform(ClassLoader loader, String className,
Class<?> classBeingRedefined,
ProtectionDomain protectionDomain,
byte[] classfileBuffer) {
if ("com/mysql/cj/NativeSession".equals(className)) {
// 插入检测代码
CtMethod.executeUpdateInternal.insertBefore(
"com.baidu.openrasp.request.AbstractRequest request = " +
"com.baidu.openrasp.HookHandler.requestCache.get();" +
"com.mysql.cj.protocol.a.NativePacketPayload pack = $4;" +
"String currentSql = String.valueOf(pack);" +
"if (pack != null){" +
" String resultStr = (new DetectAuthorityVunlClass())." +
" detect(request, currentSql);" +
" if (resultStr.equals(\"1\")){" +
" int len = pack.getPayloadLength();" +
" byte[] b = new byte[len];" +
" byte[] c = pack.getByteBuffer();" +
" if (c[1] == 85) {b[1] = 115;pack.setByteBuffer(b);}" +
" }" +
"}"
);
// 返回修改后的字节码
return clazz.toBytecode();
}
return null;
}
}
3.4.2 漏洞检测核心逻辑
public class DetectAuthorityVunlClass {
public String detect(AbstractRequest request, String bytes) {
String currentSql = hexStr2Str(bytes);
String ua = request.getHeader("user-agent");
// 记录SQL到Redis
new InsertInfoToRedis().InsertToList(request.getRequestId()+":sql", currentSql);
// 判断是否为扫描器请求
if (ua.contains("TestBySecurityTeamForVunl")) {
// 获取原始请求ID
String origRequestid = ua.split("-")[1];
// 获取原始SQL
String oriGSql = new SelectInfoFromRedis().getSqlString(origRequestid, 0);
// 比较SQL
if(currentSql.equals(oriGSql)) {
System.out.println("检测到越权漏洞!");
System.out.println("原始SQL:" + oriGSql);
System.out.println("当前SQL:" + currentSql);
return "1";
}
}
return "0";
}
}
3.5 测试流程示例
- 原始请求:
POST /rest/parentrest/api/pc/address/update HTTP/1.1
Cookie: SESSION=SSSIONFORSARA
username=sara&address=china+beijing
对应SQL:
UPDATE users SET address = "china+beijing" WHERE username = "sara"
- 测试请求:
POST /rest/parentrest/api/pc/address/update HTTP/1.1
Cookie: SESSION=SSSIONFORBOB
username=sara&address=china+beijing
- 检测结果:
- 如果测试请求执行相同SQL → 存在越权
- 如果SQL中WHERE条件变为
WHERE id = 12→ 不存在越权
4. 方案优势
- 低误报:直接分析SQL语句,准确率高
- 无脏数据:可拦截修改类SQL执行
- 自动化:适合集成到CI/CD流程
5. 局限性及改进方向
5.1 当前局限
- 异步写入场景:无法处理通过消息队列异步更新数据的情况
- SQL变参问题:包含时间戳等动态参数的SQL比对困难
- 数据库兼容性:需要适配多种数据库类型
5.2 改进方向
- WHERE条件比对:只比较WHERE部分,忽略动态参数
- 流量收集优化:通过服务器流量镜像替代Agent
- 异步场景处理:结合业务日志分析
6. 总结
基于数据的越权检测方法通过分析请求与SQL的对应关系,实现了高准确率的自动化检测,同时避免了脏数据问题。虽然存在一定局限性,但通过持续优化可以成为企业安全测试流程中的重要组成部分。
注:本文技术方案基于百度开源的OpenRASP实现,相关代码可参考baidu/openrasp项目。