Use of Unvalidated Integers in Binary Operations via function calls

Whenever input data is accepted from the user or the outside environment, it should be validated for type, length, format, and range before it is used. Until this data is properly validated, it is said to be tainted. The SV.TAINTED family of checkers looks for the use of tainted data in code.

The SV.TAINTED.BINOP checker flags code that uses tainted data, via a function call, in arithmetic binary operations, such as addition, subtraction, or multiplication.

Vulnerability and risk

When integer data input to the code is not validated properly and is used as an operand to a binary operation, the result can be an integer overflow or wraparound. This potential situation could allow an attacker to alter the normal control flow, causing an unexpected program behavior. In the worst-case scenarios, an attacker could:
  • Provide unexpected values and cause a program crash
  • Cause excessive resource consumption
  • Read confidential data
  • Use malicious input to modify data or alter control flow
  • Execute arbitrary commands

Mitigation and prevention

To avoid tainted input errors:
  • understand all the potential areas in which untrusted inputs could enter your software: parameters or arguments, cookies, input read from the network, environment variables, reverse DNS lookups, query results, filenames, databases, and any external systems;
  • use a whitelist or 'known good' policy for inputs, rather than relying only on a blacklist or 'known bad' strategy;
  • make sure all relevant properties of the input are validated, including length, type of input, ranges, missing or extra inputs, syntax, and consistency;
  • if there are security checks on the client side of an applications, make sure they are duplicated on the server side;
  • if the application combines inputs from multiple sources, perform the validation after the sources have been combined.

Vulnerable code example

1 int get_altitude();
2 void set_altitude(int);
4 int get_untrusted() {
5     int i;
6     scanf("%d", &i);
7     return i;
8 }
10 extern const int max_altitude;
12 int get_new_altitude(int shift) {
13     int current_altitude = get_altitude();
14     return current_altitude + shift;
15 }
17 void increase_altitude() {
18    int shift = get_untrusted();
19     if (shift > 0) {
20         int new_altitude = get_new_altitude(shift);
21         if (new_altitude < max_altitude) {
22             set_altitude(new_altitude);
23         }
24     }
25 }

In the above example, an attacker can provide an arbitrarily large value for variable 'new_altitude'. If the binary operation at line 14 overflows, this can result in a negative value of variable 'new_altitude' at line 20, and cause unexpected program behavior.

Klocwork reports an SV.TAINTED.BINOP defect at line 20, indicating: "Unvalidated integer value 'shift' that is received from 'get_untrusted' at line 18 is used as an operand to a binary operator via a call to 'get_new_altitude' at line 20".

Fixed code example

1 int get_altitude();
2 void set_altitude(int);
4 int get_untrusted() {
5     int i;
6     scanf("%d", &i);
7     return i;
8 }
10 extern const int max_altitude;
11 extern const int max_trusted_shift;
13 int get_new_altitude(int shift) {
14     int current_altitude = get_altitude();
15 	return current_altitude + shift;
16 }
18 void increase_altitude() {
19     int shift = get_untrusted();
20     if (shift > 0 && shift < max_trusted_shift) {
21         int new_altitude = get_new_altitude(shift);
22 		if (new_altitude < max_altitude) {
23 			set_altitude(new_altitude);
24 		}
25     }
26 }

The Klocwork checker no longer produces the defect report here, since the integer value 'shift' is validated at line 20 before being used in the binary operation.

Security training

Application security training materials provided by Secure Code Warrior.