GBl*_*ney 67 t-sql sql-server security sanitization sql-injection
为了开始这个,我很清楚参数化查询是最好的选择,但我想知道是什么让我在下面提出的策略容易受到攻击.人们坚持认为下面的解决方案不起作用,所以我找一个为什么它不会这样做的例子.
如果在发送到SQL Server之前使用以下转义在代码中构建动态SQL,那么什么样的注入可以打败这个?
string userInput= "N'" + userInput.Replace("'", "''") + "'"
Run Code Online (Sandbox Code Playgroud)
在SQL Server中无法使用"\"转义单引号.
我相信使用Unicode进行SQL走私(此处概述)会被生成的字符串被单引号前面的N标记为Unicode这一事实所阻碍.据我所知,SQL Server没有其他字符集会自动转换为单引号.没有未转义的单引号,我不相信注射是可能的.
我不相信String Truncation也是一个可行的载体.SQL Server肯定不会截断,因为根据microsoft,a的最大大小为nvarchar2GB .在大多数情况下,2 GB的字符串是不可行的,在我的情况下是不可能的.
二阶注入是可能的,但如果可能的话:
我并不是说这比使用参数化查询更好或者替代,但我想知道我概述的内容是如何易受攻击的.有任何想法吗?
roo*_*ook 43
在某些情况下,此转义函数将失败.最明显的是不使用单引号时:
string table= "\"" + table.Replace("'", "''") + "\""
string var= "`" + var.Replace("'", "''") + "`"
string index= " " + index.Replace("'", "''") + " "
string query = "select * from `"+table+"` where name=\""+var+"\" or id="+index
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以使用双引号"后退"来"突破".在最后一种情况下,没有什么可以"突破",所以你可以只写1 union select password from users--或攻击者所需的任何sql负载.
这个转义函数失败的下一个条件是如果在转义字符串后获取子字符串(是的,我在野外发现了这样的漏洞):
string userPassword= userPassword.Replace("'", "''")
string userName= userInput.Replace("'", "''")
userName = substr(userName,0,10)
string query = "select * from users where name='"+userName+"' and password='"+userPassword+"'";
Run Code Online (Sandbox Code Playgroud)
在这种情况下,abcdefgji'将abcdefgji''通过转义函数转换用户名,然后abcdefgji'通过获取子字符串将其转回.这可以通过将密码值设置为任何sql语句来利用,在这种情况下or 1=1--将被解释为sql并且用户名将被解释为abcdefgji'' and password=.生成的查询如下:
select * from users where name='abcdefgji'' and password=' or 1=1--
Run Code Online (Sandbox Code Playgroud)
已经提到的T-SQL和其他高级sql注入技术.高级SQL注入在SQL Server应用程序中是一篇很棒的论文,如果你还没有,你应该阅读它.
最后一个问题是unicode攻击.出现这类漏洞是因为转义函数不知道多字节编码,攻击者可以使用它来"消耗"转义字符.在字符串前加上"N"将无济于事,因为这不会影响字符串中稍后的多字节字符的值.但是,这种类型的攻击非常罕见,因为必须将数据库配置为接受GBK unicode字符串(我不确定MS-SQL是否可以执行此操作).
仍然可以进行二阶代码注入,这种攻击模式是通过信任攻击者控制的数据源创建的.转义用于将控制字符表示为其字符文字.如果开发人员忘记逃脱从获得的值select,然后在另一个查询使用此值,则BAM攻击者将不得不在他们的处置字符单引号.
测试一切,不要相信.
Str*_*DBA 17
通过一些额外的规定,您的上述方法不易受SQL注入攻击.要考虑的主要攻击媒介是SQL走私.当类似的unicode字符以意想不到的方式翻译时(例如`更改为'),就会发生SQL走私.有几个位置,应用程序堆栈可能容易受到SQL走私攻击.
编程语言是否适当地处理unicode字符串? 如果该语言不能识别unicode,它可能会将unicode字符中的一个字节错误地识别为单引号并将其转义.
客户端数据库(例如ODBC等)是否正确处理unicode字符串? .Net框架中的System.Data.SqlClient可以,但是从Windows 95时代的旧库怎么样?第三方ODBC库实际上确实存在.如果ODBC驱动程序不支持查询字符串中的unicode会发生什么?
DB是否正确处理输入? 假设您正在使用N',现代版本的SQL是免疫的,但SQL 6.5呢?SQL 7.0?我不知道有任何特殊的漏洞,但这对于1990年代的开发人员来说并不是很明显.
缓冲区溢出?另一个问题是引用的字符串比原始字符串长.在哪个版本的Sql Server中引入了2GB的输入限制?在那之前是什么限制?在旧版本的SQL上,当查询超出限制时会发生什么?从网络库的角度来看,查询的长度是否存在任何限制?或者编程语言中字符串的长度?
是否有任何语言设置会影响Replace()函数中使用的比较? .Net总是对Replace()函数进行二进制比较.总是这样吗?如果.NET的未来版本支持在app.config级别覆盖该行为,会发生什么?如果我们使用regexp而不是Replace()来插入单引号怎么办?计算机的区域设置是否会影响此比较?如果确实发生了行为上的改变,它可能不容易受到sql注入的影响,但是,它可能无意中编辑了字符串,方法是在它到达数据库之前将看起来像单引号的单代码字符更改为单引号.
因此,假设您在当前版本的.Net上使用C#中的System.String.Replace()函数,并在当前(2005-2012)版本的SQL Server上使用内置的SqlClient库,那么您的方法不是脆弱.当你开始改变事物时,就不会有任何承诺.参数化查询方法是提高效率,性能和(在某些情况下)安全性的正确方法.
警告以上评论并非对此技术的认可.还有其他几个很好的理由说明为什么这种生成SQL的错误方法.但是,详细说明它们不在此问题的范围之内.
请勿将此技术用于新开发.
请勿将此技术用于新开发.
请勿将此技术用于新开发.
使用查询参数比转义引号更好,更简单,更快捷.
重新评论,我看到你承认参数化,但值得强调.为什么要在参数化时使用转义?
在高级SQL注入中在SQL Server应用程序中,在文本中搜索单词"replace",并从此读取一些示例,其中开发人员即使在转义用户输入后也无意中允许SQL注入攻击.
有一个边缘情况,其中转义引号\导致漏洞,因为\在某些字符集中它变为有效多字节字符的一半.但这并不适用于您的情况,因为\它不是逃避角色.
正如其他人所指出的那样,您可能还会在SQL中添加动态内容,而不是字符串文字或日期文字.表或列标识符由"SQL或[ ]Microsoft/Sybase 分隔.SQL关键字当然没有任何分隔符.对于这些情况,我建议将值列入白名单进行插值.
最重要的是,逃避是一种有效的防御,如果你可以确保你一贯地做到这一点.这就是风险:应用程序中的开发人员团队中的一个可能会省略一个步骤,并且不安全地执行一些字符串插值.
当然,其他方法也是如此,例如参数化.只有持续不断地执行它们才有效.但我发现使用参数更容易,而不是找出正确的转义类型.开发人员更有可能使用方便且不会减慢速度的方法.
如果用户提供的输入被解释为命令,则会发生 SQL 注入。这里的命令意味着任何不被解释为可识别的数据类型文字的东西。
\n\n现在,如果您\xe2\x80\x99仅在数据文字中使用用户\xe2\x80\x99s输入,特别是仅在字符串文字中,则用户输入只有在能够离开时才会被解释为与字符串数据不同的内容字符串文字上下文。对于字符串或Unicode字符串文字,它\xe2\x80\x99是包围文字数据的单引号,而嵌入的单引号需要用两个单引号表示。
\n\n因此,要保留字符串文字上下文,需要提供一个单引号 (sic),因为两个单引号被解释为字符串文字数据,而不是字符串文字结束分隔符。
\n\n因此,如果您\xe2\x80\x99 将用户提供的数据中的任何单引号替换为两个单引号,则用户将无法离开字符串文字上下文。
\nSQL 注入可以通过 unicode 进行。如果 Web 应用程序具有如下 URL:
\n\nhttp://mywebapp/widgets/?Code=ABC
\n\n它生成类似于 \nselect * from widgets where Code = \'ABC\' 的 SQL
\n\n但黑客输入了以下内容:
\n\nhttp://mywebapp/widgets/?Code=ABC%CA%BC;删除表小部件--
\n\nSQL 看起来像 \nselect * from widgets where Code = \'ABC\xe2\x80\x99;drop table widgets--\'
\n\nSQL Server 将运行两个 SQL 语句。一个用于执行选择,一个用于执行删除。\n您的代码可能会将 url 编码的 %CA%BC 转换为 unicode U02BC,这是一个“修饰符字母撇号”。.Net 中的 Replace 函数不会将其视为单引号。然而,Microsoft SQL Server 将其视为单引号。下面是一个可能允许 SQL 注入的示例:
\n\nstring badValue = ((char)0x02BC).ToString();\nbadValue = badValue + ";delete from widgets--";\nstring sql = "SELECT * FROM WIDGETS WHERE ID=" + badValue.Replace("\'","\'\'");\nTestTheSQL(sql);\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
37463 次 |
| 最近记录: |