Missing Initialization of a Variable (4.19.1)

Weakness ID: 456

Vulnerability Mapping: ALLOWED This CWE ID may be used to map to real-world vulnerabilities
Abstraction: Variant Variant - a weakness that is linked to a certain type of product, typically involving a specific language or technology. More specific than a Base weakness. Variant level weaknesses typically describe issues in terms of 3 to 5 of the following dimensions: behavior, property, technology, language, and resource.

+ Description

The product does not initialize critical variables, which causes the execution environment to use unexpected values.

+ Common Consequences

Section HelpThis table specifies different individual consequences associated with the weakness. The Scope identifies the application security area that is violated, while the Impact describes the negative technical impact that arises if an adversary succeeds in exploiting this weakness. The Likelihood provides information about how likely the specific consequence is expected to be seen relative to the other consequences in the list. For example, there may be high likelihood that a weakness will be exploited to achieve a certain impact, but a low likelihood that it will be exploited to achieve a different impact.

Impact Details

Unexpected State; Quality Degradation; Varies by Context

Scope: Integrity, Other

The uninitialized data may be invalid, causing logic errors within the program. In some cases, this could result in a security problem.

+ Potential Mitigations

Phase(s) Mitigation

Implementation

Strategy: Attack Surface Reduction

Ensure that critical variables are initialized before first use [REF-1485].

Requirements

Strategy: Language Selection

Choose a language that is not susceptible to these issues.

+ Relationships

Section Help This table shows the weaknesses and high level categories that are related to this weakness. These relationships are defined as ChildOf, ParentOf, MemberOf and give insight to similar items that may exist at higher and lower levels of abstraction. In addition, relationships such as PeerOf and CanAlsoBe are defined to show similar weaknesses that the user may want to explore.

+ Relevant to the view "Research Concepts" (View-1000)

Nature Type ID Name
ChildOf Class Class - a weakness that is described in a very abstract fashion, typically independent of any specific language or technology. More specific than a Pillar Weakness, but more general than a Base Weakness. Class level weaknesses typically describe issues in terms of 1 or 2 of the following dimensions: behavior, property, and resource. 909 Missing Initialization of Resource
CanPrecede Base Base - a weakness that is still mostly independent of a resource or technology, but with sufficient details to provide specific methods for detection and prevention. Base level weaknesses typically describe issues in terms of 2 or 3 of the following dimensions: behavior, property, technology, language, and resource. 89 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
CanPrecede Variant Variant - a weakness that is linked to a certain type of product, typically involving a specific language or technology. More specific than a Base weakness. Variant level weaknesses typically describe issues in terms of 3 to 5 of the following dimensions: behavior, property, technology, language, and resource. 98 Improper Control of Filename for Include/Require Statement in PHP Program ('PHP Remote File Inclusion')
CanPrecede Base Base - a weakness that is still mostly independent of a resource or technology, but with sufficient details to provide specific methods for detection and prevention. Base level weaknesses typically describe issues in terms of 2 or 3 of the following dimensions: behavior, property, technology, language, and resource. 120 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')
CanPrecede Variant Variant - a weakness that is linked to a certain type of product, typically involving a specific language or technology. More specific than a Base weakness. Variant level weaknesses typically describe issues in terms of 3 to 5 of the following dimensions: behavior, property, technology, language, and resource. 457 Use of Uninitialized Variable

+ Relevant to the view "CISQ Quality Measures (2020)" (View-1305)

Nature Type ID Name
ChildOf Class Class - a weakness that is described in a very abstract fashion, typically independent of any specific language or technology. More specific than a Pillar Weakness, but more general than a Base Weakness. Class level weaknesses typically describe issues in terms of 1 or 2 of the following dimensions: behavior, property, and resource. 665 Improper Initialization

+ Relevant to the view "CISQ Data Protection Measures" (View-1340)

Nature Type ID Name
ChildOf Class Class - a weakness that is described in a very abstract fashion, typically independent of any specific language or technology. More specific than a Pillar Weakness, but more general than a Base Weakness. Class level weaknesses typically describe issues in terms of 1 or 2 of the following dimensions: behavior, property, and resource. 665 Improper Initialization

+ Modes Of Introduction

Section HelpThe different Modes of Introduction provide information about how and when this weakness may be introduced. The Phase identifies a point in the life cycle at which introduction may occur, while the Note provides a typical scenario related to introduction during the given phase.

Phase Note
Implementation

+ Applicable Platforms

Section HelpThis listing shows possible areas for which the given weakness could appear. These may be for specific named Languages, Operating Systems, Architectures, Paradigms, Technologies, or a class of such platforms. The platform is listed along with how frequently the given weakness appears for that instance.

Languages

Class: Not Language-Specific (Undetermined Prevalence)

+ Demonstrative Examples

Example 1

This function attempts to extract a pair of numbers from a user-supplied string.

(bad code)

Example Language:

void parse_data(char *untrusted_input){

int m, n, error;
error = sscanf(untrusted_input, "%d:%d", &m, &n);
if ( EOF == error ){

die("Did not specify integer value. Die evil hacker!\n");

}
/* proceed assuming n and m are initialized correctly */

}

This code attempts to extract two integer values out of a formatted, user-supplied input. However, if an attacker were to provide an input of the form:

then only the m variable will be initialized. Subsequent use of n may result in the use of an uninitialized variable (CWE-457).


Example 2

Here, an uninitialized field in a Java class is used in a seldom-called method, which would cause a NullPointerException to be thrown.

(bad code)

Example Language: Java 

private User user;
public void someMethod() {

// Do something interesting.
...

// Throws NPE if user hasn't been properly initialized.
String username = user.getName();

}


Example 3

This code first authenticates a user, then allows a delete command if the user is an administrator.

(bad code)

Example Language: PHP 

if (authenticate($username,$password) && setAdmin($username)){

$isAdmin = true;

}
/.../

if ($isAdmin){

deleteUser($userToDelete);

}

The $isAdmin variable is set to true if the user is an admin, but is uninitialized otherwise. If PHP's register_globals feature is enabled, an attacker can set uninitialized variables like $isAdmin to arbitrary values, in this case gaining administrator privileges by setting $isAdmin to true.


Example 4

In the following Java code the BankManager class uses the user variable of the class User to allow authorized users to perform bank manager tasks. The user variable is initialized within the method setUser that retrieves the User from the User database. The user is then authenticated as unauthorized user through the method authenticateUser.

(bad code)

Example Language: Java 

public class BankManager {

// user allowed to perform bank manager tasks
private User user = null;
private boolean isUserAuthentic = false;

// constructor for BankManager class
public BankManager() {

...

}

// retrieve user from database of users
public User getUserFromUserDatabase(String username){

...

}

// set user variable using username
public void setUser(String username) {

this.user = getUserFromUserDatabase(username);

}

// authenticate user
public boolean authenticateUser(String username, String password) {

if (username.equals(user.getUsername()) && password.equals(user.getPassword())) {

isUserAuthentic = true;

}
return isUserAuthentic;

}

// methods for performing bank manager tasks
...

}

However, if the method setUser is not called before authenticateUser then the user variable will not have been initialized and will result in a NullPointerException. The code should verify that the user variable has been initialized before it is used, as in the following code.

(good code)

Example Language: Java 

public class BankManager {

// user allowed to perform bank manager tasks
private User user = null;
private boolean isUserAuthentic = false;

// constructor for BankManager class
public BankManager(String username) {

user = getUserFromUserDatabase(username);

}

// retrieve user from database of users
public User getUserFromUserDatabase(String username) {...}

// authenticate user
public boolean authenticateUser(String username, String password) {

if (user == null) {

System.out.println("Cannot find user " + username);

}
else {

if (password.equals(user.getPassword())) {

isUserAuthentic = true;

}

}
return isUserAuthentic;

}

// methods for performing bank manager tasks
...


}


Example 5

This example will leave test_string in an unknown condition when i is the same value as err_val, because test_string is not initialized (CWE-456). Depending on where this code segment appears (e.g. within a function body), test_string might be random if it is stored on the heap or stack. If the variable is declared in static memory, it might be zero or NULL. Compiler optimization might contribute to the unpredictability of this address.

(bad code)

Example Language:

char *test_string;
if (i != err_val)
{

test_string = "Hello World!";

}
printf("%s", test_string);

When the printf() is reached, test_string might be an unexpected address, so the printf might print junk strings (CWE-457).

To fix this code, there are a couple approaches to making sure that test_string has been properly set once it reaches the printf().

One solution would be to set test_string to an acceptable default before the conditional:

(good code)

Example Language:

char *test_string = "Done at the beginning";
if (i != err_val)
{

test_string = "Hello World!";

}
printf("%s", test_string);

Another solution is to ensure that each branch of the conditional - including the default/else branch - could ensure that test_string is set:

(good code)

Example Language:

char *test_string;
if (i != err_val)
{

test_string = "Hello World!";

}
else {

test_string = "Done on the other side!";

}
printf("%s", test_string);


Example 6

Consider the following merchant server application as implemented in [REF-1475]. It receives card payment information (orderPgData instance in OrderPgData.java) from the payment gateway (such as PayPal). The next step is to complete the payment (finalizeOrder() in Main.java). The merchant server validates the amount (validateAmount() in OrderPgData.java), and if the validation is successful, then the payment is completed.

(bad code)

Example Language: Java 

File: OrderPgData.java

public class OrderPgData {

String PgType;
int productPrice;
int paymentAmount;
private boolean isPaymentAmountTampered;

public boolean getIsPaymentAmountTampered() {

return this.isPaymentAmountTampered;

}

...

public void validateAmount() {

... [sets this.setIsPaymentAmountTampered to true or false depending on whether the product price matches the payment amount]

}

(bad code)

Example Language: Java 

File: PgServiceResolver.java

public class PgServiceResolver {

public OrderPgData getOrderPgDataByPgType(String pgType, int productPrice, int paymentAmount) {

...
switch(pgType) {

case "card":

System.out.println("In "+pgType+" payment logic, orderPgData does not verify whether the product amount and payment amount have been tampered with.");
break;

case "paypal":

System.out.println("In "+pgType+" payment logic, orderPgData verifies whether the product amount and payment amount have been tampered with.");
orderPgData.validateAmount();
break;

}
...

(bad code)

Example Language: Java 

File: Main.java

public class Main {

public static void main(String[] args) {

String pgType = "card"; // or paypal
int productPrice = 100;
int paymentAmount = 10;
PgServiceResolver pgServiceResolver = new PgServiceResolver();
OrderPgData orderPgData = pgServiceResolver.getOrderPgDataByPgType(pgType, productPrice, paymentAmount);
finalizeOrder(orderPgData);

}
private static void finalizeOrder(OrderPgData orderPgData) {

if (orderPgData.getIsPaymentAmountTampered()) {

System.out.println("The attacker tampered with the payment amount, but product payment is canceled.");

} else {

... /* the product payment is completed */

}

}

}

In PgServiceResolver.java, when pgType is "card" indicating a card payment, orderPgData.validateAmount() is not called - that is, the amount is not validated to be the same as the expected price.

Since isPaymentAmountTampered is declared as a private boolean, but it is not initialized, it is forcibly initialized to false by the Java compiler [REF-1476].

If the adversary modifies the price, e.g., changing paymentAmount from 100 to 10, then no validation is performed. Since isPaymentAmountTampered is "false" because of the default initialization, the code finishes processing the payment because it does not believe that the amount has been changed.

This weakness could be addressed by setting the value of isPaymentAmountTampered to true. This is a "secure-by-default" value that reflects a "default deny" policy - i.e., it's assumed that the payment amount is tampered, and only a special validation step can change this assumption.

(good code)

Example Language: Java 

File: OrderPgData.java
...

private boolean isPaymentAmountTampered = true;



+ Selected Observed Examples

Note: this is a curated list of examples for users to understand the variety of ways in which this weakness can be introduced. It is not a complete list of all CVEs that are related to this CWE entry.

Reference Description

Chain: The return value of a function returning a pointer is not checked for success (CWE-252) resulting in the later use of an uninitialized variable (CWE-456) and a null pointer dereference (CWE-476)

Chain: secure communications library does not initialize a local variable for a data structure (CWE-456), leading to access of an uninitialized pointer (CWE-824).

Chain: C union member is not initialized (CWE-456), leading to access of invalid pointer (CWE-824)

Chain: Use of an unimplemented network socket operation pointing to an uninitialized handler function (CWE-456) causes a crash because of a null pointer dereference (CWE-476)

A variable that has its value set in a conditional statement is sometimes used when the conditional fails, sometimes causing data leakage

Product uses uninitialized variables for size and index, leading to resultant buffer overflow.

Internal variable in PHP application is not initialized, allowing external modification.

Array variable not initialized in PHP application, leading to resultant SQL injection.

+ Weakness Ordinalities

Ordinality Description

Primary

(where the weakness exists independent of other weaknesses)

Indirect

(where the weakness is a quality issue that might indirectly make it easier to introduce security-relevant weaknesses or make them more difficult to detect)