简体   繁体   English

SQL注入和LIMIT子句

[英]SQL Injection and the LIMIT clause

This question is to settle an argument between me and a coworker. 这个问题是为了解决我和同事之间的争论。

Let's say we have the following query, executed on a standard LAMP server. 假设我们在标准LAMP服务器上执行以下查询。

SELECT field1, field2, field3
FROM some_table
WHERE some_table.field1 = 123
ORDER BY field2 DESC
LIMIT 0, 15

Now let's assume the limit clause is vulnerable to SQL injection. 现在让我们假设limit子句容易受到SQL注入的攻击。

LIMIT [insert anything here], [also insert anything here]

The point of my coworker is that there is no way to exploit this injection, so there's no need to escape it (since it take more processing power and stuff). 我的同事的观点是没有办法利用这种注射,所以没有必要逃避它(因为它需要更多的处理能力和东西)。

I think her reasoning is stupid, but I can't figure out how to prove her wrong by finding an example. 我认为她的推理是愚蠢的,但我找不到如何通过寻找一个例子来证明她的错。

I can't use UNION since the query is using an ORDER BY clause, and the MySQL user running the query doesn't have the FILE priviledge so using INTO OUTFILE is also out of the question. 我不能使用UNION因为查询使用ORDER BY子句,并且运行查询的MySQL用户没有FILE特权,因此使用INTO OUTFILE也是不可能的。

So, can anyone tell us who is right on this case? 那么,谁能告诉我们谁在这个案子上是对的呢?

Edit : the query is executed using PHP, so adding a second query using a semicolon won't work. 编辑 :查询是使用PHP执行的,因此使用分号添加第二个查询将不起作用。

The LIMIT clause is vulnerable to SQL injection, even when it follows an ORDER BY , as Maurycy Prodeus demonstrated earlier this year: 正如Maurycy Prodeus今年早些时候演示的那样, LIMIT子句容易受到SQL注入攻击,即使它遵循ORDER BY

 mysql> SELECT field FROM user WHERE id >0 ORDER BY id LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1); ERROR 1105 (HY000): XPATH syntax error: ':5.5.41-0ubuntu0.14.04.1' 

Voilà! 瞧! The above solution is based on handy known technique of so-called error based injection. 上述解决方案基于所谓的基于错误的注入的已知技术。 If, therefore, our vulnerable web application discloses the errors of the database engine (this is a real chance, such bad practices are common), we solve the problem. 因此,如果我们易受攻击的Web应用程序公开了数据库引擎的错误(这是一个真正的机会,这种不良做法很常见),我们就能解决问题。 What if our target doesn't display errors? 如果我们的目标没有显示错误怎么办? Are we still able to exploit it successfully? 我们还能成功利用它吗?

It turns out that we can combine the above method with another well-known technique – time based injection. 事实证明,我们可以将上述方法与另一种众所周知的技术结合起来 - 基于时间的注入。 In this case, our solution will be as follows: 在这种情况下,我们的解决方案如下:

 SELECT field FROM table WHERE id > 0 ORDER BY id LIMIT 1,1 PROCEDURE analyse((select extractvalue(rand(), concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1) 

It works. 有用。 What is interesting that using SLEEP is not possible in this case. 有趣的是,在这种情况下使用SLEEP是不可能的。 That's why there must be a BENCHMARK instead. 这就是必须有一个基准的原因。

SQL Injection occurs if “ externally-influenced input […] could modify the intended SQL command ”. 如果“受外部影响的输入可以修改预期的SQL命令 ”,则会发生SQL注入。 And in this case it's clear that user input can modify the intended SQL command. 在这种情况下,很明显用户输入可以修改预期的SQL命令。

However, exploitability is another question. 但是,可利用性是另一个问题。 You may not be able to exploit it today . 今天可能无法利用它。 But maybe someday someone is able to exploit it because: 但也许有一天有人能够利用它,因为:

  • The database connection layer has changed and it is possible to execute multiple statements at once. 数据库连接层已更改,可以一次执行多个语句。
  • The statement has changed and it is possible to use UNION . 声明已更改,可以使用UNION
  • The user privileges have changed and it is possible to use INTO OUTFILE / INTO DUMPFILE . 用户权限已更改,可以使用INTO OUTFILE / INTO DUMPFILE
  • Someone finds a way that you may not have thought of. 有人找到了一种你可能没有想过的方法。 Have you noticed you can store the result in variables and/or execute a stored procedure ? 您是否注意到可以将结果存储在变量中和/或执行存储过程

If you are creating the SQL query from user input, then it will be vulnerable, unless you are using strong typing way before you get anywhere near generating the query. 如果您是从用户输入创建SQL查询,那么它将是易受攻击的,除非您在生成查询之前使用强类型方式 In such a case, there's no way you could make an integer become text saying to drop a table, for example. 在这种情况下,例如,你无法使整数成为一个表格来删除表格的文本。

Never trust user input, and always perform bounds checking. 永远不要信任用户输入,并始终执行边界检查。 For example, don't even bother doing the query if the limit values are negative. 例如,如果限制值为负,则甚至不打扰执行查询。

I would insert this: 我会插入这个:

1; DELETE FROM some_table WHERE 1; --

Just after the limit, that will select 1 row from some_table, then DELETE all some_table rows. 在限制之后,将从some_table中选择1行,然后删除所有some_table行。 then the rest will be considered as a comment. 然后其余的将被视为评论。

You should come with a coding example, not a query example as you do now. 您应该使用编码示例,而不是现在的查询示例。 She is right on the fact that you cannot really alter a statement since the order by function is always "last". 她是对的,你不能真正改变一个陈述,因为按功能的顺序总是“最后”。 So yes, when you are manually inputting those query's on a sql server, you simply cannot alter the query to output something different rather than a error message. 所以,是的,当您在SQL服务器上手动输入这些查询时,您根本无法更改查询以输出不同的内容而不是错误消息。 Yet, when you simply add an other query.. you can :) 然而,当你只是添加一个其他查询..你可以:)

Finish the last user input as a true value to let the first query run successfully, and add a ';'. 将最后一个用户输入作为真值完成,以使第一个查询成功运行,并添加“;”。 Now you can start your own query. 现在您可以开始自己的查询了。

I just have done this on my local mysql server: 我刚刚在我的本地mysql服务器上完成了这个:

SELECT * FROM city order by ID desc limit 0,15; SELECT * FROM city

Even so, in a strong case where there is absolute 0% chance someone could alter the statement, you simply do not even want to receive possible altered data. 即便如此,在强有力的情况下,有人可能会改变声明的绝对0%,你根本不想接收可能的改变数据。 There should be a reason you use the LIMIT dynamically. 应该有一个动态使用LIMIT的原因。 Once a person can change your reason, you already have failed. 一旦一个人改变了你的理由,你就已经失败了。 Its not even about risking damage, losing data or what ever. 它甚至没有冒险损坏,丢失数据或者什么都没有。 You do not want any manipulation in any way. 你不希望以任何方式进行任何操纵。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM