今天,在管理客户端的服务器时,我们的监控确定了一些缓慢的页面加载时间/其他问题。我在对此进行故障排除时注意到,以下查询在进程列表中并且似乎永远不会完成:
SELECT *
FROM motorcycles
LEFT JOIN motorcycle_year
ON motorcycle_year.year_id = motorcycles.motorcycle_vyear
LEFT JOIN motorcycle_make
ON motorcycle_make.make_id = motorcycles.motorcycle_vmake
LEFT JOIN dealers
ON dealers.dealer_id = motorcycles.motorcycle_dealer
LEFT JOIN motorcycle_subtype
ON subtype_id = motorcycle_subtype
LEFT JOIN fuel_type
ON fuel_id = motorcycle_fuel
WHERE motorcycle_id = -3885
OR 1073 = Sleep(5)
AND motorcycle_dealer = '91'
起初我认为这是客户端代码中的一个错误,但后来我确定它必须是SQL注入的结果,因为这部分:
WHERE motorcycle_id = -3885
OR 1073 = Sleep(5)
AND motorcycle_dealer = '91'
所以看起来像某种sql注入DOS攻击。由于我不理解的技术原因,这个查询似乎永远不会完成。
我尝试使用测试表和简单查询在更简单的上下文中重现它:
SELECT *
FROM users
WHERE id = -9000
OR 1073 = Sleep(5)
AND foo = 'bar'
但正如我所料,它在大约5秒内完成。那么为什么前一个查询永远不会完成?它与连接有关吗?在这一点上,我想从纯粹的好奇心中理解这一点。
如果这更适合其他堆栈交换论坛,请随时将问题迁移到那里。
编辑:为了清楚起见,如果我用类似但更纯粹的值替换,那么前一个查询(似乎是DOS sql注入的查询)几乎立即返回:
WHERE motorcycle_id =
1 AND motorcycle_dealer = '91';
答案 0 :(得分:0)
我认为SQL注入攻击是恶意的。写得不好的SQL查询会有所不同。许多连接涉及更多表和更多操作。复杂where子句的复制可能很快。如果其他表经过查询,备份,重新编制索引,则它们可能执行缓慢。 where子句在具有连接的多表查询中具有不明确的列。您可能希望使用表别名来消除歧义。
所有事情都是常量,使用数字等价测试的where子句应该比正则表达式(字符串等价测试)执行得更快。但现实世界比我们理论化的更复杂。鉴于连接的复杂性,sleep(5)可以在where子句中被多次调用。这就解释了为什么用于隔离问题的再现微型查询在如此短的时间内完成。
答案 1 :(得分:0)
这里的礼仪不确定,但我只想在PM77-1的评论here
的帮助下将其标记为已解决基本上每个记录都会发生SLEEP(5)
,因为必须为每个记录评估条件。在我的测试表中,我只有一条记录,所以我无法重现看似永无止境的查询。