StrcuturalRule和Characterization Rule:
前面的教程请看fortify规则教程1,2
对于简单的规则来说,都是无法满足我们的规则判断的,因为过程复杂,且误报的情况比较多,所以我们需要严格限定部分的内容来减少误报,有的人会说 规则写的严格会导致漏报吗?
那我告诉你,大部分情况下还是不会影响的。(这里我们不谈数据流构造的时候soundness问题,那就扯不清楚了,就只说大众理解的规则上来看的误报和漏报问题)
漏报只存在于数据流无法连接的情况下,这个是什么意思呢?
那就是:
-
缺乏source sink,这里指的是代码直接的source sink。
-
第三方包里的方法。数据流经过这些地方的时候会断开,导致无法最后流动到sink点。
例如有一个方法叫做clean_data,这个方法是security.filter.clean_data方法。例如代码如果用了esapi等包里的方法进行清除的话,就不会数据流经过那边,自然就没办法检测出来漏洞。
对于这样的概念,在fortify里叫做passthrough,在codeql里叫做addtionalStepflow。
Fortify的Structural rule在2个规则里会用到,一个是structuralrule本身,另一个是characterization rule。对应的结构分别是
<StructuralRuleformatVersion="20.1"language="java">
<RuleID>A42F2AEE-7A09-49FE-9696-8484AAC9136E2</RuleID>
<VulnKingdom>Security Features</VulnKingdom>
<VulnCategory>Password Management</VulnCategory>
<VulnSubcategory>Hardcoded Password</VulnSubcategory>
<DefaultSeverity>4.0</DefaultSeverity>
<Descriptionref="desc.semantic.java.password_management_hardcoded_password">
<Explanationappend="true"><![CDATA[This issue is being reported by a custom rule.]]></Explanation>
</Description>
<Predicate><![CDATA[
Function f: f.parameters contains [Variable v: v.annotations[0].type.name matches "org.springframework.web.bind.annotation.RequestParam" ]
]]></Predicate>
</StructuralRule>
<CharacterizationRuleformatVersion="3.17"language="java">
<RuleID>82AA0CDC-E6C2-430D-9759-F33E967E96E5C</RuleID>
<StructuralMatch><![CDATA[
Function f: f.parameters contains [Variable v: v.annotations[0].type.name matches "org.springframework.web.bind.annotation.RequestParam" ]
]]></StructuralMatch>
<Definition><![CDATA[
TaintSink(c,{+MyBatisSelectQuery,+PRIVATE,+WEB,+XSS,+DATABASE})
]]></Definition>
</CharacterizationRule>
如果你不知道这个,你可以用custom rule edtior来生成一个这样的规则的模版 ,这个很简单,点点就会了。
目前看到大家都用dataflow模块来做安全检测,但是可以看到大部分规则都是带了.* 来匹配,很多地方是有误报的。
比如以下规则
代码都是package->class->method形式,然后定义了init开头的方法是危险的,但是也没严格定义参数,参数只是说了not VALIDATED_PRIVACY_XXX 这个是一个taintflag标记,官方定义了一组这个规则,大部分情况是method的参数可能是其他的一个自定义的类,这是最常见的 !然而自己的类的一些字段可能是string的,导致进入sink后取出来拼接。但是这样的规则就会大量误报,甚至一些自定义类的字段是Long Int也会触发规则,是个猪都知道这样的场景是误报。
但是dataflow规则只能输入.*来匹配。无法对字段类型做判断,这个时候我们就要用到这个characterization rule。这个规则是用来对场景做分组的,设置taintflag用的。
再举个例子,我们要约束source为spring的@Requestmapping的方法做为控制器入口,那么根据上面的dataflow规则显然是很难满足我们的需要的,但是如果用
<CharacterizationRuleformatVersion="3.17"language="java">
<RuleID>34711D7A-C2BC-40B3-B1DE-B5C48EF65646</RuleID>
<StructuralMatch><![CDATA[
Function f: f.parameters contains [Variable v: v.annotations[0].type.name matches "org.springframework.web.bind.annotation.RequestParam" ]
]]>
</StructuralMatch>
<Definition><![CDATA[
TaintEntrypoint(v, {+XSS})
]]></Definition>
</CharacterizationRule>
就可以很好的解决这个问题了。
这个规则就是寻找一个函数f,他的第一个参数是带了RequestParam注解。和codeQL那种关系查询方法很像了。
这个是根据语法树来匹配对应的代码,对于fortify来说,这个叫做nst。
我们可以编写一个简单的规则来查找全部的function
然后打开一个function看就是这样的结构,根据tab的对应来看.Arguments是第一级属性。
那怎么了解有哪些属性呢?加博主微信,博主给你文档。
版本是18.2,最新的是23,还算新吧。
那我怎么让他显示这个tree呢?
可以用
sourceanalyzer -cp "**/**.**" "**/**/*.java" -no-default-rules -rules 2.xml -scan -f fortify-example.fpr -D com.fortify.sca.MultithreadedAnalysis=true -Ddebug.dump-structural-tree 2> tree-no-default-rule.tree
主要是这个-D参数,这个参数再官方手册上找不到,哪怕sourceanalyzer -h也看不到。。。
所以我们要改进一个sink,且这个sink的参数必须被用到@select的注解里,那就可以用
但是这里有一个问题,fortify好像对第三方的注解支持有问题,我并不能搜到ibatis的@select注解。
官方的20规则里,mybatis的注解sink 是一个由dataflow标签包裹的,里面的class package method均为.* ,即全部的方法。然后加了一个label。这个label是mybatis_mapper_label,这就像是加了一个taintflag一样,真正的处理逻辑的是一个js。。
在关键的地方会打上这个mybatis select query标记。然后dataflow的数据找到满足条件就会触发。
SuppressionRule
在fortify里,这个规则的作用是用来屏蔽你要的规则,
例如
这样的话,ruleID中的内容就不会再运行起来。这个规则对于10+M的原生规则来说是很有用的,因为我们不需要什么spring配置错误之类的一大堆的有的没的,很低危的漏洞。
其他有什么问题再群里说吧。顺便说一句上面的规则不仅限于java ,其他语言也适用
原文始发于微信公众号(xsser的博客):Fortify规则教程3
- 左青龙
- 微信扫一扫
- 右白虎
- 微信扫一扫
评论