我在我们公司的 Intranet 上创建了一个小型调查网页。此网页无法从外部访问。
该表单只是几个单选按钮和一个评论框。
我想保持良好的编码习惯,并想防范 SQL 注入。
SQL 注入可以发生在带有来自文本框的注释的插入语句上吗?如果是这样,我如何使用 .NET 2.0 来防范它?
我在我们公司的 Intranet 上创建了一个小型调查网页。此网页无法从外部访问。
该表单只是几个单选按钮和一个评论框。
我想保持良好的编码习惯,并想防范 SQL 注入。
SQL 注入可以发生在带有来自文本框的注释的插入语句上吗?如果是这样,我如何使用 .NET 2.0 来防范它?
注入可能发生在任何运行不正常的 SQL 语句上。
例如,假设您的评论表有两个字段,一个整数 ID 和评论字符串。所以你会INSERT
如下:
INSERT INTO COMMENTS VALUES(122,'I like this website');
考虑有人输入以下评论:
'); DELETE FROM users; --
如果您只是将注释字符串放入 SQL 中而不进行任何处理,这可能会将您的单曲INSERT
转换为以下两个语句,然后是注释:
INSERT INTO COMMENTS VALUES(123,''); DELETE FROM users; -- ');
这将从您的users
表中删除所有内容。有些人愿意花一整天时间寻找正确的表名来使用试错法和各种技巧来清空。 下面是关于如何执行 SQL 注入攻击的描述。
您需要使用参数化的 SQL 语句来防止这种情况。
这不仅仅是出于安全原因。例如,如果您天真地创建 SQL 语句,请使用以下注释:
I'm just loving this website
将导致 SQL 语法错误,因为 SQL 将撇号解释为结束引号。
使用参数化查询,以便自动为您引用文本。
SqlCommand command = connection.CreateCommand();
command.CommandText = "insert into dbo.Table (val1,val2,txt) values (@val1,@val2,@txt)";
command.AddParameterWithValue( "val1", value1 );
command.AddParameterWithValue( "val2", value2 );
command.AddParameterWithValue( "txt", text );
...
每当您将查询传递回数据库时,都可能发生 SQL 注入。这是一个简单的演示:
在 .NET 中,关键是按照 Dave Webb 的规定去做。它将通过包含整个字符串作为要提交的一个参数来防止注入尝试,处理所有可能被 SQL Server 解释以更改查询或附加其他命令的字符。
需要指出的是,SQL 注入可以发生在任何应用程序上,而不仅仅是 Web 应用程序。内部攻击通常对组织来说是最昂贵的。人们不能安全地假设攻击不会来自内部。
除了使用准备好的语句和参数而不是将字符串连接到 SQL 中之外,您还应该执行以下操作:
在服务器端验证和格式化用户输入。使用 WebScarab 之类的工具或通过欺骗您的表单可以轻松绕过客户端验证和限制。
为数据库用户帐户配置适当的权限。Web 应用程序应在您的数据库中使用单独的帐户或角色,其权限仅限于运行您的应用程序所需的表、视图和过程。确保用户对系统表没有选择权限
向用户隐藏详细的错误消息,并为您的对象使用不太常见的名称。令我惊讶的是,您多久可以确定服务器类型(oracle、mysql、sqlserver)并在错误消息中找到基本模式信息,然后从名为“user(s)”、“employee(s)”的表中获取信息。如果您没有像 (2) 那样设置您的权限,并且我可以确定您的服务器类型,那么您对 SQL Server 的此类语句持开放态度
从 information_schema.table 中选择表名
执行 sp_help foundTableName
是的,它们可能发生。防止这种情况发生的最简单方法是使用准备好的语句,而不是手动构建 SQL。
所以,而不是这样:
String sql =
String.Format("INSERT INTO mytable (text_column) VALUES ( '{0}' )",
myTextBox.Text); // Unsafe!
你会做这样的事情:
String sql = "INSERT INTO mytable (text_column) VALUES ( ? )"; // Much safer
然后将文本框的文本作为参数添加到您的 DbCommand 中,这将导致它自动转义并替换“?” 在 SQL 中。
使用准备好的语句防止 SQL 注入。placehoder(?) 的使用完全消除了sql注入漏洞。示例 String sql=Select * from user_table where username='+request.getparameter("username")+'; statement.executeQuery(sql);
上面的语句容易受到sql注入。
为了防止sql注入。按照片段使用
String sql=Select * from user_table where username=?; statement.setString(1,username);
是的,它可以。假设客户端发送这个:
OR 1 = 1
这对你来说可能是非常痛苦的
SELECT * FROM admin WHERE name = @name AND password = @password
你可以用
防止这种形式的 SQL 注入的最简单方法是使用参数和存储过程,而不是构建 sql 语句来运行。(在 C# 中或在 SQL Server 内部)。
但是,我不完全确定您是否应该花时间在这方面,除非这是您的公司政策,因为它在内部发生的机会充其量是最小的,如果确实发生了,我希望您能立即知道是谁它是。