我正试图想办法解决以下问题,因为它看起来像某人,我想解决它。但是,我真的想了解攻击是如何工作的,然后用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()
感谢任何帮助。
答案 0 :(得分:4)
由于听起来你已经意识到准备/参数化陈述的好处,我不会宣讲。您似乎只是好奇您现有的应用程序是如何被破坏的。
一个简单的\' ; drop table users --
可以击败你的报价加倍。您的CleanSql()
功能会将其转换为:
\'' ; drop table users --
您的SQL语句将变为:
... WHERE [Username] = '\'' ; drop table users --'
由于'\''
是有效值(转义单引号),因此where
子句有效结束。 ;
启动一个新命令,--
有效地注释结束语。 drop table
可以是任何内容...... update users set password=...
或insert into users values ()
或攻击者想要运行的任何内容。
答案 1 :(得分: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以查看为什么预准备语句更安全,但其要点是参数与查询分开传递,因此避免在查询中嵌入utrusted string 。
答案 2 :(得分:1)
只是因为这不适用于the ESCAPE
keyword is used。
此外,您的CleanSql
函数不适用于未加引号的值(例如数值)。
这就是建议使用参数化查询的原因 - 这些查询将值视为数据而不是查询的一部分。
有时您无法使用参数化,例如,如果您动态更改ORDER BY
,或者您想动态更改从中读取数据的表。在这些情况下,您应该使用白名单来确保应用程序允许动态数据。您无法使用参数化的另一种情况是有IN
子句时。这是您的CleanSql
函数有用的地方 - 请注意,您不需要括号转义 - 这仅适用于未指定转义字符的LIKE
个查询。
答案 3 :(得分:0)
一种简单的方法:System.out.println