作者:Malayke
本文為作者投稿,Seebug Paper 期待你的分享,凡經采用即有禮品相送! 投稿郵箱:paper@seebug.org

前言

由于工作原因一直都是網絡空間搜索引擎重度用戶,包括Shodan/ZoomEye/Censys/Fofa等平臺都有過使用經驗,甚至自己團隊也嘗試開發過類似平臺。自認為還是非常了解的,在前面看過黑哥寫的幾篇文章后及國外研究者的一些文章后做了一些嘗試,順帶也分享下多年使用搜索引擎的一些搜索套路,希望大家能喜歡,當然這個也是為了迎合下ZoomEye官方寫文章送會員的活動 :)

不說廢話了,步入正題:

1、Cobalt Strike

這個方法最早是在黑哥在medium上發布兩篇文章介紹利用ZoomEye識別在野Cobalt Strike服務器的文章[1][2]介紹的,因為文章是英文寫的發布在medium上國內直接訪問不到,所以這里再次簡單介紹一下。在此之前我們需要提一下Fox-it的工作,是他們最早開始通過網絡空間測繪技術去識別追蹤在野Cobalt Strike的工作并在他們的blog上發布了對應的研究成果[3],Cobalt Strike提供的Web服務是基于NanoHTTPD開源框架開發的,而當時Fox-it工程師發現NanoHTTPD返回banner里存在一個異常的空格“bug”,然后通過這個異常的空格去識別。隨后Cobalt Strike官方在發布的3.13版本了對這個“bug”做了更新處理。

事實上我們不需要這個利用這個所謂的異常的空格“bug”,根據觀察Cobalt Strike的WEB服務返回http頭存在比較明顯的特征,由此來識別追蹤Cobalt Strike。

首先我們看看Cobalt Strike版本小于3.13的,返回banner信息(直接復制的黑哥文章里的內容)

? curl http://x.x.x.x:8081/ -v

- Rebuilt URL to: [http://x.x.x.x:8081/](http://x.x.x.x:8081/)
- Trying x.x.x.x…
- TCP_NODELAY set
- Connected to x.x.x.x (x.x.x.x) port 8081 (#0)

> GET / HTTP/1.1
Host: x.x.x.x:8081
User-Agent: curl/7.54.0
Accept: /

< HTTP/1.1 404 Not Found
< Content-Type: text/plain
< Date: Wed, 27 Feb 2019 14:43:19 GMT
< Content-Length: 0
<

通過curl直接請求Cobalt Strike的WEB服務器端口主頁內容返回http頭非常簡單并且特征化,直接提取兩個關鍵字符串"HTTP/1.1 404 Not Found Content-Type: text/plain Date:""Content-Length: 0" (注:這里需要說明下ZoomEye在匹配處理是忽視回車換行的,不提取Date的部分是因為這個這個時間是變化的),這里我們通過+進行“且”運算(注:這里順帶說明下ZoomEye支持的邏輯運算:空格 為or運算符 表示邏輯“或”運算,+ 為and運算符 表示邏輯“且”運算,- 為 not運算符 表示邏輯“非”運算)

搜索語法如下:

"HTTP/1.1 404 Not Found Content-Type: text/plain Date:" +"Content-Length: 0"

通過采樣觀察,這個搜索語法得到的結果有不少誤報:比如Cobalt Strike的返回頭信息里是沒有"Server:"頭的,也沒有"Connection:"等頭,這里我們可以通過-運算(not運算)進行排除,通過嘗試我們發現"Server"這個關鍵詞在于ssl等信息里直接運算可能導致漏報,所以我們這里直接使用"Connection:"的not運算,最終搜索語法如下:

"HTTP/1.1 404 Not Found Content-Type: text/plain Date:" +"Content-Length: 0" -"Connection:"

上面我們提到Cobalt Strike在3.13版本的時候修復了“異常空格bug”的同時也修改了默認返回的http頭:(直接復制的黑哥文章里的內容)

? curl http://x.x.x.x:8001/ -v

- Rebuilt URL to: http://x.x.x.x:8001/
- Trying x.x.x.x…
- TCP_NODELAY set
- Connected to x.x.x.x port 8001 (#0)

> GET / HTTP/1.1
Host: x.x.x.x:8001
User-Agent: curl/7.54.0
Accept: /

< HTTP/1.1 404 Not Found
< Date: Thu, 26 Mar 2020 13:19:16 GMT
< Content-Type: text/plain
< Content-Length: 0
<

可以看到返回的http有內容順序進行變動:Date:頭提前了,所以之前的搜索語法是沒辦法直接工作了,那么我們按上面提到套路稍微改變下試一下,因為ZoomEye匹配模式不會去考慮回車換行的問題,我們把banner整理為一行:

HTTP/1.1 404 Not Found Date: Fri, 10 Apr 2020 07:16:27 GMT Content-Type: text/plain Content-Length: 0

因為時間是變化的所以分割一下:

HTTP/1.1 404 Not Found Date:
Fri, 10 Apr 2020 07:16:27
GMT Content-Type: text/plain Content-Length: 0

我們直接取1 +3搜索,并繼續使用 -"Connection:"繼續排除,得到最終搜索語法:

"HTTP/1.1 404 Not Found Date:" +"GMT Content-Type: text/plain Content-Length: 0" -"Connection:"

大家如果有興趣可以去推特等上找一些開源情報信息驗證一下。

這里需要說明下這個主要是根據NanoHTTPD的返回頭進行識別的尤其是針對Cobalt Strike 3.13之前的版本,所以有可能其他的設備也使用NanoHTTPD這個組件也會被識別出來形成誤報,另外在黑哥發布方法后有很多的Cobalt Strike使用團隊開始修改了配置進行偽裝,這個也是我這里需要提醒紅隊注意在使用Cobalt Strike的時候只是修改了證書啥的配置,那是遠遠不夠的。

2、Meterpreter

Metasploit 的 Meterpreter 其實常用的方式有tcp也有http(s)的模式,在ZoomEye上有現成Metasploit相關的規則(提示:在搜索框里輸入Metasploit及可關聯出所有的Metasploit相關的app):

app:"Metasploit Rex httpd" app:"Metasploit meterpreter metsvc" app:"Metasploit meterpreter" app:"Metasploit browser_autopwn"

這幾個規則大多是基于tcp的方式的,并不是這次主要目標。也就是http(s)的方式是我們今天的目標,在2019年的一篇文章里有國外的研究員提到了一個方法,這個方法有點類似Cobalt Strike上面的方法[4],都是從http(s)服務返回特征入手,這里我們看一下msf的相關代碼 lib/msf/core/handler/reverse_http.rb#L82 [5]

    OptString.new('HttpUnknownRequestResponse',
      'The returned HTML response body when the handler receives a request that is not from a payload',
      default: '<html><body><h1>It works!</h1></body></html>'
    ),

返回特征也很明顯,于是嘗試搜索:"<html><body><h1>It works!</h1></body></html>"

https://www.zoomeye.org/searchResult?q=%22%3Chtml%3E%3Cbody%3E%3Ch1%3EIt%20works!%3C/h1%3E%3C/body%3E%3C/html%3E%22

很明顯這個結果誤報太多,我猜MSF開發人員當時就是想模仿Apache的默認返回內容,所以我們還得回到Cobalt Strike套路上,看看Metasploit Meterpreter http(s)上線模式WEB服務的返回頭的信息:

- Trying 0.0.0.0:1337...
- TCP_NODELAY set
- Connected to 0.0.0.0 port 1337 (#0)

> GET / HTTP/1.1
Host: 0.0.0.0:1337
User-Agent: curl/7.68.0
Accept: /

- Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Connection: close
Connection: close
< Server: Apache
Server: Apache
< Content-Length: 44
Content-Length: 44

<

- Closing connection 0
<html><body><h1>It works!</h1></body></html>

在上面提到的國外研究員那篇文章[5]里提了一個特征:真正的Apache的默認返回頁面的內容有一個額外的\n,而MSF的沒有,于是通過Censys提供的body hash規則進行匹配搜索[6],隨機追蹤了幾個目標很顯然這個方法存在很嚴重的誤報。所以我們這里只能回歸到ZoomEye的老套路上了,觀察Metasploit Meterpreter http(s)模式的WEB服務返回banner:

HTTP/1.1 200 OK
Connection: close
Server: Apache
Content-Length: 44

<html><body><h1>It works!</h1></body></html>

因為這些沒有存在變化的元素,那就直接復制上面的字符段開搜:

"HTTP/1.1 200 OK Connection: close Server: Apache Content-Length: 44 <html><body><h1>It works!</h1></body></html>"

當然因為這個Content-Length: 44 已經很唯一了,所以其實我們在簡潔一下去掉后面的html內容,最終搜索語法如下:

"HTTP/1.1 200 OK Connection: close Server: Apache Content-Length: 44"

3、Empire

相比Cobalt Strike及Metasploit,可能Empire知名度稍微差那么一點點,不過目前也是有不少人在使用,在這里我需要說明一下我之前是沒有用過這個東西的所以就不多做其他評價了,本文主要是介紹怎么通過ZoomEye去搜索這些框架,我這里不想現成單獨去安裝一個去獲取指紋,那還有其他套路可以走?

這里我介紹一個很常用的套路:“從其他搜索引擎語法到ZoomEye搜索語法”。再此之前我留意到一個著名FireEye公司的研究者的的一個PPT[7](這里需要說明下的是這個PPT的主題和本文其實一樣的,本文的下面的一些研究的包括Empire等框架目標也是參考了這個PPT)另外順帶說一下題外八卦:

這個PPT里的主題和本文其實是一個主題,之前黑哥也在他的知識星球“黑科技”里吐槽過,大意是說他這個PPT里使用的套路尤其是Cobalt Strike那部分是有參考了本文開始提到黑哥的那些研究內容的,而且全篇直接忽視了來自中國的ZoomEye,看來川普同學覆蓋面還是很廣的!

回歸正題,在這個ppt里提到了一個Empire的shodan搜索語法:

http.html_hash:"611100469"

這里利用的背后的原理也類似上面Metasploit Meterpreter提到的問題,這里Empire是想偽裝成為IIS服務器,但是因為使用空格、tab的區別導致跟真正的IIS頁面不一致導致的,所以國外的研究人員都喜歡從比對這個角度去想辦法。那么我們怎么從Shodan這個語法轉化為ZoomEye的搜索語法呢?首先我們通過Shodan搜索結果找到如下banner:

HTTP/1.0 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 682
Cache-Control: no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: 0
Server: Microsoft-IIS/7.5
Date: Wed, 19 Aug 2020 08:33:52 GMT

細心的人可以發現:真假IIS頁面的主要區別在html里空格與tab的區別,那為什么你只關注http頭呢?其實這個問題上面的例子就用過了那就是 "Content-Length: 682 ",頁面內容長度變化都體現在http頭Content-Length上,對于正常的IIS7的返回Content-Length 我們可以通過ZoomEye搜索:

<title>IIS7</title> [https://www.zoomeye.org/searchResult?q=<title>IIS7</title>](https://www.zoomeye.org/searchResult?q=%3Ctitle%3EIIS7%3C/title%3E)

正常的為"Content-Length: 689", 而且Empire的返回頭的內容及順序是相對固定的,IIS7本身很多設置相關而有變化,所以我們繼續老套路提取http頭特征:

"HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 682 Cache-Control: no-cache, no-store, must-revalidate Pragma: no-cache Expires: 0"

4、SpiderLabs Responder

這個目標同樣來自于FireEye公司的研究者的PPT,關于SpiderLabs Responder的介紹可以自行搜索或者訪問項目主頁:https://github.com/SpiderLabs/Responder 這個框架字紋是由于http頭里直接硬編碼了Date:頭[8]

class IIS_Basic_401_Ans(Packet):
fields = OrderedDict([
("Code", "HTTP/1.1 401 Unauthorized\r\n"),
("ServerType", "Server: Microsoft-IIS/6.0\r\n"),
("Date", "Date: Wed, 12 Sep 2012 13:06:55 GMT\r\n"),
("Type", "Content-Type: text/html\r\n"),
("WWW-Auth", "WWW-Authenticate: Basic realm=\"Authentication Required\"\r\n"),
("PoweredBy", "X-Powered-By: [ASP.NET](http://asp.net/)\r\n"),
("AllowOrigin", "Access-Control-Allow-Origin: *\r\n"),
("AllowCreds", "Access-Control-Allow-Credentials: true\r\n"),
("Len", "Content-Length: 0\r\n"),
("CRLF", "\r\n"),
])

從上面的案例或者正常情況來看Date是變化的,可以直接搜索:

"Date: Wed, 12 Sep 2012 13:06:55 GMT"

這里需要注意的是在FireEye那個PPT里強調了"HTTP/1.1 401 Unauthorized",不過在我看來這個是沒有必要的,在我看來這個Date:硬編碼能撞上的幾率那是非常小的,SpiderLabs Responde是個開源項目,很可能有其他變種或者參考代碼的項目,于是我在github上搜索了下確實找到不少: 大部分屬于代理中間人框架。

5、PoshC2

PoshC2 是基于powershell開發的C2代理框架,介紹詳見:https://github.com/nettitude/PoshC2 我們這里從另外一個使用網絡空間搜索引擎的常用套路:“證書搜索”,在github項目主頁搜索Certificate 后找到 https://github.com/nettitude/PoshC2/blob/9d76be26e4c606c3630d0a54fb0d36566e696526/poshc2/server/Config.py 代碼:

Certificate Options

Cert_C = "US"
Cert_ST = "Minnesota"
Cert_L = "Minnetonka"
Cert_O = "Pajfds"
Cert_OU = "Jethpro"
Cert_CN = "P18055077"
Cert_SerialNumber = 1000
Cert_NotBefore = 0
Cert_NotAfter = (10 * 365 * 24 * 60 * 60)

看到"P18055077"這個很特別,直接使用ZoomEye證書搜索語法:

ssl:"P18055077"

這里順帶提一句:證書搜索很可能出現覆蓋不全的情況,這個例子里本身搜索出來的結果不太多所以不是很明顯,所以遇到其他的例子可以先通過證書搜索的到返回的banner后,再根據提取banner特征去搜索匹配。

總結

1、主動掃描探測及網絡空間搜索引擎可以協助我們追蹤識別各種攻擊者痕跡,也非常認同黑哥提出來的“動態測繪”的觀點,通過動態測繪關聯各種數據可以更加完善攻擊者畫像,比如上文里介紹的幾個框架都是歷史上多個APT組織使用過的框架。目前從火眼等多個公司的文章來看,有更多的安全關注到主動掃描及網絡空間搜索引擎在APT追蹤領域的應用。

2、對于紅隊來說應該注意到C2服務器的安全,尤其這些滲透攻擊框架的默認配置需要做修改,以免被主動掃描追蹤。

3、對于藍隊來說網絡空間搜索引擎也是威脅情報的來源之一,我們能提前獲取某些C2 IP并監控拉黑,或許有意想不到的發現。

參考

[1] Identifying Cobalt Strike team servers in the wild by using ZoomEye

[2] Identifying Cobalt Strike team servers in the wild by using ZoomEye(Part 2)

[3] Identifying Cobalt Strike team servers in the wild

[4] Analysing meterpreter payload with Ghidra

[5] https://github.com/rapid7/metasploit-framework/blob/76954957c740525cff2db5a60bcf936b4ee06c42/lib/msf/core/handler/reverse_http.rb#L82

[6] https://censys.io/ipv4?q=8f3ff2e2482468f3b9315a433b383f0cc0f9eb525889a34d4703b7681330a3fb

[7] https://github.com/aaronst/talks/blob/master/scanttouchthis.pdf

[8] https://github.com/SpiderLabs/Responder/blob/master/packets.py


Paper 本文由 Seebug Paper 發布,如需轉載請注明來源。本文地址:http://www.bjnorthway.com/1301/