浏览网页中较为可疑的部分,我碰巧遇到了这种特殊的SQL注入:
http://server/path/page.php?id=1+union+select+0,1,concat_ws(user(),0x3a,database(),0x3a,version()),3,4,5,6--
我对SQL的了解 - 我认为这是一个不错的 - 在我读到这篇文章时似乎非常有限。
自从我为网络广泛开发以来,我很想知道这段代码实际上做了什么,更重要的是 它是如何工作的。
答案 0 :(得分:8)
它取代了不正确编写的参数化查询,如下所示:
$sql = '
SELECT *
FROM products
WHERE id = ' . $_GET['id'];
使用此查询:
SELECT *
FROM products
WHERE id = 1
UNION ALL
select 0,1,concat_ws(user(),0x3A,database(),0x3A,version()),3,4,5,6
,它为您提供有关数据库名称,版本和用户名的信息。
答案 1 :(得分:4)
注入结果依赖于对基础查询语法的一些假设。
这里假设的是代码中的某个地方有一个查询,它将采用“id”参数并将其直接替换为查询,而无需对其进行清理。
它假定了一个简单的查询语法:
select * from records where id = {id param}
这样做会导致替换查询(在上面的示例中):
select * from records where id = 1 union select 0, 1 , concat_ws(user(),0x3a,database(),0x3a,version()), 3, 4, 5, 6 --
现在,这有用的是,它不仅设法抓住程序感兴趣的记录,而且还设置了一个伪造的数据集UNIONs告诉攻击者(这些值在冒号中以冒号分隔)第三栏):
只需运行即可获得相同的信息:
select concat_ws(user(),0x3a,database(),0x3a,version())
直接在sql提示符下,你会得到类似的东西:
joe:production_db:mysql v. whatever
此外,由于UNION进行了隐式排序,并且伪造数据集中的第一列以0开头,因此您的虚假结果可能位于列表的顶部。这很重要,因为程序可能只使用了第一个结果,或者我在上面给出的基本表达式中有一些额外的SQL,它将结果集限制为一条记录。
存在上述噪音的原因(例如选择0,1,...等)是为了使其起作用,您调用UNION的语句必须具有与第一个结果集。因此,只有相应的记录表有7列时,上述注入攻击才有效。否则你会得到语法错误,这种攻击不会真正给你你想要的。双破折号( - )只是为了确保忽略替换后可能发生的任何事情,并得到我想要的结果。 0x3a垃圾只是说“用冒号分隔我的值”。
现在,使这个查询作为攻击向量有用的原因是,如果表有多于或少于7列,则可以手动重写它。
例如,如果上述查询不起作用,并且该表有5列,经过一些实验后,我会点击以下查询URL作为注入向量:
http://server/path/page.php?id=1+union+select+0,1,concat_ws(user(),0x3a,database(),0x3a,version()),3,4--
攻击者猜测的列数可能基于对页面的有根据的看法。例如,如果您正在查看列出商店中所有Doodads的页面,它看起来像:
Name | Type | Manufacturer
Doodad Foo Shiny Shiny Co.
Doodad Bar Flat Simple Doodads, Inc.
这是一个非常好的猜测,你正在查看的表有4列(如果我们通过'id'参数搜索,请记住最有可能隐藏在某处的主键)。
对于文字墙感到抱歉,但希望能回答你的问题。
答案 2 :(得分:1)
此代码向page.php上正在执行的select语句添加了一个额外的联合查询。注入器已确定原始查询有6个字段,因此选择数值(列计数必须与联合匹配)。 concat_ws只创建一个字段,其中包含数据库用户,数据库和版本的值,以冒号分隔。
答案 3 :(得分:0)