Serverless目錄掃描實(shí)現(xiàn)
? 首先創(chuàng)建一個(gè)云函數(shù),這里以騰訊云舉例。
? 然后選擇自定義創(chuàng)建,運(yùn)行環(huán)境選擇python3.6,函數(shù)名隨意,地域則隨便選一個(gè)即可,會(huì)隨機(jī)分配該地域下的IP作為我們的出口IP地址,配置與云函數(shù)上線CS的方式相同。
云函數(shù)代碼為以下,無論是云函數(shù)還是域前置或者反向代理等手段,本質(zhì)都是流量轉(zhuǎn)發(fā),所以我們?cè)谠坪瘮?shù)上編寫的核心代碼就是實(shí)現(xiàn)了單次掃描返回信息的功能,剩下的控制代碼則由我們本地編寫的代碼執(zhí)行。
# -*- coding: utf8 -*-
import requests
def main_handler(event, context):
headers=event["headers"]
url=event["queryString"]["url"]
path = event["queryString"]["path"]
crake_url=str(url+path)
try:
r = requests.get(crake_url,timeout=5,headers=headers,verify=False)
status = r.status_code
except Exception:
status = None
pass
return status,crake_url
? 配置好云函數(shù)代碼后,繼續(xù)進(jìn)入?觸發(fā)管理?選項(xiàng)。
? 觸發(fā)器配置如圖所示,注意取消勾選集成響應(yīng)。
? 編輯API配置中,將路徑設(shè)置為?/?,然后點(diǎn)擊?立即完成
? 然后得到了兩個(gè)API網(wǎng)關(guān)的公網(wǎng)域名,這時(shí)我們就已經(jīng)完成了基本配置。可以通過這兩個(gè)公網(wǎng)域名實(shí)現(xiàn)對(duì)我們上面編寫的云函數(shù)功能的觸發(fā)實(shí)現(xiàn)。
? 這里進(jìn)一步編寫一個(gè)簡(jiǎn)單的Demo,在本地實(shí)現(xiàn)了一個(gè)目錄掃描的功能,通過對(duì)獲取的公網(wǎng)地址傳參,實(shí)現(xiàn)以云函數(shù)服務(wù)對(duì)指定站點(diǎn)目錄掃描,這里我傳遞了要掃描的url地址以及字典,代碼如下:
? 在我們本地執(zhí)行代碼進(jìn)行掃描,會(huì)得到響應(yīng)給我們并輸出掃描結(jié)果。
? 通過微步情報(bào)可以發(fā)現(xiàn)確為,騰訊云—廣州的IDC服務(wù)器
? 但是大家注意看?Apache access.log日志中?header頭中的User-Agent為python-requests/2.26.0,存在了很明顯的特征,這時(shí)我們繼續(xù)修改本地控制代碼。
? 我們創(chuàng)建一個(gè) get_ua-header.py文件,其中創(chuàng)建了一個(gè)UA數(shù)組,存放了大量不同的User-Agent。
? 這里導(dǎo)入我們剛才創(chuàng)建的UA數(shù)組,然后在第二個(gè)箭頭所指處設(shè)置header的User-Agent每次都隨機(jī)獲取UA數(shù)組中的值,再在發(fā)送請(qǐng)求中指定header,當(dāng)然這里僅為了演示,如果真實(shí)場(chǎng)景下,可以將header頭自定義設(shè)置更多選項(xiàng)讓它看起來更像是一個(gè)合法的請(qǐng)求。
? 這里云函數(shù)中獲取到了我們本地請(qǐng)求API網(wǎng)關(guān)域名的headers然后在轉(zhuǎn)發(fā)時(shí)將它的header替換為我們本地請(qǐng)求包中的header從而實(shí)現(xiàn)了自定義header的效果,修改后的掃描情形如下圖所示:
? 發(fā)現(xiàn)在Apache日志中,User-Agent已經(jīng)為我們本地請(qǐng)求的隨機(jī)信息,那么通過繼續(xù)自定義本地控制代碼中的header信息讓他看起來更加合理,就可以實(shí)現(xiàn)更加隱匿的掃描啦。
? 繼續(xù)我們重復(fù)上面的操作,創(chuàng)建一個(gè)一模一樣的云函數(shù),API網(wǎng)關(guān)也為相同配置,但是需要注意的是選擇的地域要為不同的地方,因?yàn)?單個(gè)用戶在某個(gè)地域只能有5個(gè)隨機(jī)出口IP,也就是說如果這五個(gè)IP均被封禁了那么我們的掃描就無法繼續(xù)進(jìn)行了,但是攻防本身就是對(duì)等的,那么有什么辦法能夠繞過呢?
? 我們?cè)黾恿藘蓚€(gè)一模一樣的云函數(shù)配置,僅為選擇的地域不同,也是為了繞過上面這一限制,修改我們的代碼添加另一個(gè)API網(wǎng)關(guān)域名地址對(duì)字典進(jìn)行分工掃描,兩個(gè)云函數(shù)分別截取字典的部分內(nèi)容進(jìn)行掃描,這里我選擇的地域是廣州和上海,然后開始目錄掃描。
? 現(xiàn)在繼續(xù)查看access.log日志,發(fā)現(xiàn)多出了一些上海的IP地址,是不是更加迷惑了呢?而在目標(biāo)業(yè)務(wù)系統(tǒng)中每天面對(duì)大量的請(qǐng)求使用中,以往的排查溯源思路都是過濾頻繁訪問或者進(jìn)行可疑操作的IP地址,但是對(duì)于這種情況,通常會(huì)被一些正常的請(qǐng)求混雜其中,防守方進(jìn)行日志審計(jì)時(shí)往往就會(huì)認(rèn)為這些是正常的HTTP請(qǐng)求。
? 關(guān)于這里分批掃描的實(shí)現(xiàn)思路在?拓展延伸?會(huì)繼續(xù)深入講解。
Serverless端口掃描實(shí)現(xiàn)
? 然后我們繼續(xù)來實(shí)現(xiàn)端口掃描器的實(shí)現(xiàn),云函數(shù)的配置及API網(wǎng)關(guān)配置這里就不多做贅述了,與上面講到的一樣,這里我們僅關(guān)注云函數(shù)代碼和本地控制代碼的實(shí)現(xiàn)。
? 云函數(shù)代碼如下:
# -*- coding: utf8 -*-
from socket import *
def main_handler(event, context):
IP=event["queryString"]["ip"]
port=event["queryString"]["port"]
try:
conn=socket(AF_INET,SOCK_STREAM)
res=conn.connect_ex((str(IP),int(port)))
conn.send('Hello,World!'.encode("utf8"))
results=conn.recv(25)
if res==0:
conn.close()
return port
except Exception as err:
print(err)
finally:
print("")
conn.close()
return None
? 同樣這里云函數(shù)僅需要實(shí)現(xiàn)簡(jiǎn)單的單次端口掃描,我們的控制代碼如下:
? 可以看到,這里同樣應(yīng)用了上面的講到的分批掃描,如果說上面講到的是通過對(duì)字典中的路徑區(qū)分使用兩個(gè)不同的云函數(shù)API網(wǎng)關(guān)域名,那么這里的端口掃描則為通過端口來區(qū)分。
? 因?yàn)槎丝趻呙钑?huì)慢一些,所以這里我使用了協(xié)程的方式,掃描速度會(huì)更快,使用了grequests模塊。
? 這里執(zhí)行一下本地掃描腳本,成功的得到了目標(biāo)主機(jī)端口的開放情況,但這不是重點(diǎn)。
? 這里使用Hfish來展示態(tài)勢(shì)感知中的端口掃描情況
? 可以看到,對(duì)這些端口掃描的IP均為騰訊云的隨機(jī)IP,是不是無從下手呢?
? 通過Kunyu對(duì)這些IP進(jìn)行批量查詢發(fā)現(xiàn),發(fā)現(xiàn)所在地均為中國上海和成都兩地,也證實(shí)了攻擊IP為我們?cè)坪瘮?shù)的出口IP地址,并且這些數(shù)據(jù)的Time時(shí)間均比較早,而在威脅情報(bào)中看到這些IP為IDC服務(wù)器,也輔助說明了這些IP為已經(jīng)回收目前應(yīng)用于云函數(shù)進(jìn)行請(qǐng)求的云服務(wù)器的IP地址,這里的時(shí)間因素也是我們后續(xù)判斷溯源這種攻擊方式的關(guān)鍵所在。
? 歡迎大家來了解一下Kunyu,是一個(gè)很好用的空間測(cè)繪數(shù)據(jù)分析工具,其中亮點(diǎn)滿滿哦~ 非常適合大家在紅藍(lán)對(duì)抗的工作中進(jìn)行信息收集或者溯源等工作,不同于其他工具的是,Kunyu的設(shè)計(jì)更貼合數(shù)據(jù)分析的工作而不僅僅只是IP導(dǎo)出。
下載地址:https://github.com/knownsec/Kunyu
拓展延伸
上面講到了?單個(gè)用戶在某個(gè)地域只能有5個(gè)隨機(jī)出口IP?那么在更大流量的掃描下,單次如果僅僅只是5個(gè)掃描的IP地址,依舊非常容易被排查出來從而封禁IP。那么為了解決這一問題,我們可以通過分批次的方式進(jìn)行掃描,如果是端口掃描,我們就可以創(chuàng)建多個(gè)云函數(shù)且為不同地域分工掃描不同端口,在態(tài)勢(shì)感知來看就是這n*5個(gè)IP地址在進(jìn)行掃描,也就解決了單個(gè)地域只能有5個(gè)IP的窘境。
? 同樣進(jìn)一步思考,我們也可以在相同的云函數(shù)下創(chuàng)建多個(gè)地域的云函數(shù),再創(chuàng)建其他廠商的云函數(shù),實(shí)現(xiàn)了IP地址的多元化,在這個(gè)基礎(chǔ)上再創(chuàng)建不同地域,理論上可以這樣一直疊加,實(shí)現(xiàn)單兵大流量掃描。
? 對(duì)于大集團(tuán)目標(biāo),通常每天態(tài)勢(shì)感知都會(huì)有很大的掃描流量,那么在這種情況下,如果給我們的云函數(shù)掃描再加上一定程度的隨機(jī)延時(shí)掃描,那么在態(tài)勢(shì)列表中看到的就是一堆不連續(xù)的單次請(qǐng)求,如果是目錄掃描則會(huì)直接認(rèn)為是正常的請(qǐng)求,因?yàn)镮P的隨機(jī)性以及請(qǐng)求包的合法性、不連續(xù)性根本無法聯(lián)想這是一次掃描事件,更不要談溯源的問題了,根本無法還原攻擊鏈,這樣的攻擊只會(huì)比C2隱匿反彈更難纏。
? 整個(gè)實(shí)現(xiàn)過程思維導(dǎo)圖如下:
? 各位小伙伴也可以在我所講的基礎(chǔ)上,更進(jìn)一步將請(qǐng)求包完善的盡量合理化,這樣面對(duì)防火墻等設(shè)備,面對(duì)大量的IP掃描也無法通過IP頻繁請(qǐng)求的方式從而封禁IP,導(dǎo)致封無可封,更別談溯源的問題了。而本地的控制代碼可以幫助我們更好的對(duì)整個(gè)掃描進(jìn)行控制處理,讓整個(gè)掃描更加個(gè)性化,云函數(shù)代碼只進(jìn)行單次流量轉(zhuǎn)發(fā)掃描,而本地代碼則負(fù)責(zé)了通過什么樣的方式掃描的問題。
? 但是面向藍(lán)隊(duì)成員來講也不需要太過恐慌,畢竟有攻就有防,針對(duì)這種掃描,如果找出可疑流量直接封禁IP即可,這種情況下就會(huì)導(dǎo)致紅隊(duì)掃描結(jié)果的不準(zhǔn)確,某個(gè)IP被封禁了,那么他的后續(xù)通過這個(gè)IP的請(qǐng)求都將掃描失敗。
? 再退到紅隊(duì)的角度,面對(duì)上面的應(yīng)對(duì)方式,我們可以通過思維導(dǎo)圖中講到的分工掃描,多個(gè)云函數(shù)交替重復(fù)相同的掃描任務(wù)防止封禁,這樣某個(gè)IP被封禁也不用怕掃描的失效,當(dāng)然一般來講封禁IP也都是掃描結(jié)束后的事情了,通常防守方根本沒那么快的響應(yīng)速度。
? 我一直認(rèn)為攻防對(duì)抗雙方是對(duì)等的立場(chǎng),各自都有自己的優(yōu)勢(shì),而如何利用自身的這種優(yōu)勢(shì)實(shí)現(xiàn)目標(biāo)就是需要思考的問題了,在檢驗(yàn)企業(yè)安全的同時(shí)也在磨練技術(shù)人員的技術(shù)水平,這也是紅藍(lán)對(duì)抗的意義所在。所以大家在思考攻擊或者防守問題時(shí)一定要站在對(duì)立的角度去想,思考對(duì)方的應(yīng)對(duì)手段才能找到問題的突破點(diǎn)。
? 上面提到的代碼均已上傳至Github,感興趣的師傅可以自行下載,也可以自己編寫。
??下載地址:https://github.com/wikiZ/ServerlessScan
轉(zhuǎn)載在安全客:https://www.anquanke.com/post/id/261551