Examples of bad input validation code

Because poor input validation is the largest single class of vulnerability, there are many, many examples. This section has only a few. With very little work, you should be able to find plenty more on the web. These examples are in Java and C/C++. However, the problems occur across all languages, and the concepts are the same in all of them.

Java

This example is from CVE-20: Improper Input Validation. Here is some Java code with a serious bug:

// BAD CODE
public static final double price = 20.00;
int quantity = currentUser.getAttribute("quantity");
double total = price * quantity;
chargeUser(total);

Before reading on, answer: How can an attacker exploit this?

The attacker can provide a negative quantity and end up with a credit. Unfortunately, many programmers forget that integers (other than unsigned) can be negative, even if such a value makes no sense. Boundary-value testing (Section 3.3.3) would have caught this type of bug. Careful thought about business rules would also have provided the necessary guidance.

Java

This example is also from CVE-20: Improper Input Validation. Here is some more Java code with a serious bug:

// BAD CODE
private void buildList ( int untrustedListSize ){
    if ( 0 > untrustedListSize ){
        die("Negative value supplied for list size");
    }
    Widget[] list = new Widget [ untrustedListSize ];
    list[0] = new Widget();
}

Before reading on, answer: How can an attacker exploit this?

If the attacker provides a 0, an exception will be thrown when the first element is inserted. Again, this is a boundary condition (Section 3.3.3) that is not properly handled.

C/C++

Here is some real-life code that has a vulnerability:

// BAD CODE
main(argc, argv)
char *argv[ ];
{
    register char *sp;
    char line[512];
    struct sockaddr in sin;
    int i, p[2], pid, status;
    FILE *fp; char *av[4];

    i = sizeof (sin);
    if (getpeername(0, &sin, &i) < 0)
        fatal(argv[0], "getpeername");
    line[0] = ’\0’;
    gets(line); /* receive user name */
    sp = line;
    /* . . . */

Before reading on, answer: How can an attacker exploit this?

What user would have a user name 512 bytes long when the system maximum at the time was 8? This code did no length checking and the result was a buffer overflow allowing the attacker to execute arbitrary code. This code is from fingerd, and is one of the vulnerabilities that the Morris worm attacked.

C/C++

This example is also from CVE-20: Improper Input Validation. Here is some bad CC/C++ code:

// BAD CODE
#define MAX_DIM 100
int m,n, error; /* board dimensions */
board_square_t *board;

printf("Please specify the board height: \n");
error = scanf("%d", &m);
if ( EOF == error )
    die("No integer passed: Die evil hacker!\n");

printf("Please specify the board width: \n");
error = scanf("%d", &n);
if ( EOF == error )
    die("No integer passed: Die evil hacker!\n");
if ( m > MAX_DIM || n > MAX_DIM )
    die("Value too large: Die evil hacker!\n");
board = (board_square_t*) 
    malloc( m * n * sizeof(board_square_t));

Before reading on, answer: How can an attacker exploit this?

The attacker can provide negative values that will be converted to unsigned and represent large values. The attacker could also do an overflow attack with large negative values. The failure is again a boundary value one.