看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
看看:
(来源:https://xkcd.com/327/)
这个SQL做什么:
Robert'); DROP TABLE STUDENTS; --
我知道'和——都是用来评论的,但是DROP这个词不是也会被评论吗?因为它是同一行的一部分。
当前回答
进行SQL注入时不需要输入表单数据。
之前没有人指出这一点,所以我要提醒你们。
大多数情况下,我们将尝试修补表单输入。但这并不是SQL注入攻击的唯一地方。你可以对URL进行非常简单的攻击,通过GET请求发送数据; 考虑下面的例子:
<a href="/show?id=1">show something</a>
你的url是这样的 http://yoursite.com/show?id=1
现在有人可以尝试这样的方法
http://yoursite.com/show?id=1;TRUNCATE table_name
尝试用真实的表名替换table_name。如果他记对了你的桌名,他们就会把你的桌子清空!(这是非常容易brut force这个URL与简单的脚本)
您的查询应该是这样的……
"SELECT * FROM page WHERE id = 4;TRUNCATE page"
使用PDO的PHP易受攻击代码示例:
<?php
...
$id = $_GET['id'];
$pdo = new PDO($database_dsn, $database_user, $database_pass);
$query = "SELECT * FROM page WHERE id = {$id}";
$stmt = $pdo->query($query);
$data = $stmt->fetch();
/************* You have lost your data!!! :( *************/
...
解决方案-使用PDO prepare()和bindParam()方法:
<?php
...
$id = $_GET['id'];
$query = 'SELECT * FROM page WHERE id = :idVal';
$stmt = $pdo->prepare($query);
$stmt->bindParam('idVal', $id, PDO::PARAM_INT);
$stmt->execute();
$data = $stmt->fetch();
/************* Your data is safe! :) *************/
...
其他回答
它删除了学生表。
学校程序的原始代码可能看起来像这样
q = "INSERT INTO Students VALUES ('" + FNMName.Text + "', '" + LName.Text + "')";
这是向查询中添加文本输入的最简单的方法,非常糟糕,正如您将看到的那样。
值从第一个名字,中间名文本框FNMName。文本(是罗伯特的);降表学生;——)和姓氏文本框LName。文本(让我们称之为Derper)连接到查询的其余部分,结果实际上是两个查询由语句结束符(分号)分开。第二个查询已注入到第一个查询中。当代码对数据库执行此查询时,它将如下所示
INSERT INTO Students VALUES ('Robert'); DROP TABLE Students; --', 'Derper')
简单地说,就是这两个问题:
在student表中添加一条Name值为'Robert'的新记录
and
删除Students表
第二个查询之后的所有内容都被标记为注释:——','Derper')
学生名字中的'不是注释,而是结束字符串分隔符。因为学生的名字是一个字符串,所以在语法上需要它来完成假设的查询。只有当注入的SQL查询结果为有效SQL时,注入攻击才有效。
根据dan04的评论再次编辑
');结束查询,不开始注释。然后它删除students表,并注释本该执行的其余查询。
假设你天真地写了一个学生创建方法,像这样:
void createStudent(String name) {
database.execute("INSERT INTO students (name) VALUES ('" + name + "')");
}
有人输入名字罗伯特’);降表学生;--
在数据库上运行的是这个查询:
INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --')
分号结束插入命令并开始另一个;——注释掉了该行的其余部分。DROP TABLE命令被执行…
这就是为什么绑定参数是一个好东西。
它是这样工作的: 假设管理员正在查找学生的记录
Robert'); DROP TABLE STUDENTS; --
由于admin帐户拥有很高的权限,因此可以从该帐户中删除表。
从请求中检索用户名的代码是
现在查询是这样的(搜索student表)
String query="Select * from student where username='"+student_name+"'";
statement.executeQuery(query); //Rest of the code follows
生成的查询变成
Select * from student where username='Robert'); DROP TABLE STUDENTS; --
由于用户输入没有被净化,上面的查询被操作成两个部分
Select * from student where username='Robert');
DROP TABLE STUDENTS; --
双破折号(——)将注释掉查询的其余部分。
这是很危险的,因为如果存在密码验证,它会使密码验证无效
第一个会进行正常的搜索。
如果帐户有足够的权限,第二个将删除表student(通常学校管理帐户将运行这样的查询,并将具有上面讨论的权限)。
假设名称用于变量$ name。然后运行这个查询:
INSERT INTO Students VALUES ( '$Name' )
该代码错误地将用户提供的任何内容作为变量。你希望SQL是:
插入学生价值观(“罗伯特表格”)
但聪明的用户可以提供他们想要的任何东西:
INSERT INTO Students VALUES ('Robert');DROP TABLE Students;——”)
你得到的是:
INSERT INTO Students VALUES ( 'Robert' ); DROP TABLE STUDENTS; --' )
——only注释该行的其余部分。