Insufficient Numeric Precision
NVD Categorization
CWE-1339: Insufficient Precision or Accuracy of a Real Number: The product processes a real number with an implementation in which the number’s representation does not preserve required accuracy and precision in its fractional part, causing an incorrect result.
Description
The use of real numbers with insufficient precision, such as double or float in most languages, can lead to unpredictable results and introduce bugs that attackers can exploit.
Examples
Example 1.0
In this scenario, a vulnerable bank uses the insufficient precision number data type, double:
public class VulnBank {
private double balance = 0.0;
public void deposit(double amount) {
balance += amount;
}
public void showBalance() {
System.out.println("Balance: " + balance);
}
...
}
An Attacker could deposit 0.1 dollar multiple times like so:
VulnBank attackerAcc = new VulnBank();
attackerAcc.deposit(0.1);
attackerAcc.deposit(0.1);
attackerAcc.deposit(0.1);
attackerAcc.showBalance();
One might believe the output would be Balance: 0.3, as it should. However, it outputs: Balance: 0.30000000000000004
At first glance, this is a negligible amount, but an attacker could do it multiple times, gaining significant profits.
Solution
In many programming languages, they have a reliable decimal data type, for example, BigDecimal in Java, decimal.Decimal in Python, etc.
For example, the fixed code in Example 1.0 would be
import java.math.BigDecimal;
public class FixedVulnBank {
BigDecimal balance = BigDecimal.ZERO;
public void deposit(BigDecimal amount) {
balance = balance.add(amount);
}
public void showBalance() {
System.out.println("Balance: " + balance);
}
...
}
And the program would look like
FixedVulnBank acc = new FixedVulnBank();
acc.deposit(new BigDecimal("0.1"));
acc.deposit(new BigDecimal("0.1"));
acc.deposit(new BigDecimal("0.1"));
acc.showBalance(); // output: Balance: 0.3