MS Access通过查询到SQL Server需要什么角色卫生

Eli*_*ias 0 sql-server ms-access vba pass-through

我试图将MS Access与SQL Server连接,我想确保我不容易受到SQL注入攻击.

我已经看到了使用ADO创建查询的参数化版本的建议,但我想学习如何通过DAO传递来清理我的输入.

目前我正在逃避单引号和反斜杠.

VBA中是否有任何标准的SQL Server注入卫生方法?

Mat*_*don 6

VBA中是否有任何标准的SQL Server注入卫生方法?

不.如果有的话,我会非常担心.我不做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 & "';"
Run Code Online (Sandbox Code Playgroud)

然后每次将SQL语句发送到服务器时,它都是一个不同的查询:服务器甚至不知道涉及参数,它看到的只是:

SELECT Id FROM dbo.Users WHERE UserName = ''');--DROP TABLE Users;--';
Run Code Online (Sandbox Code Playgroud)

注意额外的单引号; 如果你正在考虑嘿,SQL注入被阻止,你忘记了这不是因为你不能打败你的输入清理,那是NOBODY可以.很多公司都有使用这种"注入预防"的面向世界的网站,并认为他们的代码是安全的.当他们在推特上吹嘘他们"十多年来一直没有被黑客入侵"时,全球各地的剧本小孩需要几分钟时间才能将其删除.不能费心去挖掘链接,但这个确切的故事发生了,而不是最近.

当您通过ADO发送参数化查询时,这是服务器收到的内容:

SELECT Id FROM dbo.Users WHERE UserName = ?;
Run Code Online (Sandbox Code Playgroud)

请注意,查询不知道甚至不需要关心参数的类型及其周围的单引号.

请注意,无论用户输入是什么,它都是相同的相同语句.

请注意,参数值甚至不会涉及该查询的执行计划中的任何位置.参数是单独接收的,并由数据库服务器以完全安全的方式处理,由以此为生的人编写.

无论你怎么努力,都没有任何人可以提出的消毒方法.

如果用户输入是可执行SQL语句的一部分,那么它就不安全了.

不要假装做服务器的工作.只是不要.


做得对.

学习使用ADODB CommandParameter对象.它们有一个相当简单的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
Run Code Online (Sandbox Code Playgroud)

我说详细,因为当你明确指定一切时,你就是这样做的.就个人而言,我使用自己的ADODB包装类,并且使用它们,这段代码完全等同于上面的内容:

Const sql As String = "SELECT Id FROM dbo.Users WHERE UserName = ?;"
Dim result As Long
result = SqlCommand.QuickSelectSingleValue(sql, pUserName)

MsgBox result
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,使用适当的面向对象的代码来封装所有管道,向数据库服务器发送正确参数化且完全安全的查询并不难.

这是如何做:

修复了一些错误和其他功能的类可以在VBEX存储库的GitHub上找到,它也恰好包含一大堆其他有用的工具(根据GPLv3许可).请注意,虽然我确实编写了一些代码,或者一些启发了那些内容的代码,但我并没有声称与VBEX存储库有任何关联.我确实将这些类的原始版本上传到我自己的VBTools存储库,但是在CC-by-SA下获得许可,就像任何Stack Exchange内容一样.