VBA 中有没有标准的 SQL Server 注入清理方法?
不。如果有的话,我会非常担心。我不做 PHP,但我读过关于它的“标准 SQL 注入清理方法”的恐怖故事。看看带有php 和sql 标记的Code Review 问题 - 很多人都在问“这段代码安全吗?”,除非他们使用准备好的语句,否则答案总是“不”。
');--DROP TABLE Users;-- 是在UserName 数据库字段中看到的一个相当可疑的值(您认为这个答案的文本存储在哪里?),但是如果您正确编写了数据访问代码,则没有理由即使您的登录被授权(服务器端)执行这样的语句,它也会造成任何混乱。
问题不在于用户的输入。问题在于将用户输入连接到可执行 SQL 中,从而将用户输入视为可执行代码。
您想要是执行一个常量 SQL 语句。当你这样做时:
' *** DON'T DO THIS ***
Dim sql As String
sql = "SELECT Id FROM dbo.Users WHERE UserName = '" & pName & "';"
那么每次将SQL语句发送到服务器时,都是一个不同的查询:服务器甚至不知道涉及到一个参数,它所看到的只是:
SELECT Id FROM dbo.Users WHERE UserName = ''');--DROP TABLE Users;--';
注意多余的单引号;如果您在想嘿,SQL 注入被阻止了,那么您忘记了 这并不是因为您无法击败您的输入清理,NOBODY 可以。许多公司都有使用这种“注入预防”的面向世界的网站,并且认为他们的代码是安全的。当他们在推特上吹嘘自己“在十多年的在线使用中没有被黑客入侵”时,全球脚本小子需要几分钟才能将其删除。懒得去挖掘链接,但这个确切的故事发生在最近。
当您通过 ADO 发送参数化查询时,服务器会收到以下内容:
SELECT Id FROM dbo.Users WHERE UserName = ?;
请注意,查询不知道甚至不需要关心参数的类型及其周围的单引号。
请注意,无论用户输入是什么,它都是相同的语句。
请注意,参数值甚至不会涉及该查询的执行计划中的任何地方。参数单独接收,并由数据库服务器以完全安全的方式处理,由以此为生的人编写。
无论您如何努力,您或任何人都无法想出任何安全措施。
如果用户输入是可执行 SQL 语句的一部分,则它不安全,句号。
不要假装做服务器的工作。只是不要。
做得对。
学习使用 ADODB Command 和 Parameter 对象。它们有一个相当简单的 API,并且正确且一致地使用它们将击败任何字符串连接伪清理的 SQL 字符串。
这是一个详细的例子:
Const sql As String = "SELECT Id FROM dbo.Users WHERE UserName = ?;"
Dim conn As ADODB.Connection
Set conn = New ADODB.Connection
conn.ConnectionString = "{connection string}"
conn.Open
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
cmd.CommandType = adCommandText
cmd.CommandText = sql
cmd.ActiveConnection = conn
Dim userNameParam As ADODB.Parameter
Set userNameParam = New ADODB.Parameter
userNameParam.Type = adVarChar
userNameParam.Size = 60
userNameParam.Direction = adParamInput
userNameParam.Value = pUserName '<~ user input
cmd.Parameters.Append userNameParam
Dim result As ADODB.Recordset
Set result = cmd.Execute
MsgBox result("Id").Value
conn.Close
我说冗长,因为当您明确指定所有内容时,您就是这样做的。我个人使用我自己的 ADODB 包装类,使用它们,这段代码完全等同于上面的代码:
Const sql As String = "SELECT Id FROM dbo.Users WHERE UserName = ?;"
Dim result As Long
result = SqlCommand.QuickSelectSingleValue(sql, pUserName)
MsgBox result
如您所见,使用为您封装所有管道的适当的面向对象代码,向您的数据库服务器发送正确参数化且完全安全的查询一点也不难。
方法如下:
可以在on GitHub in the VBEX repository 找到这些修复了一些错误和其他功能的类,其中还包含大量其他有用的工具(在 GPLv3 下获得许可)。请注意,虽然我确实编写了一些代码,或者一些启发了那里的代码,但我不声称与 VBEX 存储库有任何关系。我确实将这些类的原始版本上传到了我自己的 VBTools 存储库,并在 CC-by-SA 下获得许可,任何 Stack Exchange 内容也是如此。