SQL Server应用程序高级SQL注入预防入侵
择要:
这份文档是详细讨论SQL注入技术,它顺应于比力盛行的IIS+ASP+SQLSERVER平台。它讨论了哪些SQL语句能通过种种各样的要领注入到应用步伐中,而且记载与打击相关的数据确认和数据库锁定。
这份文档的预期读者为与数据库通讯的WEB步伐的开辟者和那些饰演审核WEB应用步伐的安全专家。
先容:
SQL是一种用于干系数据库的结构化查询语言。它分为很多种,但大少数都疏松地基于美国国家尺度化构造最新的尺度SQL-92。典型的实行语句是query,它能够收集比力有达标性的记载并返回一个单一的结果集。SQL语言可以修改数据库结构(数据界说语言)和操作数据库内容(数据操作语言)。在这份文档中,我们将特别讨论SQLSERVER所使用的Transact-SQL语言。
当一个打击者能够通过往query中拔出一系列的sql语句来操作数据写入到应用步伐中去,我们管这种要领界说成SQL注入。
一个典型的SQL语句如下:
Select id,forename,surname from authors
这条语句将返回authors表中全部行的id,forename和surname列。这个结果可以被限定,比方:
Select id,forename,surname from authors where forename'john' and surname='smith'
必要偏重指明的是字符串'john'和'smith'被单引号限定。明确的说,forename和surname字段是被用户提供的输入限定的,打击者可以通过输入值来往这个查询中注入一些SQL语句,
如下:
Forename:jo'hn
Surname:smith
查询语句变为:
Select id,forename,surname from authors where forename='jo'hn' and surname='smith'
当数据库试图去实行这个查询时,它将返回如下错误:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near 'hn'
造成这种结果的缘故原由是拔出了.作为定界符的单引号。数据库尝试去实行'hn',但是失败。要是打击者提供特别的输入如:
Forename:jo';drop table authors—
Surname:
结果是authors表被删除,造成这种结果的缘故原由我们稍后再讲。
看上去好象通过从输入中去掉单引号或者通过某些要领避免它们都可以办理这个问题。这是可行的,但是用这种要领做办理要领会存在几个困难。第一,并不是全部用户提供的数据都是字符串。要是用户输入的是通过用户id来查询author,那我们的查询应该像这样:
Select id,forename,surname from authors where id=1234
在这种情况下,一个打击者可以非常简单地在数字的结尾添加SQL语句,在其他版本的SQL语言中,使用种种各样的限定标记;在数据库管理系统JET引擎中,数据可以被使用'#'限定。第二,避免单引号只管看上去可以,但是是没须要的,缘故原由我们稍后再讲。
我们更进一阵势使用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库而且尝试鉴别进入一些假造的应用步伐的权限。
这是一个提交表单页的代码,让用户输入用户名和暗码:
Login
下面是process_login.asp的代码,它是用来控制登陆的:
<%@LANGUAGE = JScript %>
<%
function trace( str ) {
if( Request.form("debug") == "true" )
Response.write( str );
}
function Login( cn ) {
var username;
var password;
username = Request.form("username");
password = Request.form("password");
var rso = Server.CreateObject("ADODB.Recordset");
var sql = "select * from users where username = '" + username + "' and password = '" + password + "'"; trace( "query: " + sql );
rso.open( sql, cn );
if (rso.EOF) {
rso.close();
%>
ACCESS DENIED
<% Response.end return; }
else {
Session("username") = "" + rso("username");
%>
ACCESS GRANTED
Welcome, <% Response.write(rso("Username")); Response.write( "
Welcome, <% Response.write(rso("Username")); Response.write( "