我想简单快速地演示一下SQL注入的工作原理。我已经解决了一些问题。我有一个包含随机用户名,密码和电子邮件的表,并且能够“注入” SQL代码以查看与此注入相关的所有用户:
' OR '1'='1
这是我的PHP代码寻找“成员”的样子:
if (isset($_POST['search'])) {
$searchterm = $_POST['searchterm'];
echo $searchterm . '<br>';
/*sql query for searching in database*/
$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
/* execute statement */
$stmt->execute();
/* bind result variables */
$stmt->bind_result($name, $email);
/* fetch values */
while ($stmt->fetch()) {
echo "Username: " . $name . " E-mail: " . $email . "<br>";
}
} else {
die($conn->error);
}
}
现在,我想演示一些更致命的问题,例如有人将您的整个桌子截断。因此,我在搜索栏中尝试了以下代码:
'; TRUNCATE TABLE Members; --
但是我收到此错误消息:
You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'TRUNCATE TABLE Members; -- '' at line 1
似乎我得到了一个额外的',但是我不知道如何摆脱它,以为-会把它注释掉。首先,我认为问题在于我在-后面没有空格,但是添加空格没有任何作用。
我曾尝试切换到PDO,因为我认为mysqli无法接受多个查询存在问题,但是后来我在某处读到PDO也不支持,但我也不知道。
有什么办法可以使它工作?
编辑:我知道默认情况下PDO支持多重查询,但是当我尝试它不起作用时,也许我绑定了错误的参数。但是我什至无法进行简单的选择查询。
答案 0 :(得分:1)
mysqli_query()默认情况下不支持多查询。为此,它具有单独的功能:mysqli_multi_query()。
SQL注入不仅与运行多个语句有关,尽管著名的XKCD cartoon也是如此。
您的代码有一个严重的SQL注入漏洞。即使您将$ _POST请求数据中的内容直接插值到SQL字符串中,您是否认为使用prepare()
可以使查询安全?
您的代码是这样的:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = '$searchterm'";
if ($stmt = $conn->prepare($sql)) {
/* execute statement */
$stmt->execute();
...
不安全的输入很容易以这种方式使SQL注入恶作剧。它甚至可能是无辜的,但仍然会导致问题。例如,假设搜索为:O'Reilly
。直接将该值复制到您的SQL中将导致如下查询:
SELECT username, email FROM Members where username = 'O'Reilly'
看到不匹配的'
引用吗?这不会带来任何恶意,但只会导致查询失败,因为不平衡的引号会导致语法错误。
使用prepare()
不能解决意外的语法错误,也不能防止复制修改查询语法的恶意内容。
为防止意外SQL和恶意SQL注入,您应使用如下绑定参数:
$searchterm = $_POST['searchterm'];
$sql = "SELECT username, email FROM Members where username = ?";
if ($stmt = $conn->prepare($sql)) {
$stmt->bind_param('s', $searchterm);
/* execute statement */
$stmt->execute();
...
绑定参数不会复制到SQL查询中。它们将分别发送到数据库服务器,并且在解析后 之后才与查询组合,因此不会引起语法问题。
关于您对mysqli::query()
的问题,如果您的SQL查询不需要绑定参数,则可以使用它。
发表评论:
...容易被注射,因此我可以向学生展示恶意攻击可能会造成多大危害。
这是一个例子:
几年前,我是一名SQL培训师,在一家公司的一次培训中,我谈论的是SQL注入。一位与会者说:“好的,请向我展示SQL注入攻击。”他递给我他的笔记本电脑。浏览器已打开他网站的登录屏幕(这只是他的测试网站,而不是实际的生产网站)。登录表单很简单,只有用户名和密码字段。
我从未见过他处理登录表单的代码,但是我认为表单是由某些代码处理的,例如大多数不安全的网站是:
$user = $_POST['user'];
$password = $_POST['password'];
$sql = "SELECT * FROM accounts WHERE user = '$user' AND password = '$password'";
// execute this query.
// if it returns more than zero rows, then the user and password
// entered into the form match an account's credentials, and the
// client should be logged in.
(这是我对他的代码的有根据的猜测,但我仍然没有看到代码。)
我花了五秒钟的时间来思考逻辑,然后我在登录表单中输入了一个布尔表达式来表示用户名,并为密码输入了随机垃圾字符。
然后,我登录到他的帐户-,甚至不知道甚至试图猜测他的密码。
我不会提供我使用的确切布尔表达式,但是如果您了解任何离散数学类中涵盖的基本布尔运算符优先级,那么您应该可以弄清楚。
答案 1 :(得分:0)
您尝试过这样的事情吗?
'(here put something);
这样,您将使用'关闭查询,并在添加时向其中添加其他内容。其他所有东西都将被丢弃