我已在公司内网创建了一个小型调查网页。该网页无法从外部访问。
该表单只包含几个单选按钮和一个评论框。
我想要遵循良好的编码实践,并希望防范SQL注入攻击。
插入语句中的文本框注释是否可能会导致SQL注入攻击?如果是,如何使用.NET 2.0来避免它?
我已在公司内网创建了一个小型调查网页。该网页无法从外部访问。
该表单只包含几个单选按钮和一个评论框。
我想要遵循良好的编码实践,并希望防范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语句。I'm just loving this website
由于 SQL 将撇号解释为闭合引号,这将导致 SQL 语法错误。
string.replace
方法,但现在看来这个方法更加简便易行。 - Brad使用参数化查询,这样文本会自动为您加上引号。
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、SQL Server),并在错误消息中找到基本模式信息,然后从名为“user(s)”、“employee(s)”的表中获取信息。如果您还没有像(2)中设置权限,而我可以确定您的服务器类型,那么您会面临像这样的SQL Server语句:
SELECT table_name FROM information_schema.table
EXECUTE 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 注入。占位符(?)的使用完全消除了 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内部)。
然而,我并不完全确定你是否应该花时间处理这个问题,除非这是你公司的政策,因为它在内部发生的可能性最小,如果确实发生了,我希望你能立即知道是谁造成的。