GitHub Java CodeQL CTF
内容提要
本文介绍GitHub安全实验室CTF挑战,聚焦于Java CodeQL漏洞分析,涉及CVE-2020-9297。文章详细说明了如何利用CodeQL进行数据流和污点跟踪,识别用户输入流向危险函数,并解决污点传播中断问题。通过添加额外污点步骤和构造函数步骤,最终实现远程代码执行。
延伸解读
CodeQL污点分析的默认限制
文章指出,CodeQL默认不会通过getter方法传播污点,这是为了避免假阳性。例如,如果对象实例被污染,但某个getter返回的是无关数据,默认不传播可减少误报。理解这一默认行为有助于分析为何数据流中断,并指导如何通过添加额外污点步骤来精确追踪。
Partial Flow调试技巧
当完整污点分析无结果时,可使用Partial Flow(部分数据流)来定位中断点。通过限制探索深度(如explorationLimit=10)并限制源,可以观察污点传播到何处停止。文章示例中,通过Partial Flow发现污点在getSoftConstraints和getHardConstraints处中断,从而确定需要添加额外步骤。
自定义污点步骤的实践
为解决getter和构造函数导致的污点传播中断,文章展示了如何通过TaintTracking::AdditionalTaintStep类添加自定义步骤。例如,将getter的qualifier视为污点源,返回值视为污点汇;对HashSet构造函数,将参数污点传播到构造结果。这种方法可扩展CodeQL的污点分析能力,但需谨慎设计以避免引入假阳性。
Q&A
GitHub Java CodeQL CTF 挑战中,漏洞的根源是什么?
漏洞的根源是用户控制的数据被传入支持Java EL表达式的Bean Validation库函数ConstraintValidatorContext.buildConstraintViolationWithTemplate,可能导致远程代码执行。
在CodeQL分析中,如何定义Source?
Source定义为ConstraintValidator接口的isValid方法的第一个参数,即用户控制的container对象。需要确保是重写的方法,通过添加isOverridable()条件来过滤。
在CodeQL分析中,如何定义Sink?
Sink定义为ConstraintValidatorContext.buildConstraintViolationWithTemplate(...)调用的第一个参数。通过匹配方法名和声明类型来识别。
为什么初始的TaintTracking配置没有找到任何路径?
因为CodeQL默认不通过getter方法传播污点,导致从source到sink的路径中断。需要添加额外的污点步骤来处理getSoftConstraints、getHardConstraints和keySet等getter调用。
如何使用Partial Flow来调试污点跟踪问题?
使用Partial Flow可以找到从source到任意节点的部分流,通过设置explorationLimit限制搜索深度,并限制source为感兴趣的特定source,从而观察污点传播在哪里停止。
为什么CodeQL默认不通过getter传播污点?
为了避免假阳性,因为getter可能返回未受污染的数据,如果默认传播,会导致大量误报。
如何添加额外的污点步骤来解决getter传播问题?
通过定义TaintTracking::AdditionalTaintStep的子类,在step谓词中指定从MethodAccess的qualifier到MethodAccess本身的污点传播,并限定方法名为getSoftConstraints、getHardConstraints或keySet。
为什么还需要为HashSet构造函数添加污点步骤?
因为污点数据通过HashSet构造函数传递,需要添加步骤使污点从构造参数传播到构造结果,以完成完整的污点流。