SQL 即使在转义引号时也会注入

SQL Injection even when escaping quote

我正在想办法解决以下问题,因为看起来有人这样做了,我想修复它。但是,在用 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()

感谢任何帮助。

你应该总是使用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 了解为什么准备好的语句更安全,但其要点是参数与查询分开传递,因此 避免在查询中嵌入不受信任的字符串

既然你已经知道prepared/parameterized语句的好处,我就不多说了。您似乎只是好奇您现有的应用程序是如何被破坏的。

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

\'' ; drop table users --

您的 SQL 语句将变为:

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

并且由于 '\'' 是一个有效值(转义单引号),您的 where 子句实际上已结束。 ; 开始一个新命令,-- 有效地注释掉结束引号。 drop table 可以是任何东西... update users set password=...insert into users values () 或攻击者想要 运行.

的任何东西

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

只是因为这在 the ESCAPE keyword is used.

时不起作用

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

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

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