本文首发于先知社区:https://xz.aliyun.com/news/91339
提示:请使用java-code-auditor这个skill帮我分析 代码审计报告.md 中的SQL注入是否为误报
请使用skill-creator帮我生成一个java代码审计skill,目的是检查扫描器漏洞中真正的漏洞,而不是误报。
工作流程为:
1、打开漏洞扫描器的报告,分析他的调用链是否能够实现参数可控,常见不可控如下:比如xml实体注入存在漏洞函数,但是无法进行前端传参。2、分析该参数在传入漏洞点之前有无过滤参数,例如路径遍历中,有函数对传入路径参数进行过滤;SQL注入中,虽然存在漏洞点,但是有专门的SQLfilter函数过滤;或者比如xml实体注入存在漏洞函数,但是无法进行前端传参3、对照references文件夹的常见误报案例,进一步分析是否为误报
注意:不需要生成scripts/(可执行脚本这个结构)、需要生成references文件夹,
1)熟悉项目耗时长:在工作中做代码审计是大概率能拿到接口说明书的,而开源项目往往没有很接口说明书。如果每一个接口对应的功能点和参数都会出现,对于前期熟悉项目的时间就大大缩短。
===>解决思路:需要让AI生成接口说明书尽快熟悉项目。
2)人工判断时间过长:扫描器、AI误报多,需要逐个跟踪函数调用进行分析、后续还要调试判断漏洞是否存在。如果不用扫描器,人工去找每个漏洞的方法关键字更是费时费力。需要使用AI。
===>解决思路:寻找代码审计过程中可以AI辅助分析减少人工的操作。
当前代码审计的流程。总体来说是分三步走
初步进行代码审计,通过搜索漏洞关键字、组件版本等等查找漏洞点
查看调用链进行进一步筛选。
过前端验证,后端调试,验证漏洞确实存在。
第一步已经能通过扫描器实现了,而且时间短,用AI也不会大量提高效率,第三步断点调试前端验证不太好通过自动化实现,于是尝试在第二步减少误报上进行努力
需要先找一个接口说明书作为模板,然后在放到AI IDE工具的文档集中,让它参考这个生成一个接口文档。
模板示例最好给一个示范的http请求包和响应包,方便后续找到该接口时做漏洞验证

提示词如下:
请基于当前项目所有 Controller,生成一份中文 接口说明书 文档 参考#测试接口说明书模板,要求:
用 Markdown 输出,一级标题为“接口总览”,下面给出接口汇总表(方法、路径、功能)。
每个接口用二级标题,包含:接口描述、请求地址、请求方式、请求参数表格(字段/类型/必填/说明)、响应 200 示例、常见错误码。给每个接口一个http请求和响应示例
代码里的 @Api、@ApiOperation 注解内容请直接摘取,不要遗漏。
生成的文档如下

针对代码先进行漏洞分析,调试后判断是否是误报,再给AI测试当面临复杂漏洞情况下的效果。
本文预先审计4个漏洞,其中xml外部实体注入和fastjson漏洞是扫描器的误报,而SQL注入和重定向是真实存在的漏洞
扫描器认为是漏洞的原因:默认情况下,XMLInputFactory 未对外部实体做出限制,代码中未见限制外部实体注入。
// 创建XML输入工厂实例XMLInputFactoryxif=XMLInputFactory.newInstance();// 使用UTF-8编码将输入流包装为字符流InputStreamReaderin=newInputStreamReader(bpmnStream, StandardCharsets.UTF_8);// 创建XML流读取器,用于解析BPMN XMLXMLStreamReaderxtr=xif.createXMLStreamReader(in);// 使用BpmnXMLConverter将XML解析为BpmnModel对象BpmnModelbpmnModel=newBpmnXMLConverter().convertToBpmnModel(xtr);
实际上,最后给xml解析的方法是BpmnXMLConverter().convertToBpmnModel,该方法无法解析外部实体。(默认只解析正常业务的字段,并不是常见的把xml的文件一起遍历解析了)
publicBpmnModelconvertToBpmnModel(XMLStreamReaderxtr) {if (ELEMENT_DEFINITIONS.equals(xtr.getLocalName())) {definitionsParser.parse(xtr, model); } elseif (ELEMENT_RESOURCE.equals(xtr.getLocalName())) {resourceParser.parse(xtr, model); .............. }

扫描器认为是漏洞的原因:fastjon版本有漏洞+JSON.parseArray关键字
@RequestMapping("/batchCode")publicvoidbatchCode(HttpServletRequestrequest, HttpServletResponseresponse, Stringtables) throwsIOException {String[] tableNames=newString[] {};tableNames=JSON.parseArray(tables).toArray(tableNames);
实际上,JSON.parseArray有两个重载方法(方法名相同,参数不同等叫重载)
parseArray(Stringtext) //将 JSON 数组字符串解析为一个通用的 JSONArray 对象。不会反序列化parseArray(Stringtext, Class<T>clazz)//将 JSON 数组字符串直接反序列化为指定类型的 Java 对象列表。
恰好该项目用的就是parseArray(String text) ,那个不会反序列化的方法,所以就无法进行fastjson反序列化
TIPS:对应广为人知的组件中不理解的函数,可以问百度的文心,一般会比其他AI更加准确
提示词:给我讲讲fastjson中的JSON.parseArray方法;
参考我上篇的SQL注入分析https://xz.aliyun.com/news/91092
漏洞点:流程上的表单formKey参数可控,导致产生漏洞
@GetMapping("/form/{procDefId}/{taskId}")publicvoidform(@PathVariable("procDefId") StringprocDefId, @PathVariable("taskId") StringtaskId, HttpServletResponseresponse) throwsIOException {// 获取流程XML上的表单KEYStringformKey=actTaskService.getFormKey(procDefId, taskId);response.sendRedirect(formKey+"/"+taskId);}
利用效果
先上传表单,表单中包含formKey参数

再利用

要利用Ai减少误报,首先要知道为什么会有误报?
扫描器扫描到漏洞关键字往往是存在的,但是这个参数要不不可控(前端传参的参数无法影响它),要不就是代码跟进过程中有过滤的方法,导致大量误报
根据这二点进行优化,我想到了使用提示词、智能体、skills三种方案,但是不知道哪种好,于是问问AI

提示词明显不如后面两种,于是尝试这两种看看会有什么效果。
根据上面的逻辑+举例(举几个经典的误报案例),放进智能体中,进行优化提示词后添加。优化前我的提示词只有100多个字,优化后已经到了1501个字,看了一下还是挺详细的

该智能体明确自己的职责为调用链追踪、过滤机制识别、漏洞验证逻辑。分析方法为参数可控性验证、过滤函数识别、还给我添加了特殊场景处理(提供了反射、动态调用的方法追踪,挺好的)
答案是正确的,但是过程全错.......
未能识别出该XXE漏洞其实参数可控,也允许外部实体注入,只是没有解析到

未识别出formKey是漏洞

识别出来该漏洞是真实存在

没有识别出来该漏洞是误报

总结来看,该智能体能够对简单漏洞进行调用链分析(如SQL注入),但是对于相对复杂一点的漏洞,依然缺乏进一步分析的能力,需要人工进行审核。
根据Anthropic官方技能库的说明,Skill是一个包含指令、脚本和资源的文件夹,用于动态指导AI完成特定任务。举例:Skills是一个个独立的文件夹,每个Ski做一件事。比如"生成PPT"是一个Skil,"审校文章"是另一个Skill。
skill和mcp的区别在于,skill是怎么做,mcp是用什么来做。
每个Skill文件夹里可以包含
SKILL.md(核心指令文件,必需)scripts/(可执行脚本,可选)references/(参考文档,可选)assets/(模板和资源,可选)
这里我们使用官方的技能包skill-creator来创建技能,https://github.com/anthropics/skills/tree/main/skills/skill-creator
内容逻辑还和之前一样,这里我们利用trae的SOLO模式(最近才刚刚支持skill,来尝鲜一下)

创建好技能后,把技能放到对应的项目目录,对项目代码进行测试
提示词:请使用java-code-auditor这个skill帮我分析 代码审计报告.md 中的XX漏洞是否为误报

没有识别出xxe是误报,但是识别出了该XXE的参数可控,以及调用链,并给出了利用功能点和能直接用的POC。但这是可以理解的,因为人工静态审计也看不出来,基本要靠动态调试和实际测试漏洞才能发现这是误报。

还知道上传路径和触发xxe的路径不是同一个,聪明啊

识别出漏洞,并在进一步提问中给出了我利用步骤,其他部分都是对的,唯一不对的是文件上传的xml稍微有点问题
AI提供的xml
<userTaskid="task"name="User Task"><extensionElements><activiti:formKey>https://evil.com/phish</activiti:formKey></extensionElements></userTask>
真实的可利用漏洞xml
<userTaskid="task"name="User Task"activiti:formKey="http://baidu.com/workflow/audit"/>成功识别,并给出调用链

没有识别出fastjson是误报,感觉重载函数这个知识点对于AI还是有点难

总结:使用skill比使用常规智能体识别率更高
| 智能体 | skills | |
|---|---|---|
| xxe | 结果识别对,但是过程错误 | 结果错误,但是分析更进一步 |
| 重定向 | 结果识别错误,过程错误 | 结果正确,过程几乎正确 |
| SQL注入 | 结果正确,过程正确 | 结果正确,过程正确 |
| fastjson | 结果识别错误,过程错误 | 结果识别错误,过程错误 |
由于trae solo+skill的模式已经完胜普通智能体,于是在这个基础上对skill进行进一步改进。
思考在skill的references或者assets上面放一个漏洞误报案例,帮助他们持续进行优化,那是放references还是assets呢?在这里明显是references,像assets一般是后续放代码审计模板之类的

之前已经生成了skill的references的示例,只要我继续在下面写就行,将fastjson前置代码分析中的误报原因和代码示例放进去。
但是添加后,AI仍然提示fastjson存在漏洞,除非我主动告诉他,他才会反应到原来这个方法并非反序列化方法
看来光设置references还不行,于是让AI思考怎么能让他知道后续怎么做?
提示词:思考你搞错的原因,以后需要怎么修改skill才能让你一下子就能识别到这个fastjson是误报?让AI修改你的skill,审查后删掉一些不必要的,然后继续多轮测试,

通过查看AI的分析,AI在漏洞函数无法利用时,只要存在漏洞版本依然算漏洞,于是手动给他加了规则如下,
多轮修改之后他终于能识别出来了呜呜呜

