网站已通过 SQL 注入被黑客入侵
Posted
技术标签:
【中文标题】网站已通过 SQL 注入被黑客入侵【英文标题】:Site has been hacked via SQL Injection 【发布时间】:2011-06-03 19:27:53 【问题描述】:最近我的网站被 SQL 注入攻击了。黑客使用了以下查询 获取我的数据库名称。我无法理解他们写的这个查询。
查询:
=-999.9%20UNION%20ALL%20SELECT%20concat(0x7e,0x27,Hex(cast(database()%20as%20char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235343830303536--
查询运行后,它显示一个整数结果,类似于“74545883
”。
您能解释一下查询的工作原理吗?
【问题讨论】:
请不要在您的查询上签名,我们知道您是谁 这是您日志中唯一的条目吗? 请不要签署您的查询 - 有一会儿,我想知道签署 mysql 查询是什么意思:) 有问题的查询...因为它模棱两可,所以我编辑它 【参考方案1】:首先,查询看起来像是 html 编码的。将%20
s 替换为空格,它将变得更具可读性。他们还将部分查询转换为某事物的十六进制表示。尝试对语句的那部分进行十六进制解码。
当您尝试将 SQL 作为字符串动态创建,然后将其发送到 DBMS 时,就会产生 SQL 注入风险。想象一下这样的字符串存储在您的系统中,用于搜索栏等:
SELECT * FROM SOME_TABLE WHERE SOME_COLUMN=
要完成查询并让攻击进入,他们需要这样输入:
'x' or 1=1
在这种情况下,查询将变为:
SELECT * FROM SOME_TABLE WHERE SOME_COLUMN='x' or 1=1
SOME_COLUMN
可以是任何变量,它在哪里失败并不重要,重要的是1=1
始终为真,从而可能让攻击者访问该表中的每一行。
既然您已经了解它,请检查您的代码并将每个动态创建的查询替换为准备好的语句。 OWASP 网站也有很多用于防御性编码的资源:
www.owasp.org
【讨论】:
【参考方案2】:查询使用DATABASE() 返回数据库名称,然后使用HEx() 函数将其转换为十六进制值。
一旦他们有了这个,他们就可以使用UNHEX函数
查看UNHEX
示例
mysql> SELECT UNHEX('4D7953514C');
-> 'MySQL'
mysql> SELECT 0x4D7953514C;
-> 'MySQL'
mysql> SELECT UNHEX(HEX('string'));
-> 'string'
mysql> SELECT HEX(UNHEX('1267'));
-> '1267'
很高兴知道它们是如何进入的,但总而言之,您需要修复代码以避免 SQL 注入。
【讨论】:
@astander - 他询问查询是如何工作的。我将其解释为“他们是如何绕过我的(缺乏)预防的”,而不是“这里的每个功能都做了什么”。我觉得一个人应该能够执行“mysql HEX”的google查询,但是新手可能不适应转义查询和常见的mysql注入尝试,是吗? 谷歌搜索“mysql HEX”会告诉他该函数的作用(就像你链接的那样),但谷歌搜索“mysql注入”不会告诉他为什么他的特定查询被黑客入侵...... 【参考方案3】:它看起来像overflow attack。他们UNION
-ed 与您现有的查询。用 (space) 替换所有 %20
,因为它的 url 编码产生:
=-999.9 UNION ALL SELECT CONCAT(0x7e,0x27,Hex(cast(database() as char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235343830303536-
分解:
=-999.9
刚刚结束您当前的查询
0x31303235343830303536
是 NULL
- 它们只是匹配现有查询中的列数。如果您有 SELECT * FROM users
并且 users
有 4 列,那么 UNION
也必须有 4 列。因此,他们只是使用 `NULL 值来填充这些列。
真正的困惑在于CONCAT()
。它们组合了 126、39、数据库名称为十六进制值、39 和 126
--
是一个 mysql 注释 - 之后它会忽略您的其余查询
从这次攻击来看,我怀疑您没有将输入包装在mysql_real_escape_string()
中,这使得被攻击者可以跳出您的查询并执行自己的查询。
更多信息请参见owasp.org。
【讨论】:
unhex(0x31303235343830303536) 给出了“%H V”。可能是电话卡?这是一个非常大的数字——介于 2^78 和 2^79 之间。 可能是 mysqls max_int - 试图溢出? 附带说明,31303235343830303536 的 ASCII 表示是“1025480056”——在 ASCII 中,0x3n 是数字 n。 有点像死灵,但我想我不妨告诉你,0x31303235343830303536 是自动 SQL 注入工具 Havij 的名片。【参考方案4】:这不是完整的查询,实际上是这个人在你的网络应用中输入了这个字符串。
现在,首先将联合部分中的 %20 替换为空格,你会得到:
SELECT concat(0x7e,0x27,Hex(cast(database() as char)),0x27,0x7e),0x31303235343830303536,0x31303235343830303536,0x31303235343830303536--
似乎用户将字符串放在您期望数字的某个地方。因此,您看到首先有一个数字(999.9)来完成查询的原始条件。然后,添加一个 UNION 部分。 最后,在 UNION 部分之后,添加注释字符 (-- ),以便绕过查询的其余部分(可能正在由您的系统添加)。
我们可以格式化代码以便更好地理解:
SELECT
concat
(
0x7e,
0x27,
Hex(cast(database() as char)),
0x27,
0x7e
),
0x31303235343830303536,
0x31303235343830303536,
0x31303235343830303536
现在,结果第一列的子字符串将包含您的数据库名称的十六进制编码形式。其实应该用单引号(0x27)括起来,然后再用~(0x7e)括起来
【讨论】:
【参考方案5】:-999.9 UNION ALL SELECT
CONCAT('Hex(cast(database() as char))'),
0x31303235343830303536,
0x31303235343830303536,
0x31303235343830303536
我认为你的日志中肯定还有其他条目,如果不是他事先知道你有 3 列。
【讨论】:
【参考方案6】:这是使用 Havij 进行注入的示例
0x7e 和 0x27 对应于 ~ 和 ' ,它们将用于构建 HTML 显示
如
id=999999.9+union+all+select+0x31303235343830303536,(select+concat(0x7e,0x27,unhex(Hex(cast(sample_tbl.name+as+char))),0x27,0x7e)+from+test
.sample_tbl+订单+by+id+limit+0,1)+--
这个查询会从test表中的sample_tbl表中渲染~'Alfred'~是列名的字段值
~'r3dm0v3_hvj_injection'~是根据http://www.string-functions.com/hex-string.aspx的Havij签名码unhex 0x7233646D3076335F68766A5F696E6A656374696F6E
【讨论】:
他们在我的网站上尝试了相同的 MySQL 注入,但他们在页面上尝试了没有任何数据库查询,一切都基于文件:-)【参考方案7】:是的,他得到了您所说的数据库名称的十六进制形式,即“74545883”。 通过 Unhexing,他将获得真正的数据库名称。
【讨论】:
以上是关于网站已通过 SQL 注入被黑客入侵的主要内容,如果未能解决你的问题,请参考以下文章