您好,欢迎来到第一枪!
当前位置: 第一枪> 产品库> 电脑、办公设备 > 软件产品 > 办公软件 > Fortify价格 Fortify新版购买 青穗软件
您是不是要采购

Fortify价格 Fortify新版购买 青穗软件

第一枪帮您来“拼单”,更多低价等你来!

Fortify价格 Fortify新版购买 青穗软件

Fortify价格 Fortify新版购买 青穗软件
  • Fortify价格 Fortify新版购买 青穗软件缩略图1
  • Fortify价格 Fortify新版购买 青穗软件缩略图2
  • Fortify价格 Fortify新版购买 青穗软件缩略图3
  • Fortify价格 Fortify新版购买 青穗软件缩略图4
热线:15339093085
来电请说明在第一枪看到,谢谢!

Fortify价格 Fortify新版购买 青穗软件产品详情

查看全部办公软件产品>>
  • 品牌:其他
  • 软件名称:Fortify

1.数据从一个不可信赖的数据源进入应用程序。 在这种情况下,数据经由getParameter()到后台。 
2. 数据写入到应用程序或系统日志文件中。 这种情况下,数据通过info() 记录下来。为了便于以后的审阅、统计数据收集或调试,应用程序通常使用日志文件来储存事件或事务的历史记录。根据应用程序自身的特性,审阅日志文件可在必要时手动执行,也可以自动执行,即利用工具自动挑选日志中的重要事件或带有某种倾向性的信息。如果攻击者可以向随后会被逐字记录到日志文件的应用程序提供数据,则可能会妨碍或误导日志文件的*。理想的情况是,攻击者可能通过向应用程序提供包括适当字符的输入,在日志文件中插入错误的条目。如果日志文件是自动处理的,那么攻击者可以*文件格式或注入意外的字符,从而使文件无法使用。更阴险的攻击可能会导致日志文件中的统计信息发生偏差。通过*或其他方式,受到*的日志文件可用于掩护攻击者的跟踪轨迹,甚至还可以牵连第三方来执行恶意行为。糟糕的情况是,攻击者可能向日志文件注入代码或者其他命令,利用日志处理实用程序中的漏洞。
例 1: 下列 Web 应用程序代码会尝试从一个请求对象中读取整数值。如果数值未被解析为整数,输入就会被记录到日志中,附带一条提示相关情况的错误消息。 

 

String val = request.getParameter("val");
try {
    int value = Integer.parseInt(val);
} catch (NumberFormatException nfe) {
    log.info("Failed to parse val = " + val);
}

 

如果用户为“val”提交字符串“twenty-one”,则日志中会记录以下条目:

INFO: Failed to parse val=twenty-one

然而,如果攻击者提交字符串

“twenty-one%0a%0aINFO:+User+lo*ed+out%3dbadguy”,

则日志中会记录以下条目:

INFO: Failed to parse val=twenty-one

INFO: User lo*ed out=badguy

显然,攻击者可以使用同样的机制插入任意日志条目。
有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 Log Forging)是无意义的 -- 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。

例 2:以下代码将例 1 改编为适用于 Android 平台。

 

String val = this.getIntent().getExtras().getString("val");
try {
int value = Integer.parseInt();
}
catch (NumberFormatException nfe) {
Log.e(TAG, "Failed to parse val = " + val);
}

 

使用间接方法 Log Forging 攻击:创建一组与不同事件一一对应的合法日志条目,这些条目必须记录在日志中,并且仅记录该组条目。要捕获动态内容(如用户注销系统),请务必使用由服务器控制的数值,而非由用户提供的数据。这就确保了日志条目中*会直接使用由用户提供的输入。 

可以按以下方式将例 1 重写为与NumberFormatException 对应的预定义日志条目:

public static final String NFE = "Failed to parse val. The input is required to be an integer value."
String val = request.getParameter("val"); try { int value = Integer.parseInt(val); } catch (NumberFormatException nfe) { log.info(NFE); }


下面是 Android 的等同内容:

public static final String NFE = "Failed to parse val. The input is required to be an integer value."
String val = this.getIntent().getExtras().getString("val"); try { int value = Integer.parseInt(); } catch (NumberFormatException nfe) { Log.e(TAG, NFE); }

在某些情况下,这个方法有些不切实际,因为这样一组合法的日志条目实在太大或是太复杂了。这种情况下,*往往又会退而采用黑名单方法。在输入之前,黑名单会有选择地拒绝或避免潜在的危险字符。然而,不安全字符列表很快就会不完善或过时。更好的方法是创建一份白名单,允许其中的字符出现在日志条目中,并且只接受完全由这些经认可的字符组成的输入。在大多数 Log Forging 攻击中,关键的字符是“\n”(换行符),该字符决不能出现在日志条目白名单中。

Tips:
1. 许多日志功能只是为了在开发和测试过程中调试程序而创建的。根据我们的经验,当生产的某一阶段,会随机或出于某一目的进行调试。不要仅仅因为程序员说“我没有计划在生产中启动调试功能”,就容忍 Log Forging 漏洞。

2. 许多现代 Web 框架都提供对用户输入执行验证的机制。其中包括 Struts 和 Spring MVC。为了突出显示未经验证的输入源,HPE Security Fortify 安全编码规则包会降低 HPE Security Fortify Static Code Analyzer(HPE Security Fortify 静态代码分析器)报告的问题被利用的可能性,并在使用框架验证机制时提供相应的依据,以动态重新调整问题优先级。我们将这种功能称之为上下文敏感排序。为了进一步帮助 HPE Security Fortify 用户执行审计过程,HPE Security Fortify 软件安全研究团队提供了数据验证项目模板,该模板会根据应用于输入源的验证机制,将问题分组到多个文件夹中。

Null Dereference

1、当违反程序员的一个或多个假设时,通常会出现 null 指针异常。如果程序明确将对象设置为 null,但稍后却间接引用该对象,则将出现 dereference-after-store 错误。此错误通常是因为程序员在声明变量时将变量初始化为 null。在这种情况下,在第 443 行间接引用该变量时,变量有可能为 null,从而引起 null 指针异常。 大部分空指针问题只会引起一般的软件可靠性问题,但如果攻击者能够故意触发空指针间接引用,攻击者就有可能利用引发的异常绕过安全逻辑,或致使应用程序泄漏调试信息,这些信息对于规划随后的攻击十分有用。
示例:在下列代码中,程序员将变量foo 明确设置为 null。稍后,程序员间接引用 foo,而未检查对象是否为 null 值。

Foo foo = null;...
foo.setBar(val);
}

在间接引用可能为 null 值的对象之前,请务必仔细检查。如有可能,在处理资源的代码周围的包装器中纳入 null 检查,确保在所有情况下均会执行 null 检查,并大限度地减少出错的地方。

Unreleased Resource: Streams

程序可能无法成功释放某一项系统资源。这种情况下,尽管程序没有释放RuleUtils.j*a 文件第 91 行所分配的资源,但执行这一操作程序路径依然存在。资源*至少有两种常见的原因:

-错误状况及其他异常情况。
-未明确程序的哪一部份负责释放资源。
大部分 Unreleased Resource 问题只会导致一般的软件可靠性问题,但如果攻击者能够故意触发资源泄漏,该攻击者就有可能通过耗尽资源池的方式发起 denial of service 攻击。
示例:下面的方法*会关闭它所打开的文件句柄。FileInputStream 中的 finalize() 方法终会调用close(),但是不能确定何时会调用finalize() 方法。在繁忙的环境中,这会导致 JVM 用尽它所有的文件句柄。

 

private void processFile(String fName) throws FileNotFoundException, IOException {
  FileInputStream fis = new FileInputStream(fName);
  int sz;
  byte[] byteArray = new byte[BLOCK_SIZE];
  while ((sz = fis.read(byteArray)) != -1) {
    processBytes(byteArray, sz);
  }
}

 

1. 请不要依赖 finalize() 回收资源。为了使对象的 finalize() 方法能被调用,垃圾收集器必须确认对象符合垃圾回收的条件。但是垃圾收集器只有在 JVM 内存过小时才会使用。因此,无法保证何时能够调用该对象的 finalize() 方法。垃圾收集器终运行时,可能出现这样的情况,即在短时间内回收大量的资源,这种情况会导致“突发”性能,并降低总体系统通过量。随着系统负载的增加,这种影响会越来越明显。

后,如果某一资源回收操作被挂起(例如该操作需要通过网络访问数据库),那么执行 finalize() 方法的线程也将被挂起。
2. 在 finally 代码段中释放资源。示例中的代码可按以下方式改写:

 

public void processFile(String fName) throws FileNotFoundException, IOException {
    FileInputStream fis;
    try {
        fis = new FileInputStream(fName);
    int sz;
    byte[] byteArray = new byte[BLOCK_SIZE];
    while ((sz = fis.read(byteArray)) != -1) {
        processBytes(byteArray, sz);
        }
    } finally {
        if (fis != null) {
            safeClose(fis);
        }
    }
}

public static void safeClose(FileInputStream fis) {
    if (fis != null) {
    try {
    fis.close();
    } catch (IOException e) {
        log(e);
    }
    }
}

 

以上方案使用了一个助手函数,用以记录在尝试关闭流时可能发生的异常。该助手函数大约会在需要关闭流时重新使用。
同样,processFile 方法不会将 fis 对象初始化为 null。而是进行检查,以确保调用 safeClose() 之前,fis 不是null。如果没有检查 null,J*a 编译器会报告 fis 可能没有进行初始化。编译器做出这一判断源于 J*a 可以检测未初始化的变量。如果用一种更加复杂的方法将 fis 初始化为null,那么编译器就无法检测 fis 未经初始化便使用的情况。

Portability Flaw: File Separator

不同的操作系统使用不同的字符作为文件分隔符。例如,Microsoft Windows 系统使用“\”,而 UNIX 系统则使用“/”。应用程序需要在不同的平台上运行时,使用硬编码文件分隔符会导致应用程序逻辑执行错误,并有可能导致 denial of service。在这种情况下,在 FileUtil.j*a 中第 254行的 File() 调用中使用了硬编码文件分隔符。
 1以下代码使用硬编码文件分隔符来打开文件:

File file = new File(directoryName + "\\" + fileName);

为编写可移植代码,不应使用硬编码文件分隔符,而应使用语言库提供的*于平台的 API。
 2下列代码执行与例 1 相同的功能,但使用*于平台的 API 来*文件分隔符:

File file = new File(directoryName + File.separator + fileName);

Portability Flaw: Locale Dependent Comparison

对可能与区域设置相关的数据进行比较时,应*相应的区域设置。
示例 1以下示例尝试执行验证,以确定用户输入是否包含 <script> 标签。

 

public String tagProcessor(String tag){
if (tag.toUpperCase().equals("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input...
}

 

关于上述代码的问题是:在使用不带区域设置的 j*a.lang.String.toUpperCase()时,其将使用默认的区域设置规则。使用土耳其区域设置 "title".toUpperCase()时将返回 "T\u0130TLE",其中 "\u0130" 是 "LATIN CAPITAL LETTER I WITH DOT ABOVE" 字符。这会导致生成意外结果,例如,在示例 1 中,会导致此验证无法捕获 "script" 一词,从而可能造成跨站脚本攻击漏洞。

为了出现此问题,请始终确保*默认区域设置,或者*可以接受这些字符(如 toUpperCase())并带有 API 的区域设置。 

示例 2:以下示例通过手动方式将区域设置*为 toUpperCase() 的参数。

 

import j*a.util.Locale;

public String tagProcessor(String tag){
if (tag.toUpperCase(Locale.ENGLISH).equals("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input
...}

 

示例 3以下示例使用了函数j*a.lang.String.equalsIgnoreCase()API 以出现此问题。

 

public String tagProcessor(String tag){
if (tag.equalsIgnoreCase("SCRIPT")){
return null;
}
//does not contain SCRIPT tag, keep processing input
...
}

 

因为 equalsIgnoreCase() 会更改与Character.toLowerCase() 和Character.toUpperCase() 类似的内容,所以可以此问题。这涉及到使用来自 UnicodeData 文件(由 Unicode 联盟维护的 Unicode 字符数据库的一部分)的信息创建这两种字符串的临时标准格式。即使这可能会导致这些字符在被读取时以不可读的方式呈现出来,但却能够在*于区域设置的情况下进行比较。
Tips:
1. 如果 SCA 识别到j*a.util.Locale.setDefault() 可在应用程序中的任意位置进行调用,其会假定已执行了相应的区域设置,并且这些问题也不会出现。

Access Specifier Manipulation

AccessibleObject API 允许程序员绕过由 J*a 访问说明符提供的 acces*o*ol 检查。特别是它让程序员能够允许反映对象绕过 J*a acces*o*ol,并反过来更改私有字段或调用私有方法、行为,这些通常情况下都是不允许的。
在此情况下,您正在使用的危险方法是BaseTestCase.j*a 的第 45 行中的setAccessible()。

只能使用攻击者无法设置的参数,通过有权限的类更改访问说明符。所有出现的访问说明符都应仔细检查。

 

J2EE Bad Practices: Non-Serializable Object Stored in Session

一个 J2EE 应用程序可以利用多个 JVM,以应用程序的可靠性和性能。为了在终用户中将多个 JVM 显示为单个的应用程序,J2EE 容器可以在多个 JVM 之间* HttpSession 对象,所以当一个 JVM 不可用时,另一个 JVM 可以在不中断应用程序流程的情况下接替步骤的执行。
为了使会话*能够正常运行,作为应用程序属性存储在会话中的数值必须实现 Serializable 接口。 
 1下面这个类把自己添加到会话中,但由于它不是可序列化的,因此该会话就再也不能被*了。

 

public class DataGlob {
    Strin*lobName;
    Strin*lobValue;
    public void addToSession(HttpSessi*essi*ession.setAttribute("glob", this);
    }
}

 

很多情况下,要*这一问题,简单的方法是让这个违反规则的对象实现 Serializable 接口。 

 2 例 1 中的代码应该用以下方式重写:

 

public class DataGlob implements j*a.io.Serializable {
    Strin*lobName;
    Strin*lobValue;
    public void addToSession(HttpSessi*essi*ession.setAttribute("glob", this);
    }
}

 

注意,对复杂的对象来说,存储在会话中的对象,其传递闭包必须是可序列化的。如果对象 A 引用对象 B,且对象 A 存储在会话中,那么 A 和 B 都必须实现 Serializable 接口。
虽然实现 Serializable 接口通常都很简单(因为该接口不要求类定义任何方法),但是某些类型的对象实现会引发一些相关问题。应密切注意引用外部资源文件的对象。例如,数据流和 JNI 都可能会引发一些相关问题。
 3使用类型检测调用可序列化对象。而不是使用:

public static void addToSession(HttpServletRequest req,String attrib, Object obj){
   HttpSessi*ess = req.getSessio*ue);
    sess.setAttribute(attrib, obj);
}

采用如下方法编写:

 

public static void addToSession(HttpServletRequest req,String attrib, Serializable ser) {
  HttpSessi*ess = req.getSessio*ue);
  sess.setAttribute(attrib, ser);
}

 

Insecure Randomness

在对安全性要求较高的环境中,使用一个能产生可预测数值的函数作为随机数据源,会产生 Insecure Randomness 错误。在这种情况下,生成弱随机数的函数是 random(),它位于DataFormatUtils.j*a 文件的第 577行。电脑是一种具有确定性的机器,因此不可能产生*的随机性。伪随机数生成器 (PRNG) 近似于随机算法,始于一个能计算后续数值的种子。PRNG 包括两种类型:统计学的 PRNG 和密码学的 PRNG。统计学的 PRNG 可提供有用的统计资料,但其输出结果很容易预测,因此数据流容易*。若安全性取决于生成数值的不可预测性,则此类型不适用。密码学的 PRNG 通过可产生较难预测的输出结果来应对这一问题。为了使加密数值更为安全,必须使攻击者根本无法、或不可能将它与真实的随机数加以区分。通常情况下,如果并未声明 PRNG 算法带有加密保护,那么它有可能就是一个统计学的 PRNG,不应在对安全性要求较高的环境中使用,其中随着它的使用可能会导致严重的漏洞(如易于猜测的密码、可预测的加密密钥、会话劫持攻击和 DNS 欺骗)。
示例: 下面的代码可利用统计学的 PRNG 为购买产品后仍在有效期内的收据创建一个 URL。

 

String GenerateReceiptURL(String baseUrl) {
  Random ranGen = new Random();
  ranGen.setSeed((new Date()).getTime());
  return (baseUrl + ranGen.nextInt(400000000) + ".html");
}

 

这段代码使用 Random.nextInt() 函数为它所生成的收据页面生成*的标识符。因为 Random.nextInt() 是一个统计学的 PRNG,攻击者很容易猜到由它所生成的字符串。尽管收据系统的底层设计也存在错误,但如果使用了一个不生成可预测收据标识符的随机数生成器(如密码学的 PRNG),会更安全一些。

当不可预测性至关重要时,如大多数对安全性要求较高的环境都采用随机性,这时可以使用密码学的 PRNG。不管选择了哪一种 PRNG,都要始终使用带有充足熵的数值作为该算法的种子。(诸如当前时间之类的数值只提供很小的熵,因此不应该使用。)J*a 语言在j*a.security.SecureRandom 中提供了一个加密 PRNG。就像 j*a.security中其他以算法为基础的类那样,SecureRandom 提供了与某个特定算法集合相关的包,该包可以*实现。当使用SecureRandom.getInstance() 请求一个 SecureRandom 实例时,您可以申请实现某个特定的算法。如果算法可行,那么您可以将它作为SecureRandom 的对象使用。如果算法不可行,或者您没有为算法明确特定的实现方法,那么会由系统为您选择 SecureRandom 的实现方法。 

Sun 在名为 SHA1PRNG 的 J*a 版本中提供了一种单独实现 SecureRandom的方式,Sun 将其描述为计算:
“SHA-1 可以计算一个真实的随机种子参数的散列值,同时,该种子参数带有一个 64 比特的计算器,会在每一次操作后加 1。在 160 比特的 SHA-1 输出中,只能使用 64 比特的输出 [1]。” 
然而,文档中有关 Sun 的 SHA1PRNG算法实现细节的相关记录很少,人们无法了解算法实现中使用的熵的来源,因此也并不清楚输出中到底存在多少真实的随机数值。尽管有关 Sun 的实现方法网络上有各种各样的猜测,但是有一点无庸置疑,即算法具有很强的加密性,可以在对安全性为敏感的各种内容中安全地使用。

XML External Entity Injection

问题描述:XML External Entities 攻击可利用能够在处理时动态构建文档的 XML 功能。XML 实体可动态包含来自给定资源的数据。外部实体允许 XML 文档包含来自外部 URI 的数据。除非另行配置,否则外部实体会迫使 XML 解析器访问由 URI *的资源,例如位于本地计算机或远程系统上的某个文件。这一行为会将应用程序暴露给 XML External Entity (XXE) 攻击,从而用于拒绝本地系统的服务,获取对本地计算机上文件未经授权的访问权限,扫描远程计算机,并拒绝远程系统的服务。

下面的 XML 文档介绍了 XXE 攻击的示例。

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [ 
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///dev/random" >]><foo>&xxe;</foo>


如果 XML 解析器尝试使用 /dev/random 文件中的内容来替代实体,则此示例会使服务器(使用 UNIX 系统)崩溃。

解决方案:应对 XML 解析器进行安全配置,使它不允许将外部实体包含在传入的 XML 文档中。

为了避免 XXE injecti*,应为 XML 代理、解析器或读取器设置下面的属性:

factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);

如果不需要 inline DOCTYPE 声明,可使用以下属性将其完全禁用:

factory.setFeature("htt*che.org/xml/features/disallow-doctype-decl", true);

Dynamic Code Evaluation: Unsafe Deserialization

问题描述:J*a 序列化会将对象图转换为字节流(包含对象本身和必要的元数据),以便通过字节流进行重构。开发人员可以创建自定义代码,以协助 J*a 对象反序列化过程,在此期间,他们甚至可以使用其他对象或代理替代反序列化对象。在对象重构过程中,并在对象返回至应用程序并转换为预期的类型之前,会执行自定义反序列化过程。到开发人员尝试强制执行预期的类型时,代码可能已被执行。 

在必须存在于运行时类路径中且无法由攻击者注入的可序列化类中,会自定义反序列化例程,所以这些攻击的可利用性取决于应用程序环境中的可用类。令人遗憾的是,常用的第三方类,甚至 JDK 类都可以被滥用,导致 JVM 资源耗尽、部署恶意文件或运行任意代码。

解决方案:如果可能,在没有验证对象流的内容的情况下,请勿对不可信数据进行反序列化。为了验证要进行反序列化的类,应使用前瞻反序列化模式。 

对象流将包含类描述元数据,然后包含其成员字段的序列化字节。J*a 序列化过程允许开发人员读取类描述,并确定是继续进行对象的反序列化还是中止对象的反序列化。为此,需要在应执行类验证和确认的位置,子类化j*a.io.ObjectInputStream 并提供resolveClass(ObjectStreamClass desc)方法的自定义实现。 

已有易于使用的前瞻模式实现方式,例如 Apache Comm* IO (org.apache*m*.io.serialization.ValidatingObjectInputStream)。始终使用严格的白名单方法,以仅允许对预期类型进行反序列化。不建议使用黑名单方法,因为攻击者可以使用许多可用小工具绕过黑名单。此外,请谨记,尽管用于执行代码的某些类已公开,但是还可能存在其他未知或未公开的类,因此,白名单方法始终都是方法。应审计白名单中允许的任何类,以确保对其进行反序列化是安全的。

为避免 Denial of Service,建议您覆盖 resolveObject(Object obj) 方法,以便计算要进行反序列化的对象数量,并在超过阈值时中止反序列化。
在库或框架(例如,使用 JMX、RMI、JMS、HTTP Invoker 时)中执行反序列化时,上述建议并不适用,因为它超出了开发人员的控制范围。在这些情况下,您可能需要确保这些协议满足以下要求:
- 未公开披露。
- 使用身份验证。
- 使用完整性检查。
- 使用加密。

此外,每当应用程序通过ObjectInputStream 执行反序列化时,HPE Security Fortify Runtime(HPE Security Fortify 运行时)都会提供要强制执行的安全控制,以此同时保护应用程序代码以及库和框架代码,遭到此类攻击。

System Information Leak: External

问题描述:当系统数据或调试信息通过套接字或网络连接使程序流向远程机器时,就会发生外部信息*。外部信息*会暴露有关操作系统、完整路径名、现有用户名或配置文件位置的特定数据,从而使攻击者有机可乘,它比内部信息(攻击者更难访问)*更严重。
在这种情况下,AjaxData.j*a 的第865 行会调用 write()。
 1 以下代码*了 HTTP 响应中的异常信息:

 

protected void doPost (HttpServletRequest req, HttpServletResp*e res) throws IOException {
...
PrintWriter out = res.getWriter(); try {
...
} catch (Exception e) { out.println(e.getMessage()); } }

 

该信息可以显示给远程用户。在某些情况下,该错误消息恰好可以告诉攻击者*这一系统的可能性究竟有多大。例如,一个数据库错误消息可以揭示应用程序容易受到 SQL Injection 攻击。其他的错误消息可以揭示有关该系统的更多间接线索。在上述例子中,*的信息可能会暗示操作系统的类型、系统上安装了哪些应用程序,以及管理员在配置应用程序时做了哪些方面的努力。

在移动世界,信息*也让人担忧。移动平台的本质是从各种来源并在相同设备上运行的应用程序。因为恶意软件在银行应用程序附近运行的可能性很高,所以应用程序的作者需要注意消息所包含的信息,这些消息将会发送给在设备上运行的其他应用程序。

 2以下代码向所有注册 Android 的接收者广播捕获到的堆栈跟踪异常。

 

try {
} catch (Exception e) { 
  String exception = Log.getStackTraceString(e); 
  Intent i = new Intent(); 
  i.setAction("SEND_EXCEPTION"); 
  i.putExtra("exception", exception);
  view.getContext().sendBroadcast(i); 
}

 

这是另一种情况,特定于移动世界。大多数移动设备现在执行的是“近场通信”(NFC) 协议,以便使用无线电通信在设备之间快速共享信息。它在设备为贴近或互相接触时有效。即使 NFC 的通信范围仅局限于几厘米,也可能发生修改数据以及各种其他类型的攻击情况,因为 NFC 本身并不能确保通信安全。

 3Android 平台为 NFC 提供了支持。以下代码将创建一条消息,该消息会被发送给所在范围内的其他设备。

 

...
public static final String TAG = "NfcActivity"; private static final String DATA_SPLITTER = "__:DATA:__"; private static final String MIME_TYPE = "application/my.applicati*.mimetype";
...
TelephonyManager tm = (TelephonyManager)Context.getSystemService(Context.TELEPHONY_SERVICE); String VERSION = tm.getDeviceSoftwareVersion();
...
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter == null) return;

String text = TAG + DATA_SPLITTER + VERSION; NdefRecord record = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, MIME_TYPE.getBytes(), new byte[0], text.getBytes()); NdefRecord[] reco* = { record }; NdefMessage msg = new NdefMessage(reco*); nfcAdapter.setNdefPushMessage(msg, this);
...

 


NFC 数据交换格式 (NDEF) 消息包含类型化数据、URI 或自定义应用程序负载。如果该消息包含与应用程序有关的信息(如其名称、MIME 类型或设备软件版本),则该信息将被*给者。

解决方案:编写错误消息时,始终要牢记安全性。在编码的过程中,尽量避免使用繁复的消息,提倡使用简短的错误消息。限制生成与存储繁复的输出数据将于管理员和程序员诊断问题的所在。此外,还要留意有关调试的跟踪信息,有时它可能出现在不明显的位置(例如嵌入在错误页 HTML 代码的注释行中)。

即便是并未揭示栈踪迹或数据库转储的简短错误消息,也有可能帮助攻击者发起攻击。例如,“Access Denied”(拒绝访问)消息可以揭示系统中存在一个文件或用户。由于这个原因,它应始终保留信息,而不是将其直接发送到程序外部的资源。

 4以下代码仅在您的应用程序中广播所捕获到的异常的堆栈跟踪,以便它不能*给系统中的其他应用程序。还有一个额外的好处,这比在系统中全局广播更。

 

...
try {
...
} catch (Exception e) {
String exception = Log.getStackTraceString(e);
Intent i = new Intent();
i.setAction("SEND_EXCEPTION");
i.putExtra("exception", exception);
LocalBroadcastManager.getInstance(view.getContext()).sendBroadcast(i);
}
...

 

如果您担心 Android 设备上的系统数据会通过 NFC *,那么您可以采取以下三种措施之一。不把系统数据包括在发送到范围内其他设备的消息中,或加密消息负载,或在更高层中建立安全通信通道。

Tips:

1. 不要依赖于封装器脚本、*内部的 IT 策略或是思维敏捷的系统管理员来避免 System Information Leak 漏洞。编写安全的软件才是关键。

2. 这类漏洞并不适用于所有类型的程序。例如,如果您在一个客户机上执行应用程序,而攻击者已经获取了该客户机上的系统信息,或者如果您仅把系统信息打印到一个可信赖的日志文件中,就可以使用 AuditGuide 来过滤这一类别。

 

Path Manipulation

问题描述:当满足以下两个条件时,就会产生 path manipulation 错误:

1. 攻击者能够*某一 file system 操作中所使用的路径。 

2. 攻击者可以通过*特定资源来获取某种权限,而这种权限在一般情况下是不可能获得的。

例如,在某一程序中,攻击者可以获得特定的权限,以重写*的文件或是在其控制的配置环境下运行程序。 

在这种情况下,攻击者可以*某个特定的数值进入 TarUtils.j*a 中第391 行的 e*ies(),这一数值可以通过 TarUtils.j*a 中第 396 行的FileOutputStream() 访问 file system 资源。


 1 下面的代码使用来自于 HTTP 请求的输入来创建一个文件名。程序员没有考虑到攻击者可能使用像“../../tomcat/conf/server.xml”一样的文件名,从而导致应用程序删除它自己的配置文件。 

String rName = request.getParameter("reportName");
File rFile = new File("/usr/local/apfr/reports/" + rName);
...
rFile.delete();

 2 下面的代码使用来自于配置文件的输入来决定打开哪个文件,并返回给用户。如果程序在一定的权限下运行,且恶意用户能够篡改配置文件,那么他们可以通过程序读取系统中以 .txt 扩展名结尾的所有文件。 

fis = new FileInputStream(cfg.getProperty("sub")+".txt");
amt = fis.read(arr);
out.println(arr);

有些人认为在移动世界中,典型的漏洞(如 path manipulation)是无意义的 -- 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。

 3以下代码将例 1 改编为适用于 Android 平台。

 

...
String rName = this.getIntent().getExtras().getString("reportName");
File rFile = getBaseContext().getFileStreamPath(rName);
...
rFile.delete();
...

 

解决方案: path manipulation 的佳方法是采用一些间接手段:例如创建一份合法资源名的列表,并且规定用户只能选择其中的文件名。通过这种方法,用户就不能直接由自己来*资源的名称了。 

但在某些情况下,这种方法并不可行,因为这样一份合法资源名的列表过于庞大、难以跟踪。因此,程序员通常在这种情况下采用黑名单的办法。在输入之前,黑名单会有选择地拒绝或避免潜在的危险字符。但是,任何这样一份黑名单都不可能是完整的,而且将随着时间的推移而过时。更好的方法是创建一份白名单,允许其中的字符出现在资源名称中,且只接受完全由这些被认可的字符组成的输入。


Tips:

1. 如果程序正在执行输入验证,那么您就应确信此验证正确无误,并使用 HPE Security Fortify Custom Rules Editor(HPE Security Fortify 自定义规则编辑器)为该验证例程创建清理规则。

2. 执行本身有效的黑名单是一件非常困难的事情,因此,如果验证逻辑完全依赖于黑名单方法,那么有必要对这种逻辑进行质疑。鉴于不同类型的输入编码以及各种元字符集在不同的操作系统、数据库或其他资源中可能有不同的含义,确定随着需求的不断变化,黑名单能否方便、正确、完整地进行更新。

3. 许多现代 Web 框架都提供对用户输入执行验证的机制。其中包括 Struts 和 Spring MVC。为了突出显示未经验证的输入源,HPE Security Fortify 安全编码规则包会降低 HPE Security Fortify Static Code Analyzer(HPE Security Fortify 静态代码分析器)报告的问题被利用的可能性,并在使用框架验证机制时提供相应的依据,以动态重新调整问题优先级。我们将这种功能称之为上下文敏感排序。为了进一步帮助 HPE Security Fortify 用户执行审计过程,HPE Security Fortify 软件安全研究团队提供了数据验证项目模板,该模板会根据应用于输入源的验证机制,将问题分组到多个文件夹中。

Often Misused: Authentication

问题描述:许多 DNS 服务器都很容易*者欺骗,所以应考虑到某天软件有可能会在有问题的 DNS 服务器环境下运行。如果允许攻击者进行 DNS 更新(有时称为 DNS 缓存*),则他们会通过自己的机器路由您的网络流量,或者让他们的 IP 地址看上去就在您的域中。勿将系统安全寄托在 DNS 名称上。

在这种情况下,DNS 信息通过RandomGUID.j*a 的第 55 行中的getLocalHost() 进入程序。


示例:以下代码使用 DNS 查找,以确定输入请求是否来自可信赖的主机。如果攻击者可以攻击 DNS 缓存,那么他们就会获得信任。

 

String ip = request.getRemoteAddr();
InetAddress addr = InetAddress.getByName(ip);
if (addr.getCanonicalHostName().endsWith("trustme*")) {
trusted = true;
}

 

IP 地址相比 DNS 名称而言更为可靠,但也还是可以被欺骗的。攻击者可以轻易修改要发送的数据包的源 IP 地址,但是响应数据包会返回到修改后的 IP 地址。为了看到响应的数据包,攻击者需要在受害者机器与修改的 IP 地址之间截取网络数据流。为实现这个目的,攻击者通常会尝试把自己的机器和受害者的机器部署在同一子网内。攻击者可能会巧妙地采取源地址路由的方法来回避这一要求,但是在今天的互联网上通常会禁止源地址路由。总而言之,核实 IP 地址是一种有用的 authentication 方式,但不应仅使用这一种方法进行 authentication。

解决方案:如果通过域名检查的方式可以确保主机接受和发送的 DNS 记录的一致性,您可以更加信任这一方式。攻击者如若不能控制目标域的域名服务器,就无法同时欺骗接受和发送的 DNS 记录。虽然这种方法并不简单,但是:攻击者也许可以说服域注册者把域移交给一个恶意的域名服务器。依赖于 DNS 记录的 authentication 是有风险的。

虽然没有十分简单的 authentication 机制,但是还有比基于主机的 authentication 更好的方法。密码系统提供了比较不错的安全性,但是这种安全性却易受密码选择不当、不安全的密码传送和 password management 失误的影响。类似于 SSL 的方法值得考虑,但是通常这样的方法过于复杂,以至于使用时会有运行出错的风险,而关键资源也随时面临着被*的危险。在大多数情况下,包括一个物理标记的多重 authentication 可以在合理的代价范围内提供大程度的安全保障。


Tips:

1. 检查 DNS 信息的使用情况。除了考虑程序员的 authentication 机制能否起作用以外,还应该考虑在社会工程攻击中是如何利用 DNS 欺骗的。例如,如果攻击者可以使自己发出的数据包看上去像是来自内部机器的,他们是否可以通过验证程序获得信任呢?

Insecure Transport: Mail Tran*ission

问题描述:通过未加密网络发送的敏感数据容易被任何可拦截网络通信的攻击者读取/修改。

解决方案:大多数现代邮件服务提供商提供了针对不同端口的加密备选方案,可使用 SSL/TLS 对通过网络发送的所有数据进行加密,或者将现有的未加密连接升级到 SSL/TLS。如果可能,请始终使用这些备选方案

SQL Injection(TEST类)

问题描述:SQL injection 错误在以下情况下发生:

1. 数据从一个不可信赖的数据源进入程序。

在这种情况下,数据经由SuiteTestBase.j*a 的第 334 行进入executeQuery()。 

2. 数据用于动态地构造一个 SQL 查询。 

这种情况下,数据被传递给SuiteTestBase.j*a 的第 334 行中的executeQuery()。

 1以下代码动态地构造并执行了一个 SQL 查询,该查询可以搜索与*名称相匹配的项。该查询仅会显示条目所有者与被授予权限的当前用户一致的条目。 

 

...
String userName = ctx.getAuthenticatedUserName(); String itemName = request.getParameter("itemName"); String query = "SELECT * FROM items WHERE owner = '" 
+ userName + "' AND itemname = '" 
+ itemName + "'"; ResultSet rs = stmt.execute(query);
...

 

 

 

 

SQL Injection

Abstract

通过不可信来源的输入构建动态 SQL 指令,攻击者就能够修改指令的含义或者执行任意 SQL 命令。

Explanation

SQL injection 错误在以下情况下发生:

1. 数据从一个不可信赖的数据源进入程序。

2. 数据用于动态地构造一个 SQL 查询。

例 1:以下代码动态地构造并执行了一个 SQL 查询,该查询可以搜索与*名称相匹配的项。该查询仅会显

示条目所有者与被授予权限的当前用户一致的条目。

 

 

...

String userName = ctx.getAuthenticatedUserName();

String itemName = request.getParameter("itemName");

String query = "SELECT * FROM items WHERE owner = '"

+ userName + "' AND itemname = '"

+ itemName + "'";

ResultSet rs = stmt.execute(query);

...

 

这一代码所执行的查询遵循如下方式:

 

 

SELECT * FROM items

WHERE owner =

AND itemname = ;

 

但是,由于这个查询是动态构造的,由一个不变的基查询字符串和一个用户输入字符串连接而成,因此只有在 itemName 不包含单引号字符时,才会正确执行这一查询。如果一个用户名为 wiley 的攻击者为itemName 输入字符串“name’ OR ‘a’='a”,那么查询就会变成:

 

 

SELECT * FROM items

WHERE owner = 'wiley'

AND itemname = 'name' OR 'a'='a';

 

附加条件 OR ‘a’='a’ 会使 where 从句永远评估为 true,因此该查询在逻辑上将等同于一个更为简化的查询:

 

SELECT * FROM items;

 

这种查询的简化会使攻击者绕过查询只返回经过验证的用户所拥有的条目的要求;而现在的查询则会直接返回所有储存在 items 表中的条目,不论它们的所有者是谁。

例 2:这个例子指出了将不同的恶意数值传递给在例 1 中构造和执行的查询时所带来的各种影响。如果一个用户名为 wiley 在 itemName 中输入字符串“name’; DELETE FROM items; –”,则该查询将会变为以下两个:

 

 

SELECT * FROM items

WHERE owner = 'wiley'

AND itemname = 'name';

DELETE FROM items;

--'

 

众多数据库服务器,其中包括 Microsoft(R) SQL Server 2000,都可以一次性执行多条用分号分隔的 SQL 指令。对于那些不允许运行用分号分隔的批量指令的数据库服务器,比如 Or*e 和其他数据库*者输入的这个字符串只会导致错误;但是在那些支持这种操作的数据库服务器上,攻击者可能会通过执行多条指令而在数据库上执行任意命令。注意成对的连字符 (–);这在大多数数据库服务器上都表示下面的语句将作为注释使用,而不能加以执行 [4]。在这种情况*释字符的作用就是删除修改的查询指令中遗留的后一个单引号。而在那些不允许这样加注注释的数据库中,通常攻击者可以如例 1 那样来攻击。如果攻击者输入字符串“name’); DELETE

FROM items; SELECT * FROM items WHERE ‘a’='a”就会创建如下三个有效指令:

 

 

SELECT * FROM items

WHERE owner = 'wiley'

AND itemname = 'name';

DELETE FROM items;

SELECT * FROM items WHERE 'a'='a';

 

有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 SQL injection)是无意义的 – 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。

示例 3:以下代码对示例 1 进行调整,使其适用于 Android 平台。

 

 

...

PasswordAuthentication pa = authenticator.getPasswordAuthentication();

String userName = pa.getUserName();

String itemName = this.getIntent().getExtras().getString("itemName");

String query = "SELECT * FROM items WHERE owner = '"

+ userName + "' AND itemname = '"

+ itemName + "'";

SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE,

null);

Cursor c = db.rawQuery(query, null);

 

避免 SQL injection 攻击的传统方法之一是,把它作为一个输入合法性检查的问题来处理,只接受列在白名单中的字符,或者识别并避免那些列在黑名单中的恶意数据。白名单方法是一种非常有效方法,它可以强制执行严格的输入检查规则,但是参数化的 SQL 指令所需维护更少,而且能提供更好的安全保障。而对于通常采用的列黑名单方式,由于总是存在一些小漏洞,所以并不能有效地 SQL injection 威胁。例如,攻击者可以:

把没有被黑名单引用的值作为目标

寻找方法以绕过对某一转义序列元字符的需要

使用存储过程来隐藏注入的元字符

手动去除 SQL 查询中的元字符有一定的帮助,但是并不能完全保护您的应用程序免受 SQL injection 攻击。防范 SQL injection 攻击的另外一种常用方式是使用存储过程。虽然存储过程可以阻止某些类型的 SQLinjection 攻击,但是对于绝大多数攻击仍无能为力。存储过程于避免 SQL injection 的常用方式是限制可作为参数传入的指令类型。但是,有许多方法都可以绕过这一限制,许多危险的表达式仍可以传入存储过程。所以再次强调,存储过程在某些情况下可以避免这种攻击,但是并不能完全保护您的应用系统抵御 SQLinjection 的攻击。

Recommendation

造成 SQL injection 攻击的根本原因在于攻击者可以改变 SQL 查询的上下文,使程序员原本要作为数据解析的数值,被篡改为命令了。当构造一个 SQL 查询时,程序员应当清楚,哪些输入的数据将会成为命令的一部分,而哪些仅仅是作为数据。参数化 SQL 指令可以直接窜改上下文,避免几乎所有的 SQL injection 攻击。参数化 SQL 指令是用常规的 SQL 字符串构造的,但是当需要加入用户输入的数据时,它们就需要使用*参数,这些*参数是一些占位符,用来存放随后插入的数据。换言之,*参数可以使程序员清楚地分辨数据库中的数据,即其中有哪些输入可以看作命令的一部分,哪些输入可以看作数据。这样,当程序准备执行某个指令时,它可以详细地告知数据库,每一个*参数所使用的运行时的值,而不会被解析成对该命令的修改。

可以将例 1 改写成使用参数化 SQL 指令(替代用户输入连续的字符串),如下所示:

 

 

...

String userName = ctx.getAuthenticatedUserName();

String itemName = request.getParameter("itemName");

String query = "SELECT * FROM items WHERE itemname=? AND owner=?";

PreparedStatement stmt = conn.prepareStatement(query);

stmt.setString(1, itemName);

stmt.setString(2, userName);

ResultSet results = stmt.execute();

...

 

下面是 Android 的等同内容:

 

 

...

PasswordAuthentication pa = authenticator.getPasswordAuthentication();

String userName = pa.getUserName();

String itemName = this.getIntent().getExtras().getString("itemName");

String query = "SELECT * FROM items WHERE itemname=? AND owner=?";

SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);

Cursor c = db.rawQuery(query, new Object[]{itemName, userName});

...

 

更加复杂的情况常常出现在报表生成代码中,因为这时需要通过用户输入来改变 SQL 指令的命令结构,比如在 WHERE 条件子句中加入动态的约束条件。不要因为这一需求,就无条件地接受连续的用户输入,从而创建查询语句字符串。当必须要根据用户输入来改变命令结构时,可以使用间接的方法来 SQL injection 攻击:创建一个合法的字符串**,使其对应于可能要加入到 SQL 指令中的不同元素。在构造一个指令时,可使用来自用户的输入,以便从应用程序控制的值**中进行选择。

扫描到结果截图:

 

注:这些错误把参数以”?”的形式传输即可解决

1.2  跨站脚本攻击

这个

Cross-Site Scripting: External Links、Persistent、Reflected

Abstract

向一个 Web 浏览器发送未经验证的数据会导致该浏览器执行恶意代码。配置中的设置可大限度降低暴露cross-site scripting 漏洞的可能性。

Explanation

Cross-Site Scripting (XSS) 漏洞在以下情况下发生:

1. 数据通过一个不可信赖的资源进入 Web 应用程序,通常是一个网页请求或者数据库。

2. 未检验包含在动态内容中的数据,便将其传送给了 Web 用户。传送到 Web 浏览器的恶意内容通常采用 J*aScript 代码片段的形式,但也可能会包含一些 HTML、Flash 或者他任意一种可以被浏览器执行的代码。基于 XSS 的攻击手段花样百出,几乎是无穷无尽的,但通常它们都会包含传输给攻击者的私人数据(如 Cookie 或者其他会话信息)。在攻击者的控制下,指引受害者进入恶意的网络内容;或者利用易受攻击的站点,对用户的机器进行其他恶意操作。由于针对 XSS 漏洞进行的攻击通常涉及到与受攻击者控制的恶意站点进行通信或需要重新定向到该站点,因此注入对其他域内容引用的能力在诸多攻击中必不可少。可对 AntiSamy 进行配置,使其阻止指向外部域的链接,进而降低攻击者可通过 XSS 攻击造成的*。然而,这种保护只能解决部分问题,并不能解决由XSS 漏洞带来的整体威胁。

例 1:以下 AntiSamy 配置条目允许链接至在应用程序所运行的域之外的 URL。

 

 

<attribute name=href onInvalid=filterTag">

    <regexp-list>

        <regexp name="*iteURI"/>

        <regexp name=offsiteURI"/>

    </regexp-list>

</attribute>

 

Recommendation

无论什么时候,应尽可能阻止引用了外部域的链接。

例 2:以下 AntiSamy 配置条目禁止链接至在应用程序所运行的域之外的 URL。

 

 

<attribute name=href onInvalid="filterTag">

    <regexp-list>

        <regexp name="*iteURL"/>

    </regexp-list>

</attribute>

 

例 3:以下 JSP 代码片段可在数据库中查询具有给定 ID 的雇员,并输出相应雇员姓名。

 

 

<%...

Statement stmt = conn.createStatement();

ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);

if (rs != null) {

rs.next();

String name = rs.getString("name");

}

%>

Employee Name: <%= name %>

 

如果对 name 的值处理得当,该代码就能正常地执行各种功能;如若处理不当,就会对代码的*行为无能为力。这段代码暴露出的危险较小,因为 name 的值是从数据库中读取的,而且显然这些内容是由应用程序管理的。然而,如果 name 的值是由用户提供的数据产生,数据库就会成为恶意内容沟通的通道。如果不对数据库中存储的所有数据进行恰当的输入验证,那么攻击者就可以在用户的 Web 浏览器中执行恶意命令。这种类型的 Persistent XSS(也称为 Stored XSS)*其阴险狡猾,因为数据存储导致的间接性使得辨别威胁的难度*,而且还了一个攻击影响多个用户的可能性。XSS *会从访问提供留言簿 (guestbook)的网站开始。攻击者会在这些留言簿的条目中嵌入 J*aScript,接下来所有访问该留言簿的用户都会执行这些恶意代码。

针对 XSS 的解决方法是,确保在适当位置进行验证,并检验其属性是否正确。

由于 XSS 漏洞出现在应用程序的输出中包含恶意数据时,因此,合乎逻辑的做法是在数据流出应用程序的*刻对其进行验证。然而,由于 Web 应用程序常常会包含复杂而难以理解的代码,用以生成动态内容,因此,这一方法容易产生遗漏错误(遗漏验证)。降低这一风险的有效途径是对 XSS 也执行输入验证。

由于 Web 应用程序必须验证输入信息以避免其他漏洞(如 SQL Injection),因此,一种相对简单的解决方法是,加强一个应用程序现有的入验证机制,将 XSS 检测包括其中。尽管有一定的价值,但 XSS 输入验证并不能取代严格的输出验证。应用程序可能通过共享的数据存储或其他可信赖的数据源接受输入,而该数据存储所接受的输入源可能并未执行适当的输入验证。因此,应用程序不能间接地依赖于该数据或其他任意数据的安全性。这就意味着,避免 XSS 漏洞的佳方法是验证所有进入应用程序以及由应用程序传送至用户端的数据。

针对 XSS 漏洞进行验证安全的方式是,创建一份安全字符白名单,允许其中的字符出现在 HTTP 内容中,并且只接受完全由这些经认可的字符组成的输入。例如,有效的用户名可能仅包含字母数字字符,电话号码可能仅包含 0-9 的数字。然而,这种解决方法在 Web 应用程序中通常是行不通的,因为许多字符对浏览器来说都具有特殊的含义,在写入时,这些字符仍应被视为合法的输入,比如一个 Web 设计版就必须接受带有 HTML 代码片段的输入。

更灵活的解决方法称为黑名单方法,但其安全性较差,这种方法在进行输入之前就有选择地拒绝或避免了潜在的危险字符。为了创建这样一个列表,需要了解对于 Web 浏览器具有特殊含义的字符集。虽然HTML 标准定义了哪些字符具有特殊含义,但是许多 Web 浏览器会设法更正 HTML 中的常见错误,并可能在特定的上下文中认为其他字符具有特殊含义,这就是我们不鼓励使用黑名单作为阻止 XSS 的方法的原因。卡耐基梅隆大学 (Carnegie Mellon University) 软件工程学院 (Software Engineering Institute) 下属的CERT(R) (CERT(R) Coordination Center) 合作中心提供了有关各种上下文中认定的特殊字符的具体信息 [1]

在有关块级别元素的内容中(位于一段文本的中间):

“<” 是一个特殊字符,因为它可以引入一个标签。

“&” 是一个特殊字符,因为它可以引入一个字符实体。

“>” 是一个特殊字符,之所以某些浏览器将其认定为特殊字符,是基于一种假设,即该页的作者本想在前面添加一个 ”<”,却错误地将其遗漏了。

下面的这些原则适用于属性值:

对于外加双引号的属性值,双引号是特殊字符,因为它们标记了该属性值的结束。

对于外加单引号的属性值,单引号是特殊字符,因为它们标记了该属性值的结束。

对于不带任何引号的属性值,空格字符(如空格符和制表符)是特殊字符。

“&” 与某些特定变量一起使用时是特殊字符,因为它引入了一个字符实体。

例如,在 URL 中,搜索引擎可能会在结果页面内提供一个链接,用户可以点击该链接来重新运行搜索。可以将这一方法运用于编写 URL 中的搜索查询语句,这将引入更多特殊字符:

空格符、制表符和换行符是特殊字符,因为它们标记了 URL 的结束。

“&” 是特殊字符,因为它可引入一个字符实体或分隔 CGI 参数。

非 ASCII 字符(即 ISO-8859-1 编码表中所有高于 128 的字符)不允许出现在 URL 中,因此在此上下文中也被视为特殊字符。

在服务器端对在 HTTP 转义序列中编码的参数进行时,必须过滤掉输入中的 ”%” 符号。例如,当输入中出现 ”%68%65%6C%6C%6F” 时,只有从输入的内容中过滤掉 ”%”,上述字符串才能在网页上显示为”hello”。

在 的正文内:

如果可以将文本直接插入到已有的脚本标签中,应该过滤掉分号、省略号、中括号和换行符。

服务器端脚本:

如果服务器端脚本会将输入中的感叹号 (!) 转换成输出中的双引号 (“),则可能需要对此进行更多过滤。

配置文件可用来缩小攻击者可用来实施攻击的攻击面。

例 1:以下 AntiSamy 配置文件禁止在 href 中设置异地 URL。

 

 

<attribute name=href" onInvalid=filtertag">

    <regexp-list>

        < regexp name="*iteURL"/>

    </regexp-list>

</attribute>

 

扫描到结果截图:

注:这个直接加上过滤器就行了,不算太难,但是加上之后一定要跟扫描代码的人员说一下,自己代码中存在这个过滤器,反正我扫描的时候总感觉这个工具不能自动检测到过滤器给自己带来很多不是问题的问题

1.3 路径操作

1.4 代码注入

1.5 上传任意文件

1.6 未验证的重新定向和转发

1.7 拒绝服务

1.8 HTTP响应截断

二、安全特性

2.1访问控制

个人修改方法:附加限制,获取当前登录用户,对任何查询操作均校验该人员是否有权限

以下为*解释及修改方法

Access Co*ol: Database

Abstract

如果没有适当的&nb*cces*o*ol,就会执行一个包含用户控制主键的 SQL 指令,从而允许攻击者访问未经授权的记录。

Explanation

Database acces*o*ol 错误在以下情况下发生:

1. 数据从一个不可信赖的数据源进入程序。

2. 这个数据用来* SQL 查询中主键的值。

示例 1:以下代码使用可转义元字符并出现 SQL 注入漏洞的参数化语句,以构建和执行用于搜索与*标识符 [1] 相匹配的清单的 SQL 查询。您可以从与当前被授权用户有关的所有清单中选择这些标识符。

 

 

...

id = Integer.decode(request.getParameter("invoiceID"));

String query = "SELECT * FROM invoices WHERE id = ?";

PreparedStatement stmt = conn.prepareStatement(query);

stmt.setInt(1, id);

ResultSet results = stmt.execute();

...

 

问题在于*没有考虑到所有可能出现的 id 值。虽然接口生成了一个当前用户的标识符清单,但是攻击者可以绕过这个接口,从而获取所需的任何清单。因为此例中的代码没有执行检查,确保用户有权访问需要的清单,所以代码会显示所有清单,即使这些清单并不属于当前用户。有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 Database acces*o*ol 错误)是无意义的 – 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。

示例 2:以下代码对示例 1 进行调整,使其适用于 Android 平台。

 

 

...

String id = this.getIntent().getExtras().getString("invoiceID");

String query = "SELECT * FROM invoices WHERE id = ?";

SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE,

null);

Cursor c = db.rawQuery(query, new Object[]{id});

 

许多现代 Web 框架都提供对用户输入执行验证的机制。其中包括 Struts 和 Spring MVC。为了突出显示未经验证的输入源,Fortify 安全编码规则包会降低 Fortify Static Code Analyzer(Fortify 静态代码分析器)报告的问题被利用的可能性,并在使用框架验证机制时提供相应的依据,以动态重新调整问题优先级。我们将这种功能称之为上下文敏感排序。为了进一步帮助 Fortify 用户执行审计过程,Fortify 软件安全研究团队提供了数据验证项目模板,该模板会根据应用于输入源的验证机制,将问题分组到多个文件夹中。

Recommendation

与其靠表示层来限制用户输入的值,还不如在应用程序和数据库层上进行&nb*cces*o*ol。任何情况下都不允许用户在没有取得相应权限的情况下获取或修改数据库中的记录。每个涉及数据库的查询都必须遵守这个原则,这可以通过把当前被授权的用户名作为查询语句的一部分来实现。

例 3:以下代码实施了与例 1 相同的功能,但是附加了一个限制,即为当前被授权的用户*某一特定的获

取清单的方式。

 

 

...

userName = ctx.getAuthenticatedUserName();

id = Integer.decode(request.getParameter("invoiceID"));

String query =

"SELECT * FROM invoices WHERE id = ? AND user = ?";

PreparedStatement stmt = conn.prepareStatement(query);

stmt.setInt(1, id);

stmt.setString(2, userName);

ResultSet results = stmt.execute();

...

 

下面是 Android 的等同内容:

 

 

...

PasswordAuthentication pa = authenticator.getPasswordAuthentication();

String userName = pa.getUserName();

String id = this.getIntent().getExtras().getString("invoiceID");

String query = "SELECT * FROM invoices WHERE id = ? AND user = ?";

SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE,

null);

Cursor c = db.rawQuery(query, new Object[]{id, userName});

...

 

扫描到结果截图:

注:在这里面我发现只要你传输的数据中存在”id”那么恭喜你*了,工具都会默认想让你增加用户验证。

这一代码所执行的查询遵循如下方式:

SELECT * FROM items
WHERE owner = <userName>
AND itemname = <itemName>;

但是,由于这个查询是动态构造的,由一个不变的基查询字符串和一个用户输入字符串连接而成,因此只有在 itemName 不包含单引号字符时,才会正确执行这一查询。如果一个用户名为 wiley 的攻击者为itemName 输入字符串“name' OR 'a'='a”,那么构造的查询就会变成:

SELECT * FROM items
WHERE owner = 'wiley'
AND itemname = 'name' OR 'a'='a';

附加条件 OR 'a'='a' 会使 where 从句永远评估为 true,因此该查询在逻辑上将等同于一个更为简化的查询:

SELECT * FROM items;

这种查询的简化会使攻击者绕过查询只返回经过验证的用户所拥有的条目的要求;而现在的查询则会直接返回所有储存在 items 表中的条目,不论它们的所有者是谁。

 2这个例子指出了不同的恶意数值传递给在例 1 中构造和执行的查询时所带来的各种影响。如果一个用户名为 wiley 的攻击者为 itemName输入字符串“name'; DELETE FROM items; --”,那么构造成的查询语句将会变为两个:

 

SELECT * FROM items 
WHERE owner = 'wiley'
AND itemname = 'name';

DELETE FROM items;

--'

 

众多数据库服务器,其中包括 Microsoft(R) SQL Server 2000,都可以一次性执行多条用分号分隔的 SQL 指令。对于那些不允许运行用分号分隔的批量指令的数据库服务器,比如 Or*e 和其他数据库*者输入的这个字符串只会导致错误;但是在那些支持这种操作的数据库服务器上,攻击者可能会通过执行多条指令而在数据库上执行任意命令。 

注意成对的连字符 (--);这在大多数数据库服务器上都表示下面的语句将作为注释使用,而不能加以执行 [4]。在这种情况*释字符的作用就是删除修改的查询指令中遗留的后一个单引号。而在那些不允许这样加注注释的数据库中,通常攻击者可以如例 1 那样来攻击。如果攻击者输入字符串“name'); DELETE FROM items; SELECT * FROM items WHERE 'a'='a”就会创建如下三个有效指令: 

 

SELECT * FROM items 
WHERE owner = 'wiley'
AND itemname = 'name';

DELETE FROM items;

SELECT * FROM items WHERE 'a'='a';

 

有些人认为在移动世界中,典型的 Web 应用程序漏洞(如 SQL injection)是无意义的 -- 为什么用户要攻击自己?但是,谨记移动平台的本质是从各种来源并在相同设备上运行的应用程序。恶意软件在银行应用程序附近运行的可能性很高,它们会强制扩展移动应用程序的攻击面(包括跨进程通信)。

 3以下代码将例 1 改编为适用于 Android 平台。

 

...
PasswordAuthentication pa = authenticator.getPasswordAuthentication(); String userName = pa.getUserName(); String itemName = this.getIntent().getExtras().getString("itemName"); String query = "SELECT * FROM items WHERE owner = '"
+ userName + "' AND itemname = '" 
+ itemName + "'"; SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null); Cursor c = db.rawQuery(query, null);
...

 

避免 SQL injection 攻击的传统方法之一是,把它作为一个输入合法性检查的问题来处理,只接受列在白名单中的字符,或者识别并避免那些列在黑名单中的恶意数据。白名单方法是一种非常有效方法,它可以强制执行严格的输入检查规则,但是参数化的 SQL 指令所需维护更少,而且能提供更好的安全保障。而对于通常采用的列黑名单方式,由于总是存在一些小漏洞,所以并不能有效地 SQL injection 威胁。例如,攻击者可以:

— 把没有被黑名单引用的值作为目标
— 寻找方法以绕过对某一转义序列元字符的需要
—使用存储过程来隐藏注入的元字符

手动去除 SQL 查询中的元字符有一定的帮助,但是并不能完全保护您的应用程序免受 SQL injection 攻击。

防范 SQL injection 攻击的另外一种常用方式是使用存储过程。虽然存储过程可以阻止某些类型的 SQL injection 攻击,但是对于绝大多数攻击仍无能为力。存储过程于避免 SQL injection 的常用方式是限制可作为参数传入的指令类型。但是,有许多方法都可以绕过这一限制,许多危险的表达式仍可以传入存储过程。所以再次强调,存储过程在某些情况下可以避免这种攻击,但是并不能完全保护您的应用系统抵御 SQL injection 的攻击。

解决方案:造成 SQL injection 攻击的根本原因在于攻击者可以改变 SQL 查询的上下文,使程序员原本要作为数据解析的数值,被篡改为命令了。当构造一个 SQL 查询时,程序员应当清楚,哪些输入的数据将会成为命令的一部分,而哪些仅仅是作为数据。参数化 SQL 指令可以直接窜改上下文,避免几乎所有的 SQL injection 攻击。参数化 SQL 指令是用常规的 SQL 字符串构造的,但是当需要加入用户输入的数据时,它们就需要使用*参数,这些*参数是一些占位符,用来存放随后插入的数据。换言之,*参数可以使程序员清楚地分辨数据库中的数据,即其中有哪些输入可以看作命令的一部分,哪些输入可以看作数据。这样,当程序准备执行某个指令时,它可以详细地告知数据库,每一个*参数所使用的运行时的值,而不会被解析成对该命令的修改。

可以将例 1 改写成使用参数化 SQL 指令(替代用户输入连续的字符串),如下所示:

 

...
String userName = ctx.getAuthenticatedUserName();
String itemName = request.getParameter("itemName");
String query = "SELECT * FROM items WHERE itemname=? AND owner=?"; 
PreparedStatement stmt = conn.prepareStatement(query);
stmt.setString(1, itemName);
stmt.setString(2, userName);
ResultSet results = stmt.execute();
...

 

下面是 Android 的等同内容:

 

...
PasswordAuthentication pa = authenticator.getPasswordAuthentication();
String userName = pa.getUserName();
String itemName = this.getIntent().getExtras().getString("itemName");
String query = "SELECT * FROM items WHERE itemname=? AND owner=?";
SQLiteDatabase db = this.openOrCreateDatabase("DB", MODE_PRIVATE, null);
Cursor c = db.rawQuery(query, new Object[]{itemName, userName});
...

 

更加复杂的情况常常出现在报表生成代码中,因为这时需要通过用户输入来改变 SQL 指令的命令结构,比如在 WHERE 条件子句中加入动态的约束条件。不要因为这一需求,就无条件地接受连续的用户输入,从而创建查询语句字符串。当必须要根据用户输入来改变命令结构时,可以使用间接的方法来 SQL injection 攻击:创建一个合法的字符串集合,使其对应于可能要加入到 SQL 指令中的不同元素。在构造一个指令时,可使用来自用户的输入,以便从应用程序控制的值集合中进行选择。


Tips:

1. 使用参数化 SQL 指令的一个常见错误是使用由用户控制的字符串来构造 SQL 指令。这显然背离了使用参数化 SQL 指令的初衷。如果不能确定用来构造参数化指令的字符串是否由应用程序控制,请不要因为它们不会直接作为 SQL 指令执行,就假定它们是安全的。务必*地检查 SQL 指令中使用的所有由用户控制的字符串,确保它们不会修改查询的含意。

2. 许多现代 Web 框架都提供对用户输入执行验证的机制。其中包括 Struts 和 Spring MVC。为了突出显示未经验证的输入源,HPE Security Fortify 安全编码规则包会降低 HPE Security Fortify Static Code Analyzer(HPE Security Fortify 静态代码分析器)报告的问题被利用的可能性,并在使用框架验证机制时提供相应的依据,以动态重新调整问题优先级。我们将这种功能称之为上下文敏感排序。为了进一步帮助 HPE Security Fortify 用户执行审计过程,HPE Security Fortify 软件安全研究团队提供了数据验证项目模板,该模板会根据应用于输入源的验证机制,将问题分组到多个文件夹中。

3. Fortify RTA adds protection against thi*ategory.

以上内容为Fortify价格 Fortify新版购买 青穗软件,本产品由西安青穗信息技术有限责任公司直销供应。
声明:第一枪平台为第三方互联网信息服务提供者,第一枪(含网站、小程序等)所展示的产品/服务的标题、价格、详情等信息内容系由会员企业发布,其真实性、准确性和合法性均由会员企业负责,第一枪概不负责,亦不负任何法律责任。第一枪提醒您选择产品/服务前注意谨慎核实,如您对产品/服务的标题、价格、详情等任何信息有任何疑问的,请与该企业沟通确认;如您发现有任何违法/侵权信息,请立即向第一枪举报并提供有效线索。我要举报

江湖通产品

查看全部办公软件产品>>

企业信息

西安青穗信息技术有限责任公司
公司认证:
  • 公司地址:中国 陕西 西安 雁塔区  科技路10号华奥大厦C座22层
  • 注册资本:501-1000万
  • 企业类型:私营有限责任公司
  • 主营行业:安全软件、功能测试软件

联系方式

  • 联系人: 徐会立
  • 电话:029-81544056
  • 手机:15339093085
  • 邮箱:
  • 地址: 中国 陕西 西安 雁塔区  科技路10号华奥大厦C座22层
  • 邮编:

最新办公软件产品

点击查看联系方式
点击隐藏联系方式
联系人:徐会立电话:029-81544056手机:15339093085