前言Java漏洞挖掘有一个痛点。在漏洞点已知的情况下,如何找到控制点,确定具体的数据流。几天前我看到@AlvaroMu?oz使用codeql发现了[CVE-2020-10199]NexusRepositoryManager远程代码执行漏洞。于是他对codeql产生了很大的好奇,花了几天时间研究codeql语法和CVE案例。提取CVE的QL代码,Codeql,Codeql的具体介绍可以参考:https://help.semmle.com/使用codeql可以清楚的搜索到方法调用的数据流向,以及思路写QL代码相当于在代码库中使用写好的逻辑去寻找可能的调用点。关键是确定Source和Sink的查找逻辑。简单分析一下漏洞原理,该漏洞是由于没有过滤的表达式注入造成的。作者确定漏洞点并执行函数buildConstraintViolationWithTemplate。该方法中bean.getMessage()返回的resultmessage没有使用stripJavaEl方法过滤导致表达式注入最后调用org.hibernate.validator.internal.engine.messageinterpolation#interpolate,进行插入操作并解析恶意字符串,导致在表达注入中。HelperBeanbean#message写Codeql最重要的是首先要确定数据的流向Sink点就是污染点字段。在此处跟进org.sonatype.nexus.validation.HelperBean#getMessage方法。返回消息值。该值通过HelperBean方法传递到Ql代码中。这里直接上代码,简单解释一下:搜索出流HelperBean方法中message字段的数据流isSink方法搜索逻辑:定义参数p,被调用的HelperBean方法使用,p参数命名为messageisSouce方法搜索逻辑:由于不清楚数据源最终从哪里经过sink,所以直接使用source.asExpr()调用所有可能的表达式为dataflow.importjavaimportsemmle.code.java.dataflow.FlowSourcesclassConfigextendsDataFlow::Configuration{Config(){this="1"}overridepredicateisSource(DataFlow::Nodesource){exists(source.asExpr())}overridepredicateisSink(DataFlow::Nodesink){exists(参数p|p=sink.asParameter()和p.getCallable().getName()="HelperBean"和p.getName()="message")}}来自Config配置,DataFlow::PathNodesource,DataFlow::PathNodesinkwhereconfig.hasFlowPath(source,sink)selectsource。getNode().getLocation(),source,sink搜索结果运行QueryAbstractGroupRepositoriesApiResource#validateGroupMembers根据搜索结果,这里最可疑的来源是AbstractGroupRepositoriesApiResource:92。点击结果跟进,Codeql很友好的标记了污染点repositoryName并溯源获取repositoryName的值,最终从request中获取。Ql代码现在需要确定调用AbstractGroupRepositoriesApiResource#validateGroupMembers()方法的位置。isSink方法搜索逻辑:定义参数p,被调用的validateGroupMembers方法使用,p参数调用requestisSouce方法搜索逻辑:这里的source本来是用Codeql自带的RemoteFlowSource获取的,但是没有结果.所以这里直接使用source.asExpr()来搜索全局表达式。importjavaimportsemmle.code.java.dataflow.FlowSources类ConfigextendsDataFlow::Configuration{Config(){this="1"}overridepredicateisSource(DataFlow::Nodesource){exists(source.asExpr())}overridepredicateisSink(DataFlow::Nodesink){exists(Parameterp|p=sink.asParameter()andp.getCallable().getName()="validateGroupMembers"andp.getName()="request")}}//从Configconfig,DataFlow::PathNodesource,DataFlow::PathNodesinkwhereconfig.hasFlowPath(source,sink)selectsource,sinksearchresultsRunQuery中获取潜在可控函数,其中GolangGroupRepositoriesApiResource为漏洞调用的可控点。结语原文如有错误,请高手指正。希望大师们喜欢
