Skip navigation.

exploreopera

| Help

Sign up | Help

taviso

linux, programming and security

Posts tagged with "auditing"

Auditing puzzle

, ,

Here is an interesting auditing question, try to make the following short C program crash.

#include <string.h>
#include <stdio.h>
#include <locale.h>
#include <ctype.h>

int main(int argc, char **argv)
{
    char buf[128];
    int len;

    /* initialise the buffer */
    memset(buf, '\0', sizeof(buf));

    /* setup locale for toupper() */
    setlocale(LC_ALL, "");

    /* check an argument was specified */
    if (argc >= 2) {
        /* get the first 10 characters */
        len = snprintf(buf, sizeof(buf), "you entered: %.10s", argv[1]);

        /* check for non-printing characters */
        while (len--)
            buf[len] = isprint(buf[len]) ? toupper(buf[len]) : '?';

        /* output string */
        fprintf(stdout, "%s\n", buf);
    }

    return 0;
}

Scroll down for discussion. .
.
.
.
.
.
.
.
.
.
.
.
.
.
.

snprintf() wont overrun the `buf` buffer, so specifying too much data wont cause a crash

$ ./a.out `perl -e 'print "A"x"1024"'`; echo $?
YOU ENTERED: AAAAAAAAAA
0

However, the return code from snprintf() isnt checked, and it can return -1 for a number of reasons, including malloc() failing, or invalid multibyte characters in the string. If any of the users of this application are using a utf8 locale, they could be vulnerable to a security issue.

$ LC_ALL=en_GB.utf8 ./a.out `printf "\x80foobar"`; echo $?
Segmentation fault
139

Its worth remembering that a number of common libraries will call setlocale() for you in their constructors, so even if you didnt intend to, it could be called for you. Using the return code from snprintf() or sprintf() without testing for failure could result in multiple security vulnerabilities, so its always worth checking even if you dont modify the locale.

Quick Security Auditing Puzzle

, , ,

Here's an interesting problem, how can I make this simple program crash? (assume IA32)

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    int a, b;

    if (argc != 3)
        return 1;

    a = atoi(argv[1]);
    b = atoi(argv[2]);

    return b ? a / b : 0;
}


scroll down for the solution.

.
.
.
.
.
.
.
.
.
.
.
.
.
.
.


The code correctly checks for divide by zero, so attempting this wont work:

$ ./a.out 42 0; echo $?
0
$


But not every invalid operation has been checked, while every programmer knows to avoid dividing by zero, very few are aware that it's also illegal to divide INT_MIN by -1. The reason is obvious, on a twos complement system |INT_MIN| is one greater than INT_MAX, so the result of the operation simply cannot fit in an integer.

This little known fact is almost guaranteed to crash any system that uses integer division on user controlled values as so few developers check for this unusual case.

$ ./a.out -2147483648 -1; echo $?
Floating point exception (core dumped)
136