【SDL实践指南】Foritify规则自定义刨析

admin 2025年2月12日16:42:36评论31 views字数 11541阅读38分28秒阅读模式

文章前言

Fortify SCA运用了Fortify Security研究小组开发的Fortify Source Code Analyzers的相关规则(语意规则、配置规则、数据流规则、控制流规则、结构化规则)和Code Modeling规则类型(Alias rules、Allocation rules、Buffer Copy rules、Non-Returning rules、String Length rules)去分析安全漏洞中的源代码,本篇文章将对Foritify用户自定义规则的创建和使用进行简单介绍

规则定义

规则创建

假设我们现在有如下JAVA源代码文件:

package org.example;public class HardPassword {    public String iamUser="Admin";    public String iamPassword="123456";    public String iampassword="123456";    public String iamPass="1234567";    public String iam="12345678";    public String password="123456789";    public String getUsername() {        return username;    }    public void setUsername(String username) {        this.username = username;    }    public String getPassword() {        return Password;    }    public void setPassword(String password) {        Password = password;    }}

从上面我们可以看到这里对IAM的用户密码使用了硬编码,下面我们通过Fortify内置的规则编辑器CustomRulesEditor自定义规则来对源代码中的硬编码问题进行排查扫描,首先我们进入到Fortify的bin目录中运行CustomRulesEditor规则编辑器:

【SDL实践指南】Foritify规则自定义刨析

打开规则编辑器之后我们可以看到规则分类有以下四类:

  • Taint Flags/Rule Type:Taint Flags是一种标记机制,用于指示数据流的来源是否是"污点"的(即不可信的)数据源,这些标记帮助识别潜在的安全问题,例如:SQL注入、跨站脚本攻击(XSS)以及 XML外部实体(XXE)等漏洞

  • Package/Category:Package和Category用于组织和分类规则以便于管理和使用,Package为规则的包名称,表示规则所属的特定库或模块,这有助于用户快速找到相关规则并理解其上下文,Category表示规则的功能类别,例如:输入验证、安全性检查等,通过将规则分类用户可以更轻松地定位与特定安全主题相关的规则

  • Audience/Rule Type:Audience指的是规则的目标用户群体,这可能包括开发人员、安全分析师或代码审查人员等,了解受众有助于设置规则的详细程度和复杂性以适应不同技能水平的用户

  • Kingdom/Rule Type:Kingdom通常用于更高层次的分类,可能代表规则的主要领域或大类,例如:"网络安全"、"应用程序安全"等,它提供了一种结构化的方式来组织规则,使用户能够快速识别与特定领域相关的规则

  • Category/Rule Type:Category在此上下文中再次出现,表示规则的功能分类,例如:"输入验证"、"输出编码"等,这有助于用户快速了解规则的目的和作用

【SDL实践指南】Foritify规则自定义刨析

我们直接保持默认的"Taint Flags/Rule Type"并选择"File->Generate Rule"来创建规则:

【SDL实践指南】Foritify规则自定义刨析

随后会显示自定义规则的引用模板,目前主要按照漏洞类型(Category)和规则类型(Rule Type)进行分类,但是不管是何种分类都可以大致分为数据污染源Tainted规则、数据控制流规则、数据传递规则、漏洞缺陷爆发的Sink规则

【SDL实践指南】Foritify规则自定义刨析

在这里我们选择漏洞类型(Category)中Password Management下的"Structural Rule for Password Management"模板

【SDL实践指南】Foritify规则自定义刨析

随后选择规则适用的编程语言:

【SDL实践指南】Foritify规则自定义刨析

随后填写用于匹配密码的正则表达式(备注:在这里要多做验证测试):

(?i)iampass(|wd|word)

【SDL实践指南】Foritify规则自定义刨析

配置规则存储路径:

【SDL实践指南】Foritify规则自定义刨析

随后可以看到根据模板生成的规则,其中总计6条匹配项,其中2项为匹配硬编码密码,另外4项为匹配空密码操作:

  • RulePackID:规则包唯一ID

  • SKU:全局唯一标识符

  • Name:规则包名称

  • Version:规则包版本

  • Description:规则包描述

  • Rules:规则组,里面可容纳多个规则

  • RuleDefinitions:规则定义

【SDL实践指南】Foritify规则自定义刨析

根据我们当前的规则目的我们无需去处理空密码,所以我们直接删除后面的四项,最后留下以下内容:

【SDL实践指南】Foritify规则自定义刨析

<?xml version="1.0" encoding="UTF-8"?><RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules">    <RulePackID>86AF47A5-E7EF-4779-AB49-123A3EC90AE2</RulePackID>    <SKU>SKU-D:EnvironmentFortifySCACoreconfigcustomrulesIAM-HandCoded-rule</SKU>    <Name><![CDATA[D:EnvironmentFortifySCACoreconfigcustomrulesIAM-HandCoded-rule]]></Name>    <Version>1.0</Version>    <Description><![CDATA[]]></Description>    <Rules version="22.1.0">        <RuleDefinitions>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A611</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description ref="desc.semantic.java.password_management_hardcoded_password">                    <Explanation append="true"><![CDATA[This issue is being reported by a custom rule.]]></Explanation>                </Description>                <Predicate><![CDATA[                FieldAccess fa: fa.field.name matches "(?i)iampass(|wd|word)" and                                fa in [AssignmentStatement: lhs.location is fa and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and fa.field is [Field f:]*            ]]></Predicate>            </StructuralRule>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A6111</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description ref="desc.semantic.java.password_management_hardcoded_password">                    <Explanation append="true"><![CDATA[This issue is being reported by a custom rule.]]></Explanation>                </Description>                <Predicate><![CDATA[                VariableAccess va: va.variable.name matches "(?i)iampass(|wd|word)" and                                va in [AssignmentStatement: lhs.location is va and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and va.variable is [Variable v:]*            ]]></Predicate>            </StructuralRule>        </RuleDefinitions>    </Rules></RulePack>
简易测试

首先将自定义规则保存到用户自定义规则目录中去(上面我们在创建时就直接保存到了自定义规则目录)——FortifySCACoreconfigcustomrules

【SDL实践指南】Foritify规则自定义刨析

当然你也可以在${FortifyInstall}/Core/config/fortify-sca.properties进行配置自定义路径

【SDL实践指南】Foritify规则自定义刨析

随后启动Fortify代码扫描工具并配置加载自定义规则:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

选择工程执行静态代码扫描:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

随后开始执行扫描:

【SDL实践指南】Foritify规则自定义刨析

扫描结果如下:

【SDL实践指南】Foritify规则自定义刨析

在这里由于我们扫描的时候加载了默认的扫描规则,其中也包含了HardCoded Password规则所以有一部分是重复的,在验证的时候我们需要特别留意以下这里的RuleID是否和我们自定义的规则中的一致来确保我们自己定义的规则是有被加载且保证正常扫描执行到:

【SDL实践指南】Foritify规则自定义刨析

在这里我们为了规避默认的规则带来的影响我们可以对项目执行"重新扫描"并只勾选自定义规则:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

随后得到如下结果,从中可以看到这里的大小写以及关键字的匹配都是我们预期想要的内容,所以至此规则测试完成且符合我们的预期

【SDL实践指南】Foritify规则自定义刨析

规则完善

在完成上面的规则的测试之后我们还需要对规则进行进一步的优化处理,包括:规则名称、修复建议、

规则名称

前面我们说过在加载规则的时候的那个路径是规则的名称而不是规则的路径,这里为了后期规则的区分我们对规则名称进行一次更改,变更的方式为更改规则中的"Name"标签属性:

【SDL实践指南】Foritify规则自定义刨析

随后可以看到再次加载规则的时候规则名称被成功更改:

【SDL实践指南】Foritify规则自定义刨析

漏洞描述

在创建自定义规则时我们有两种选择来生成关于漏洞的描述:

A、引用Foritify官方的描述

首先我们需要确定要使用的描述的标识符,描述标识符位于https://vulncat.fortify.com/en/weakness,找到要使用的描述的标识符后将自定义规则的ref属性设置为Fortify描述的标识符

【SDL实践指南】Foritify规则自定义刨析

描述有点偏,位于每个描述的最下面部分,例如:

desc.semantic.java.password_management_hardcoded_password

【SDL实践指南】Foritify规则自定义刨析

随后变更规则,加入漏洞描述:

【SDL实践指南】Foritify规则自定义刨析

但是并没有什么效果:

【SDL实践指南】Foritify规则自定义刨析

<?xml version="1.0" encoding="UTF-8"?><RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules">    <RulePackID>86AF47A5-E7EF-4779-AB49-123A3EC90AE2</RulePackID>    <SKU>SKU-D:EnvironmentFortifySCACoreconfigcustomrulesIAM-HandCoded-rule</SKU>    <Name><![CDATA[IAM-HandCoded Password]]></Name>    <Version>1.0</Version>    <Description><![CDATA[]]></Description>    <Rules version="22.1.0">        <RuleDefinitions>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A611</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description ref="desc.semantic.java.password_management_hardcoded_password">                </Description>                <Predicate><![CDATA[                FieldAccess fa: fa.field.name matches "(?i)iampass(|wd|word)" and                                fa in [AssignmentStatement: lhs.location is fa and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and fa.field is [Field f:]*            ]]></Predicate>            </StructuralRule>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A6111</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description ref="desc.semantic.java.password_management_hardcoded_password">                    <Explanation append="true"><![CDATA[This issue is being reported by a custom rule.]]></Explanation>                </Description>                <Predicate><![CDATA[                VariableAccess va: va.variable.name matches "(?i)iampass(|wd|word)" and                                va in [AssignmentStatement: lhs.location is va and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and va.variable is [Variable v:]*            ]]></Predicate>            </StructuralRule>        </RuleDefinitions>    </Rules></RulePack>

B、用户自定义描述

关于用户的自定义描述我们可以直接借助自定义规则编辑器来实现:

<Abstract>:漏洞摘要<Explanation>:漏洞描述<Recommendations>:修复建议

【SDL实践指南】Foritify规则自定义刨析

随后可以看到如下效果:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

变更后的规则如下:

<?xml version="1.0" encoding="UTF-8"?><RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules">    <RulePackID>86AF47A5-E7EF-4779-AB49-123A3EC90AE2</RulePackID>    <SKU>SKU-D:EnvironmentFortifySCACoreconfigcustomrulesIAM-HandCoded-rule</SKU>    <Name><![CDATA[IAM-HandCoded Password]]></Name>    <Version>1.0</Version>    <Description><![CDATA[]]></Description>    <Rules version="22.1.0">        <RuleDefinitions>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A611</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description>                    <Abstract><![CDATA[IAM账号密码硬编码]]></Abstract>                    <Explanation><![CDATA[IAM账号密码硬编码在源代码文件中存在安全风险]]></Explanation>                    <Recommendations><![CDATA[禁止将IAM账号密码硬编码在源代码文件中]]></Recommendations>                </Description>                <Predicate><![CDATA[                FieldAccess fa: fa.field.name matches "(?i)iampass(|wd|word)" and                                fa in [AssignmentStatement: lhs.location is fa and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and fa.field is [Field f:]*            ]]></Predicate>            </StructuralRule>            <StructuralRule formatVersion="22.1.0" language="java">                <RuleID>668C7FF9-A407-4EFD-B5E7-04A70E56A6111</RuleID>                <VulnKingdom>Security Features</VulnKingdom>                <VulnCategory>Password Management</VulnCategory>                <VulnSubcategory>Hardcoded Password</VulnSubcategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description >                    <Abstract><![CDATA[IAM账号密码硬编码]]></Abstract>                    <Explanation><![CDATA[IAM账号密码硬编码在源代码文件中存在安全风险]]></Explanation>                    <Recommendations><![CDATA[禁止将IAM账号密码硬编码在源代码文件中]]></Recommendations>                </Description>                <Predicate><![CDATA[                VariableAccess va: va.variable.name matches "(?i)iampass(|wd|word)" and                                va in [AssignmentStatement: lhs.location is va and not rhs.constantValue.null and not rhs.constantValue is [Null:] and not rhs.constantValue == ""] and va.variable is [Variable v:]*            ]]></Predicate>            </StructuralRule>        </RuleDefinitions>    </Rules></RulePack>

使用扩展

覆盖规则

场景描述:代码审计过程中发现Foritify的某一条规则频繁错误提报,此时我们可以通过自定义规则对原规则进行覆盖处理

具体实现:

Step 1:首先记录当前规则ID

C204F020-1CA1-4c25-A6CB-BAA69CA2DA0B

【SDL实践指南】Foritify规则自定义刨析

Step 2:新建一个规则覆盖当前规则ID

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

随便胡乱输入匹配规则

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

生成规则如下:

【SDL实践指南】Foritify规则自定义刨析

更改当前Rule ID:

【SDL实践指南】Foritify规则自定义刨析

随后导入规则执行扫描操作:

【SDL实践指南】Foritify规则自定义刨析

随后可以看到记录被移除

【SDL实践指南】Foritify规则自定义刨析

函数调用

场景描述:代码审计过程中发现存在具备特征的函数名称时我们可以为函数名称制定规则来实现全量检索,在检索时我们的终极目的时检索定位处所有调用该函数的位置点

具体实现:

示例代码:

package org.example;public class SecTest {    public int evil(int a, int b) {        //do something    return a+b;    }    public int verify() {        //do something     return evil(1,2);    }}

新建扫描规则

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

选择语言:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

(?i)evil

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

最终规则如下:

【SDL实践指南】Foritify规则自定义刨析

<?xml version="1.0" encoding="UTF-8"?><RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules">    <RulePackID>96F34CB0-3E78-4410-B6FE-E4D87859E682</RulePackID>    <SKU>SKU-D:EnvironmentFortifySCACoreconfigcustomrulesevil-rule</SKU>    <Name><![CDATA[D:EnvironmentFortifySCACoreconfigcustomrulesevil-rule]]></Name>    <Version>1.0</Version>    <Description><![CDATA[]]></Description>    <Rules version="22.1.0">        <RuleDefinitions>            <SemanticRule formatVersion="22.1.0" language="java">                <MetaInfo>                    <Group name="Accuracy">5.0</Group>                    <Group name="Impact">5.0</Group>                    <Group name="RemediationEffort">15.0</Group>                    <Group name="Probability">5.0</Group>                </MetaInfo>                <RuleID>5C3B2AC3-9F40-4CF3-9942-88E7C76ED780</RuleID>                <VulnCategory>FunSecScan</VulnCategory>                <DefaultSeverity>4.0</DefaultSeverity>                <Description/>                <Type>default</Type>                <FunctionIdentifier>                    <NamespaceName>                        <Pattern>.*</Pattern>                    </NamespaceName>                    <ClassName>                        <Pattern>.*</Pattern>                    </ClassName>                    <FunctionName>                        <Pattern>(?i)evil</Pattern>                    </FunctionName>                    <ApplyTo implements="true" overrides="true" extends="true"/>                </FunctionIdentifier>            </SemanticRule>        </RuleDefinitions>    </Rules></RulePack>

随后进行扫描

【SDL实践指南】Foritify规则自定义刨析

紧接着可以看到扫描结果如下:

【SDL实践指南】Foritify规则自定义刨析

备注:这里一定一定要切记,测试代码一定要符合JAVA标准语法且能够再IDEA中正常编译,不要随意乱写,否则直接扫描不出来东西,笔者这里就是在测试的时候文件名称和类名称没写一致导致始终死活出不来后期才发现这个问题,主要的原因是在使用Fortify进行扫描的时候会将源代码进行一次编译处理,如果你代码有问题,那么在编译阶段就会直接挂,根本走不到所谓的代码规则的匹配阶段,更不用说扫描出漏洞来了~

白名单类

场景描述:企业为了对用户输入的数据进行统一处理大多数情况下回制定统一的过滤函数或者验证函数来进行验证,在这种情况下我们需要对此类函数加白

具体实现:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

这一步就有点意思了,我们在这里可以对调用的返回值加白或者函数整体加白使其调用点加白,另外也可以指定参数加白来适配各类场景,在这里我们选择返回值加白:

【SDL实践指南】Foritify规则自定义刨析

【SDL实践指南】Foritify规则自定义刨析

最终规则如下,数据污染溯源中如果遇到evil则会直接跳过不再报相关问题

<?xml version="1.0" encoding="UTF-8"?><RulePack xmlns="xmlns://www.fortifysoftware.com/schema/rules">    <RulePackID>4F7E0448-CB78-4B38-BB9C-CD99204A9DF0</RulePackID>    <SKU>SKU-D:EnvironmentFortifySCACoreconfigcustomrulescustom-rule</SKU>    <Name><![CDATA[D:EnvironmentFortifySCACoreconfigcustomrulescustom-rule]]></Name>    <Version>1.0</Version>    <Description><![CDATA[]]></Description>    <Rules version="22.1.0">        <RuleDefinitions>            <DataflowCleanseRule formatVersion="22.1.0" language="java">                <RuleID>937B7C98-A88E-4D73-84B9-09A02D8D3534</RuleID>                <FunctionIdentifier>                    <NamespaceName>                        <Pattern>.*</Pattern>                    </NamespaceName>                    <ClassName>                        <Pattern>.*</Pattern>                    </ClassName>                    <FunctionName>                        <Pattern>verify</Pattern>                    </FunctionName>                    <ApplyTo implements="true" overrides="true" extends="true"/>                </FunctionIdentifier>                <OutArguments>return</OutArguments>            </DataflowCleanseRule>        </RuleDefinitions>    </Rules></RulePack>

文末小结

Foritify自定义规则适用频次最多的应该属于SemanticRule,如果要使用更为复杂的数据流规则、控制流规则、内容规则等则自行进行配置测试即可,建议结合具体的漏洞代码展开为好~

原文始发于微信公众号(七芒星实验室):【SDL实践指南】Foritify规则自定义刨析

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年2月12日16:42:36
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【SDL实践指南】Foritify规则自定义刨析http://cn-sec.com/archives/3729825.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息