鉴于读者可能对SQL注入漏洞缺少概念,所以,我们会将SQL注入漏洞与XSS漏洞对比着来讲解。
首先,我们来认识一下与SQL注入漏洞有关的Web浏览器的相关工作原理,然后,我们会解释几个名词,以此说明何谓“SQL注入漏洞”。
Web浏览器的工作原理本身是很复杂的,剔除其他无关因素,即可化简为下图:
SQL注入攻击是通过操作输入来修改SQL语句,用以达到执行代码对WEB服务器进行攻击的方法。简单的说就是在post/get Web表单、输入域名或页面请求的查询字符串中插入SQL命令,最终使Web服务器执行恶意命令的过程。
❝
数据库:是一个按数据结构来存储和管理数据的计算机软件系统。数据库的概念实际包括两层意思:
数据库是一个实体,它是能够合理保管数据的“仓库”,用户在该“仓库”中存放要管理的事务数据,“数据”和“库”两个概念结合成为数据库。
数据库是数据管理的新方法和技术,它能更合适的组织数据、更方便的维护数据、更严密的控制数据和更有效的利用数据。
❞
❝
SQL:结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。
❞
❝
注入式攻击:是通过传递一些带有特定的字符的参数来改变执行的SQL语句,从而达到破坏的效果。
❞
总结以上的三个概念,我们可以粗略地总结SQL注入漏洞:由SQL编写的数据库所连接的网站存在可以被进行注入式攻击的漏洞
。
然后,我们再来看一看这个漏洞是如何产生的:
❝
这种漏洞是因为在项目中没有将代码与数据(比如用户敏感数据)隔离,在读取数据的时候,错误的将数据作为代码的一部分执行而导致的。
❞
任何一个基于SQL语言的数据库都可能被攻击,很多开发人员在编写Web应用程序时未对从输入参数、Web表单、Cookie等接受到的值进行规范性验证和检测,通常会出现SQL注入漏洞。
读到这里,你可能敏锐地觉察到,这个漏洞与XSS有一点像——都是将用户输入的数据当做代码执行了。对于SQL注入与XSS的异同点,我们不急于现在就讨论,等到我们对SQL注入有一定的认识之后,再来讨论这个不迟。
❝
所谓注入点就是可以实行注入的地方,通常是一个缺乏完善的防御机制数据库与页面的交互点。根据注入点数据库的运行帐号的权限的不同,你所得到的权限也不同。
❞
注入点的概念乍一看挺抽象的,我们可以类比XSS来思考——注入点类似于XSS里的表单!简单来说,就是我们可以进行攻击的地方。
接下来,我们要尝试思考另外一个问题——如何确定是否存在注入点?
判断某个链接是否存在SQL注入,可以通过对其传入的可控参数进行简单的构造,通过服务端返回的内容来判断有无注入。
比如,对于上一篇中我们所测试的网站:http://www.dalingfood.com/news.php?nid=142
,当我们把网站最后面的?nid=142
改成?nid='
时,会显示如下界面:
出现这种情况,就是因为我们所输入的'
被错误地当做代码的一部分执行了,所以,我们可以认为,此处大概率有注入点。
当然,这只是一个小的演示,详细的检测语句与判断方法如下:
数字类型
构造测试 | 预期结果 | 变种 |
' |
//触发错误,返回数据库错误 | |
1+1 | //返回原来相同的结果 | 3-1 |
1+0 | //返回原来相同的结果 | |
1 or 1=1 | //永真条件,返回所有记录 | 1) or (1=1 |
1 or 1=2 | //空条件,返回原来相同的结果 | 1) or (1=2 |
1 and 1=2 | //永假条件,不返回记录 | 1) and (1=21234567 |
其他类型
构造测试 | 预期结果 | 变种 |
a ' | //触发错误,返回数据库错误 | |
a ' or '1' ='1 | //永真条件,返回所有记录 | a') or ('1'=1 |
a' or '1' ='2 | //空条件,返回原来相同结果 | a') or ('1'=2 |
a' and '1' ='2 | //永假条件,不返回记录 | a') and ('1'='212345 |
服务端返回错误形式
-
错误直接回显在页面上 -
错误隐藏在页面源代码中 -
检测到错误跳转到另一个页面 -
返回HTTP错误代码500或重定向302 -
适当处理错误结果,常显示一个通用错误页面
-
如果参数(
id
)是数字,测试id=2-1
与id=1
返回的结果是否相同,如果做了2-1=1
的运算,说明可能存在数字型注入。如果要用+
号运算的话,因为URL
编码的问题,需要把加好换成%2B
,如id=1%2B1
-
在参数后面加单引号或双引号,判断返回结果是否有报错
-
添加注释符,判断前后是否有报错,如
id=1' --+
或id=1" --+
或id=1' #
或id=1" --+
(--
后面跟+
号,是把+
当成空格使用) -
有些参数可能在括号里面,如:
SELECT first_name, last_name FROM users WHERE user_id = ('$id');
所以也可以在参数后面加单、双引号和括号,如id=1') --+
或id=1") --+
或id=1') #
或id=1") --+
-
参数后面跟
or
或者and
,判断返回结果是否有变化,如1' or 'a'='a
或者and 'a'='a
或者1' or 'a'='b
或者1' or '1'='2
如果返回的正确页面与错误页面都一样,可以考虑时间延迟的方法判断是否存在注入,如1' and sleep(5)
在刚刚讲注入点的时候,你可能就注意到,sql注入漏洞与XSS在网页中找表单不同。比如,基于get方式的SQL注入漏洞多数情况下是利用改变URL的参数部分、通过观察返回的页面来确认注入点的。所以,了解URL就显得非常有必要了。就以下面这个URL为例,介绍下普通URL的各部分组成
http://www.aspxfans.com:8080/news/index.asp?boardID=5&ID=24618&page=1#name
❝
从上面的URL可以看出,一个完整的URL包括以下几部分:
1.协议部分:该URL的协议部分为“http:”,这代表网页使用的是HTTP协议。在Internet中可以使用多种协议,如HTTP,FTP等等本例中使用的是HTTP协议。在"HTTP"后面的“//”为分隔符
2.域名部分:该URL的域名部分为“www.aspxfans.com”。一个URL中,也可以使用IP地址作为域名使用
3.端口部分:跟在域名后面的是端口,域名和端口之间使用“:”作为分隔符。端口不是一个URL必须的部分,如果省略端口部分,将采用默认端口
4.虚拟目录部分:从域名后的第一个“/”开始到最后一个“/”为止,是虚拟目录部分。虚拟目录也不是一个URL必须的部分。本例中的虚拟目录是“/news/”
5.文件名部分:从域名后的最后一个“/”开始到“?”为止,是文件名部分,如果没有“?”,则是从域名后的最后一个“/”开始到“#”为止,是文件部分,如果没有“?”和“#”,那么从域名后的最后一个“/”开始到结束,都是文件名部分。本例中的文件名是“index.asp”。文件名部分也不是一个URL必须的部分,如果省略该部分,则使用默认的文件名
6.锚部分:从“#”开始到最后,都是锚部分。本例中的锚部分是“name”。锚部分也不是一个URL必须的部分
7.参数部分:从“?”开始到“#”为止之间的部分为参数部分,又称搜索部分、查询部分。本例中的参数部分为“boardID=5&ID=24618&page=1”。参数可以允许有多个参数,参数与参数之间用“&”作为分隔符
❞
所以,我们测试是否存在注入点,主要是从最后的参数部分下手。
2.1 按照执行效果来分类
2.1.1 盲注入
盲注入不会展现任何数据库报错内容,它是依据构造真或假的问题对数据库进行“提问”,注入方式主要有两种:基于布尔值与基于时间。
2.2.1.1 基于布尔值的盲注
如在MySQL中判断数据名长度的输入为1' and length(database()) = 10 #,通过相应的正确与否判断数据名的长度是否为10,猜测数据库中数据的具体内容时,可以借助书本上SUBSTR、LIMIT、ASCII等一些特殊的命令及函数进行猜测;
2.1.1.2 基于时间的盲注
基于时间的SQL盲注入方式通常是在SQL语句中添加延时函数,依据相应时间来判断是否存在SQL注入,常用的延时函数或指令有sleep、repeat等。
总结:盲注入提交SQL命令较多,通常通过手工方式无法完成,借用工具如SQLMAP。
2.1.2 基于报错的注入
常用函数:
-
updatexml(1,concat('~',SQL语句,'~'),1)
-
extractvalue(1,concat('~',(SQL语句)))
2.1.3 联合查询注入
联合查询是可合并多个相似的选择查询的结果集。等同于将一个表追加到另一个表,从而实现将两个表的查询组合在一起,使用为此为UNINO或UNION ALL 联合查询:将多个查询的结果合并到一起(纵向合并):字段数不变,多个查询的记录数合并
2.1.4 堆叠注入
堆叠注入是一堆sql语句(多条)一起执行。我们知道在mysql中,主要是命令行中,每一条语句结尾加;
, 由于搜索引擎的不同,Orcle不支持堆叠查询.
2.2 按数据类型分
2.1 数字类型
后台语句可能为:
$id=$_POST['id']select user,password from users where id=$id12
2.2 字符类型
$id=$_POST['id']后台语句可能为:select user,password from users where id='$id'12
总结:
-
数字类型直接将后台接收到用户输入的内容带入到数据库中执行;而字符型将接收到的内容添加到引号内然后进行执行。 -
字符型注入需要考虑语句的闭合问题,而数字类型则不存在
2.3 按注入位置分
GET方式注入:注入参数以GET方式进行提交
POST方式注入:注入参数以POST方式进行提交
基于cookie的注入:后台接收cookie内的参数,在http的cookie字段中存在注入漏洞
基于http头部的注入:后台会接收referer或user-agent字段中的参数,http头部中的referer、user-agent字段中存在注入漏洞
下一次我们将会再次进行sql注入的实战,请大家好好学习理论知识,打好基础,这将是实战成功的重要保障。
·END·
▼
谨记责任,高歌向前
▼
微信公众号:蝰蛇安全实验室
文案 | Crispitol
排版 | tqllqt_1
审核 | Crispitol
指导老师 | Hard Target
本文始发于微信公众号(蝰蛇安全实验室):萌新向 | SQL实战前
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论