界: API Abuse

API 是调用方和被调用方之间的约定。最常见的 API 滥用是由于调用方未能遵守此约定的终止导致的。例如,如果某个程序在调用 chroot() 后未能调用 chdir(),则违反了用于指定如何安全地更改活动根目录的约定。库滥用的另一个典型示例是期望被调用方向调用方返回可信的 DNS 信息。在这种情况下,调用方通过对被调用方行为做出某种假设(返回值可用于身份验证目的)滥用其 API。另一方也可能违反调用方-被调用方约定。例如,如果编码器子类化 SecureRandom 并返回一个非随机值,则将违反此约定。

Missing Check against Null

Abstract
程序可能会间接引用一个 null 指针,因为它不会检查函数的返回值,而该值可能为 null
Explanation
几乎每一个对软件系统的严重攻击都是从违反程序员的假设开始的。攻击后,程序员的假设看起来既脆弱又拙劣,但攻击前,许多程序员会在午休时间为自己的种种假设做很好的辩护。

在代码中很容易发现的两个可疑的假设是:一是这个函数调用不可能出错;二是即使出错了,也不会对系统造成什么重要影响。当程序员忽略函数返回值时,就暗示着自己是基于上述任一假设来执行操作。
示例 1: 以下代码不会在调用成员函数 Equals() 之前检查 Item 属性返回的字符串是否为 null,从而可能会导致 null dereference。


string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...


对于这种编码错误的一贯辩解是:

“我知道请求的值肯定会存在,因为....如果不存在,程序就无法执行所需的行为,因此是处理该错误还是允许程序自行崩溃而间接引用 null 也就无关紧要了。”

但是,攻击者对于发现程序中的意外情况十分在行,特别是发生异常时。
desc.controlflow.dotnet.missing_check_against_null
Abstract
程序会间接引用 null 指针,因为它不会对函数的返回值进行检查,而该函数有可能返回 null
Explanation
几乎每一个对软件系统的严重攻击都是从违反程序员的假设开始的。攻击后,程序员的假设看起来既脆弱又拙劣,但攻击前,许多程序员会在午休时间为自己的种种假设做很好的辩护。

在代码中很容易发现的两个可疑的假设是:一是这个函数调用不可能出错;二是即使出错了,也不会对系统造成什么重要影响。当程序员忽略函数返回值时,就暗示着自己是基于上述任一假设来执行操作。
例 1:以下代码在使用由 malloc() 返回的指针之前,并没有检查内存是否分配成功。


buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);


对于这种编码错误的一贯辩解是:

“如果我的程序耗尽了所有内存,则会失败。无论是在程序尝试间接引用 null 指针时处理相关错误,还是允许程序自行崩溃并出现分段故障,都无关紧要。”

但是这个解释忽略了以下三个重要的因素:

— 根据应用程序的类型和大小,可能会释放由其他程序使用的内存,从而使程序继续运行。

- 程序不可能执行正常退出(如果需要)。如果程序执行原子操作,则会使系统处于不一致的状态。

— 程序员失去了记下诊断信息的机会。对 malloc() 的调用失败是不是因为 req_size 太大,还是因为在同一时刻处理的请求太多。或者是由于已累计超时的 memory leak 引起的。如果不对错误进行处理,就不会知道是什么原因。
References
[1] J. Viega, G. McGraw Building Secure Software Addison-Wesley
desc.controlflow.cpp.missing_check_against_null
Abstract
程序会间接引用 null 指针,因为它不会对函数的返回值进行检查,而该函数有可能返回 null
Explanation
几乎每一个对软件系统的严重攻击都是从违反程序员的假设开始的。攻击后,程序员的假设看起来既脆弱又拙劣,但攻击前,许多程序员会在午休时间为自己的种种假设做很好的辩护。

在代码中很容易发现的两个可疑的假设是:一是这个函数调用不可能出错;二是即使出错了,也不会对系统造成什么重要影响。当程序员忽略函数返回值时,就暗示着自己是基于上述任一假设来执行操作。

示例 1: 以下代码在调用成员函数 compareTo() 之前,不会检查 getParameter() 返回的字符串是否为 null,从而可能会造成 null dereference。


String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
例 2:。以下代码显示了这样一个例子,一个系统属性被设置为了 null,随后间接引用它的程序员错误地认为该属性值是已定义的。


System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");


对于这种编码错误的一贯辩解是:

“我知道请求的值肯定会存在,因为....如果不存在,程序就无法执行所需的行为,因此是处理该错误还是允许程序自行崩溃而间接引用 null 也就无关紧要了。”

但是,攻击者对于发现程序中的意外情况十分在行,特别是发生异常时。
desc.controlflow.java.missing_check_against_null