代码质量不佳会导致不可预测的行为。对于用户来说,通常表现为可用性差。对于攻击者来说,提供了以意外方式对系统施加压力的机会。
NaN
进行对比始终是一个错误。NaN
进行比较,得出的计算结果将始终为 false
(!=
运算符是个例外,因为 NaN
未经排序,所以始终会得出 true
结果)。NaN
。
...
if (result == Double.NaN){
//something went wrong
throw new RuntimeException("Something went wrong, NaN found");
}
...
result
并非 NaN
,但是使用带有 NaN
的运算符 ==
将始终得出 false
值,所以此检查将永远不会抛出异常。this
引用,进而导致出现漏洞。
...
class User {
private String username;
private boolean valid;
public User(String username, String password){
this.username = username;
this.valid = validateUser(username, password);
}
public boolean validateUser(String username, String password){
//validate user is real and can authenticate
...
}
public final boolean isValid(){
return valid;
}
}
validateUser
和该类并非 final
,这意味着它们是可以被覆盖的,对将覆盖此该函数的子类的变量执行初始化会允许避开 validateUser
功能。例如:
...
class Attacker extends User{
public Attacker(String username, String password){
super(username, password);
}
public boolean validateUser(String username, String password){
return true;
}
}
...
class MainClass{
public static void main(String[] args){
User hacker = new Attacker("Evil", "Hacker");
if (hacker.isValid()){
System.out.println("Attack successful!");
}else{
System.out.println("Attack failed");
}
}
}
Example 1
中的代码会输出“Attack successful!”,因为 Attacker
类会覆盖从超类 User
的构造函数调用的 validateUser()
函数,并且 Java 将首先在子类中查找从该构造函数调用的函数。inputReader
对象的类名称确认是否信任该对象的输入。如果攻击者能够提供一种执行恶意命令的 inputReader
实现方式,则此代码将无法区分该对象是善意的还是恶意的。
if (inputReader.GetType().FullName == "CompanyX.Transaction.Monetary")
{
processTransaction(inputReader);
}
inputReader
对象的类名称确认是否信任该对象的输入。如果攻击者能够提供一种执行恶意命令的 inputReader
实现方式,则此代码将无法区分该对象是善意的还是恶意的。
if (inputReader.getClass().getName().equals("com.example.TrustedClass")) {
input = inputReader.getInput();
...
}
inputReader
对象的类名称确认是否信任该对象的输入。如果攻击者能够提供一种执行恶意命令的 inputReader
实现方式,则此代码将无法区分该对象是善意的还是恶意的。
if (inputReader::class.qualifiedName == "com.example.TrustedClass") {
input = inputReader.getInput()
...
}
x = NULL
和 x != NULL
将始终为 false。NULL
的值是不确定的。它不等于任何值,甚至不等于另一个 NULL
值。同样,一个 null
值永远不会等于另一个值。例 2:以下语句将始终为 false。
checkNull BOOLEAN := x = NULL;
checkNotNull BOOLEAN := x != NULL;
equals()
方法,而不是==
或 !=
方法。==
或 !=
来比较两个字符串是否相等,其实质比较的是两个对象,而不是字符串的值。因此,若采用这个方法,两个引用将永远不会相等。
if (args[0] == STRING_CONSTANT) {
logger.info("miracle");
}
==
和 !=
标记符被用来比较相同对象中包含的字符串时,它们只会按照预期的那样运行。要出现这种情况,最常用的方法就是将字符串内置,这样一来,就可以将字符串添加到一个由 String
类维护的对象池中。一旦字符串内置,在使用该字符串时,都会采用相同的对象,相等运算符也会按照预期的那样执行。所有字符串文字和带值的字符串常量都会自动内置。其他字符串可以通过调用 String.intern()
来手动内置,并会返回一个规范的当前字符串实例,必要时也会创建一个实例。