Poor code quality leads to unpredictable behavior. From a user's perspective that often manifests itself as poor usability. For an attacker it provides an opportunity to stress the system in unexpected ways.
NaN
is always an error.NaN
it is always evaluated as false
, except for the !=
operator, which always evaluates to true
since NaN
is unordered.NaN
.
...
if (result == Double.NaN){
//something went wrong
throw new RuntimeException("Something went wrong, NaN found");
}
...
result
is not NaN
, however using the operator ==
with NaN
always results in a value of false
, so this check will never throw the exception.this
reference prior to the object being fully initialized, which can in turn lead to a vulnerability.
...
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
and the class are not final
, it means that they can be overridden, and then initializing a variable to the subclass that overrides this function would allow bypassing of the validateUser
functionality. For example:
...
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
prints "Attack successful!", since the Attacker
class overrides the validateUser()
function that is called from the constructor of the superclass User
, and Java will first look in the subclass for functions called from the constructor.inputReader
object based on its class name. If an attacker can supply an implementation of inputReader
that executes malicious commands, this code cannot differentiate the benign and malicious versions of the object.
if (inputReader.GetType().FullName == "CompanyX.Transaction.Monetary")
{
processTransaction(inputReader);
}
inputReader
object based on its class name. If an attacker can supply an implementation of inputReader
that executes malicious commands, this code cannot differentiate the benign and malicious versions of the object.
if (inputReader.getClass().getName().equals("com.example.TrustedClass")) {
input = inputReader.getInput();
...
}
inputReader
object based on its class name. If an attacker can supply an implementation of inputReader
that executes malicious commands, this code cannot differentiate the benign and malicious versions of the object.
if (inputReader::class.qualifiedName == "com.example.TrustedClass") {
input = inputReader.getInput()
...
}
x = NULL
and x != NULL
will always be false.NULL
is indeterminate. It is not equal to anything, not even another NULL
value. Also, a null
value is never not equal to another value.Example 2: The following statement will always be false.
checkNull BOOLEAN := x = NULL;
checkNotNull BOOLEAN := x != NULL;
equals()
method, not ==
or !=
.==
or !=
to compare two strings for equality, which compares two objects for equality, not their values. Chances are good that the two references will never be equal.
if (args[0] == STRING_CONSTANT) {
logger.info("miracle");
}
==
and !=
operators will only behave as expected when they are used to compare strings contained in objects that are equal. The most common way for this to occur is for the strings to be interned, whereby the strings are added to a pool of objects maintained by the String
class. Once a string is interned, all uses of that string will use the same object and equality operators will behave as expected. All string literals and string-valued constants are interned automatically. Other strings can be interned manually be calling String.intern()
, which will return a canonical instance of the current string, creating one if necessary.