【问题标题】:SQL Injection even when escaping quote即使在转义引号时也进行 SQL 注入
【发布时间】:2015-08-28 05:26:01
【问题描述】:

我正在想办法解决以下问题,因为看起来有人这样做了,我想修复它。但是,我真的很想在使用OWASP Recommendation 之类的东西修复它之前了解攻击是如何工作的

    Set conn = Server.CreateObject("ADODB.Connection")
    conn.open xDb_Conn_Str
    sSql = "SELECT * FROM [User]"
    sSql = sSql & " WHERE [Username] = '" & CleanSql(sUserId) & "'"
    Set rs = conn.Execute(sSql)

CleanSql -

Function CleanSql(str)

    Dim sWrk

    sWrk = Trim(str&"")
    sWrk = Replace(sWrk, "'", "''") ' Adjust for Single Quote

    sWrk = Replace(sWrk, "[", "[[]") ' Adjust for Open Square Bracket

    CleanSql = sWrk

End Function

单引号显然被转义了。

在此之后,它将检查是否找到用户使用以下内容验证密码:

If UCase(rs("Password")) = UCase(sPassWd) Then
    DoStuff()

感谢任何帮助。

【问题讨论】:

  • 您不能将准备好的语句与绑定变量一起使用吗?你用的是什么数据库? stackoverflow.com/questions/149848/…
  • “看起来有人做了(使用 SQL 注入绕过密码检查”。你确定吗?证据是什么?难道他们不能只是嗅探、猜测或以其他方式获得密码或会话饼干?
  • DB 是 sql - 我可以使用它。我正在接管应用程序
  • 东西已添加到帖子等。这就是我确定@Thilo
  • 您可以在不绕过密码检查逻辑的情况下向网站帖子添加内容。被盗的管理员密码。跨站脚本。合法但愤怒的用户。缺少会话验证代码。肯定会转向准备好的陈述,但你的黑客可能会进入其他地方。

标签: security asp-classic sql-injection


【解决方案1】:

由于听起来您已经意识到准备好的/参数化语句的好处,所以我不会说教。您似乎只是好奇您现有的应用程序是如何被破坏的。

一个简单的\' ; drop table users -- 可以击败你的报价加倍。您的 CleanSql() 函数会将其变为:

\'' ; drop table users --

您的 SQL 语句将变为:

... WHERE [Username] = '\'' ; drop table users --'

由于'\'' 是一个有效值(转义的单引号),您的where 子句有效地结束了。 ; 启动一个新命令,-- 有效地消除了结束引号。 drop table 可以是任何东西...update users set password=...insert into users values () 或攻击者想要运行的任何东西。

【讨论】:

  • 我要搞砸这个。我的问题的好答案,可能被标记为解决方案。谢谢
  • 我试过\' ; select Username from dbo.users where userid = 29 --,因为我知道密码,但它仍然不起作用。现在我很好奇,因为你的解释看起来是正确的。
  • 出色的工作 007。所以在这种情况下,他们实际上可以完成 SELECT * FROM [Users] WHERE [Username] = '\'' UNION SELECT 'ourname', 'ourpassword' FROM [Users]
  • 这只是如何绕过这种类型的字符串连接的一个示例。例如,您的数据库可能不支持以这种方式 (\') 转义单引号。但有些人会。如果不是这样,很可能是类似的事情。字符的表示方式有很多种:转义、编码、不同的字符集等。
【解决方案2】:

你应该总是使用Prepared statement,因为在大多数情况下转义是不够的,因为总会有你会忘记的特殊情况。

Dim cmdPrep1 As New ADODB.Command
Set cmdPrep1.ActiveConnection = conn

cmdPrep1.CommandText = "SELECT * FROM [User]  WHERE [Username] = ?"
cmdPrep1.CommandType = adCmdText
cmdPrep1.Prepared = True

Set prm1 = cmdPrep1.CreateParameter("Username", adChar, adParamInput, Len(sUserId), sUserId)
cmdPrep1.Parameters.Append prm1

Set rs = cmdPrep1.Execute()

如果准备好的语句不适用于您的语言或数据库,强烈考虑切换。
请参阅此wikipedia article 了解为什么准备好的语句更安全,但其要点是参数与查询分开传递,因此避免在查询中嵌入不受信任的字符串

【讨论】:

  • 太好了,我知道大部分情况下如何防范它……我知道通常推荐的方法。我想知道这是否真的是接入点,以及有人会如何解决上述问题。谢谢你的帖子。
  • 准备好的语句是OWASP prevention list中的第一个推荐
【解决方案3】:

仅仅是因为这不适用于the ESCAPE keyword is used

此外,您的 CleanSql 函数不适用于未加引号的值(例如数值)。

这就是为什么建议使用参数化查询 - 这些将值视为数据而不是查询的一部分。

有时您不能使用参数化,例如,如果您动态更改 ORDER BY,或者如果您想动态更改从中读取数据的表。在这些情况下,您应该使用白名单来确保您的应用程序允许动态数据。不能使用参数化的另一种情况是存在IN 子句。这是您的 CleanSql 函数有用的地方 - 请注意,您不需要括号转义 - 这仅适用于未指定转义字符的 LIKE 查询。

【讨论】:

    【解决方案4】:

    一个简单的方法:var = Replace(Request.Form("form"),"'","\'")

    【讨论】:

    • 简单,但绝不安全
    猜你喜欢
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-04
    • 2013-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多