拒絕做工具小子—編寫Python漏洞驗證指令碼

前言

我們實戰經常會遇到以下幾個問題:

1、遇到一個利用步驟十分繁瑣的漏洞,中間錯一步就無法利用

​ 2、挖到一個通用漏洞,想要批次刷洞小賺一波,但手動去測試每個網站工作量太大

這個時候編寫一個poc指令碼將會將會減輕我們很多工作。本文將以編寫一個高效通用的poc指令碼為目的,學習一些必要的python知識,這周也是拒絕做工具小子努力學習的一週

requests模組使用技巧

Requests是Python中一個常用的HTTP請求庫,使用Requests庫來發起網路請求非常簡單,具體的使用方法這裡就不多介紹了,這裡只提幾個Requests模組的使用技巧,請收好

取消重定向

Requests 會自動處理所有重定向,但有時我們並不需要重定向,可以透過

allow_redirects

引數禁用重定向處理:

r = requests。get(‘http://github。com’, allow_redirects=False)

SSL 證書驗證

Requests在請求https網站預設會驗證SSL證書,可有些網站並沒有證書,可增加

verify=False

引數忽略證書驗證,但此時可能會遇到煩人的

InsecureRequestWarning

警告訊息。最終能沒有警告訊息也能訪問無證書的https網站的方法如下:

import requestsfrom requests。packages。urllib3。exceptions import InsecureRequestWarningrequests。packages。urllib3。disable_warnings(InsecureRequestWarning)requests。get(‘https://github。com’, verify=False)

代理

使用代理的目的就不說了,使用方法如下:

# http代理,需要指定訪問的http協議和https協議兩種proxies = { “http”: “http://127。0。0。1:8080”, “https”: “http://127。0。0。1:1080”,}# socks5代理proxies = { ‘http’: ‘socks5://user:pass@host:port’, ‘https’: ‘socks5://user:pass@host:port’}requests。get(“http://example。org”, proxies=proxies)

有個使用技巧就是代理到burp中,檢查一下python發包。如我本地抓到requests請求包如下,可以發現特徵十分明顯,所以我們在實戰使用時儘量修改User-Agent

拒絕做工具小子—編寫Python漏洞驗證指令碼

保持cookie

使用session會話物件,向同一主機發送多個請求,底層的 TCP 連線將會被重用,不僅能提效能還能保持cookie

s = requests。Session()s。get(‘http://httpbin。org/cookies/set/sessioncookie/123456789’)r = s。get(“http://httpbin。org/cookies”)

在編寫poc指令碼時我們只需要利用Requests模組傳送帶有payload的資料即可,配合上這裡的小技巧可能會有更好的體驗

驗證結果

傳送帶有payload的請求後,我們需要透過分析響應包判斷是否存在漏洞。往往存在漏洞的響應包都有一些特殊值,我們只需要在響應包中找到這樣的特殊值即可證明存在漏洞,所以這裡我們通常有兩種寫法

成員運算子 - in

if ‘xxx’ in r。text: print(‘存在漏洞’)else: print(‘不存在漏洞’)

正則匹配 - re.search()

if re。search(‘xxx’,r。text): print(‘存在漏洞’)else: print(‘不存在漏洞’)

這兩種寫法差不多,不過re。search()有個好處是可以使用正則表示式,在漏洞特徵是動態變化的情況時也能有效的捕捉

單執行緒poc指令碼

此時我們已經能寫一個單執行緒poc指令碼了,我對單執行緒的poc指令碼的要求十分簡單,就是簡單,在面對不同的漏洞時簡單修改幾行程式碼就可以了。這裡提供一個我自己寫的單執行緒poc指令碼,大概意思就是這樣

import requestsimport refrom requests。packages。urllib3。exceptions import InsecureRequestWarningrequests。packages。urllib3。disable_warnings(InsecureRequestWarning)def Poc(url): proxy = { ‘http’:‘http://127。0。0。1:8080’, ‘https’:‘http://127。0。0。1:8080’ } headers = { ‘User-Agent’:‘Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/92。0。4515。107 Safari/537。36’, ‘Connection’:‘close’ } data = {‘name’:‘xxxx’,‘value’:‘xxxx’} try: response = requests。post(url=url,headers=headers,data=data,verify=False,proxies=proxy,timeout=10) if ‘baidu’ in response。text: print(‘存在漏洞’) else: print(‘none’) except Exception as e: print(f‘請求失敗:{e}’)if __name__ == ‘__main__’: url = ‘https://www。baidu。com’ Poc(url)

使用多執行緒

當我們想批次驗證數個網站是否存在漏洞時,就需要多執行緒來提升效率了。關於Python多執行緒的詳細知識這裡就不是這裡的重點了。這裡我們將利用Threading和queue做一個多執行緒poc指令碼,我計劃的流程如下

把所有目標url放到queue佇列中;

啟動多執行緒從queue佇列中獲取目標並執行;

儲存執行結果。

具體程式碼最後會給出

顏色標記

我在使用多執行緒時就遇到一個問題,因為多執行緒處理的資料比較多,終端瞬間會輸出大量資訊,很容易就會忽略一些關鍵的資訊

拒絕做工具小子—編寫Python漏洞驗證指令碼

然後我就想用顏色來區分不同的資訊,在linux終端中使用

\033[顯示方式;前景色;背景色m

的格式就能輸出各個顏色的字型。這裡推薦python第三方庫:colorama

colorama是一個可以跨多終端顯示不同顏色字元與背景的第三方庫,在linux終端上,使用ANSI跳脫字元來實現彩色字型的輸出。在windows的終端上,透過包裝stdout實現。在windows和linux上有不同的實現方案,從而達到跨平臺的效果

安裝第三方庫的命令各位應該都會吧

pip install colorama

具體使用參考官方文件:https://pypi。org/project/colorama/

我的使用習慣就是報錯資訊的字型使用紅色,發現漏洞的字型使用綠色,此時部分程式碼如下:

from colorama import init,Foreinit(autoreset=True)print(Fore。GREEN + ‘[+]存在漏洞’)print(Fore。RED + ‘[!]連線錯誤’)

使用顏色後的終端輸出如下,現在使用體驗上明顯會更好一點,大家也可以根據自己的喜好去設定

拒絕做工具小子—編寫Python漏洞驗證指令碼

新增進度條

我們使用多執行緒的目的就是為了更快的處理更多的url,但目標過多,我們還是免不了更長時間的等待。我們經常會把指令碼掛在那裡跑,然後呆呆的等著。然後我就想做一個進度條,根據進度條能大概的去預估時間,然後安排自己的工作,提升工作效率,這不就是使用指令碼的意義嗎

我首先就找到了很多人推薦的第三方庫:

tqdm

,在多執行緒中使用時可以使用手動更新進度

import timefrom tqdm import tqdmwith tqdm(total=200) as pbar: pbar。set_description(‘Processing:’) for i in range(20): time。sleep(0。1) pbar。update(10)

但我這裡就遇到一個問題,很多人使用tqdm時只輸出一個Progress bar任務條,但我們的需求是希望同時輸出每次漏洞探測結果和任務條,這會導致這兩者在終端中顯示的混亂,如下圖所示

拒絕做工具小子—編寫Python漏洞驗證指令碼

有沒有一種辦法能讓任務條一直固定輸出在終端的末尾呢,這樣兩個資訊都能很清晰的顯示

我找了好久解決方法,但官方似乎說沒有找到在多個平臺上平等使用tqdm的方法,就沒有這個功能。不過我最終找到官方提供了一個tqdm。write()方法,似乎能解決這個問題,只需要把指令碼中所有print()方法換成tqdm。write()方法

拒絕做工具小子—編寫Python漏洞驗證指令碼

到這裡我們就成功的擁有了一個進度條

【一>所有資源關注我,私信回覆“資料”獲取<一】

1、網路安全學習路線

2、電子書籍(白帽子)

3、安全大廠內部影片

4、100份src文件

5、常見安全面試題

6、ctf大賽經典題目解析

7、全套工具包

8、應急響應筆記

多執行緒poc指令碼

我最終寫好的多執行緒poc指令碼如下,中間還有很多可以最佳化的地方,希望能得到大家的指點

import requestsfrom requests。packages。urllib3。exceptions import InsecureRequestWarningimport threadingimport queuefrom colorama import init,Forefrom tqdm import tqdminit(autoreset=True)requests。packages。urllib3。disable_warnings(InsecureRequestWarning)global_file_target_url = ‘url。txt’global_file_result = ‘right。txt’global_threads_num = 12global_q = queue。Queue()global_list_result = []# 目標uriglobal_where = ‘’# payload 成功時頁面標誌資訊global_payload = ‘test’global_request_proxy = { ‘http’:‘socks5://127。0。0。1:8080’, ‘https’:‘socks5://127。0。0。1:8080’}global_request_headers = { ‘User-Agent’:‘Mozilla/5。0 (Windows NT 10。0; Win64; x64) AppleWebKit/537。36 (KHTML, like Gecko) Chrome/92。0。4515。107 Safari/537。36’, ‘cookie’:‘xxxxxxxxxxxxxx’, ‘Connection’:‘close’ #關閉多餘的連線請求}global_request_data = {‘name’:‘xxxx’,‘value’:‘xxxx’} #POST傳遞的資料global_error = 0def req(url): global global_error i = 0 while i<3: if i>0: #print(f‘[!]第{i}次重試請求{url}’) tqdm。write(f‘[!]第{i}次重試請求{url}’) try: response = requests。get(url=url,headers=global_request_headers,verify=False,timeout=10) response。encoding = response。apparent_encoding text = response。text if global_payload in text: return True else: return False except Exception as e: if i==0: global_error +=1 i = i+1 #print(Fore。RED+f‘[!]{url}請求失敗’) tqdm。write(Fore。RED+f‘[!]{url}請求失敗’)def poc(pbar): while not global_q。empty(): target_url = global_q。get() url = target_url+global_where if req(url): #print(Fore。GREEN+‘[+]存在漏洞:’+target_url) tqdm。write(Fore。GREEN+‘[+]存在漏洞:’+target_url) global_list_result。append(target_url) else: #print(‘[-]未發現漏洞’) tqdm。write(‘[-]未發現漏洞’) pbar。update(1)def main(): # 1、新增目標url佇列 with open(global_file_target_url,‘r’) as f: urls = f。readlines() for url in urls: url = url。strip() global_q。put(url) num_url = global_q。qsize() pbar = tqdm(total=num_url) pbar。set_description(‘Processing:’) tqdm。write(‘url總數:’+str(num_url)) # 2、啟動多執行緒poc驗證 threads = [] for _ in range(global_threads_num): t = threading。Thread(target=poc,args=(pbar,)) threads。append(t) t。start() for t in threads: t。join() # 3、儲存結果到檔案 global_file_result if global_list_result: file = open(global_file_result,‘w’) for res in global_list_result: file。write(res+“\n”) file。close() tqdm。write(f‘失敗請求數{global_error}’)if __name__ == ‘__main__’: main()

參考:

https://mp。weixin。qq。com/s/aWbPUANyglL5kWiiFfSRYw

https://mp。weixin。qq。com/s/Dwec68-ROfiqWeRUY4wEpg~~~~