當前位置:
首頁 > 新聞 > Sublist3r子域名枚舉神器源碼閱讀

Sublist3r子域名枚舉神器源碼閱讀

*本文作者:mscb,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。



前言


Sublist3r是一款簡單易用的子域名枚舉利器。但是今天我不打算講解它的使用教程,而是深入一層,從它的代碼中窺探原理。也許有人可能很不理解,為什麼不好好的使用工具而偏偏去深究它的代碼實現細節。


從我個人角度來說,我覺得:


第一個層面,一位優秀的安全從業者,至少在讀/寫代碼層面不能成為短柄。如果一味的只使用工具,不了解原理,那很容易成為大家口中的「腳本小子(script kiddie)」。


第二個層面,這是我個人推崇的的學習方法,從自己的學習道路中,我喜歡遵循3個W的學習原則,即(What->Why->What):



第一個What表示在初學階段,需要學會

哪些東西

幹些什麼

,比如知道了Sublist3r工具可以用來枚舉子域名。


第二個Why則表示在中級階段,去了解這個東西的實現原理,以及為什麼要這麼實現,比如通過工具的代碼學會它的底層細節,與此同時還能豐富知識體系。

第三個What表示在高級階段,知道要

幹什麼事情

需要

什麼工具

,不在細究技術細節,而是通過前期的學習,形成自己的知識網路,能精準的根據當前情況定位到具體的工具。


Sublist3r工具介紹


從Sublist3r的GitHub主頁(https://github.com/aboul3la/Sublist3r)上,我們可以了解到這是一款基於python開發使用OSINT技術的子域名枚舉工具。幫助滲透測試者和bug捕獲者收集目標域名的子域名。


什麼是OSINT


OSINT是英文名「Open-source intelligence」的縮寫,中文名稱叫「公開來源情報」。從公眾可見的信息中,查找所需目標的信息。說的通俗易懂一點,就是我想知道某某東西的詳細信息,我在公開的信息里查找、檢索,找到有關這個東西的任何內容都提取出來,最後將這些內容匯總,得到較為詳細的信息。再說的通俗易懂一點就是:查資料。再再通俗一點就是:找百度。最終目標信息的準確度、詳細程度均依賴於查找源。所以Sublist3r的原理就是這樣,但是Sublist3r的查找源很多,不僅僅是在個別搜索引擎上查找。搜索源包括有百度、Yahoo、Google、Bing、Ask、Netcraft等等除此之外使用通過查找SSL證書、DNS、暴力枚舉等這些手段去查找子域名。


簡單使用


可以通過git clone [https://github.com/aboul3la/Sublist3r.git](https://github.com/aboul3la/Sublist3r.git)安裝Sublist3r。然後使用sudo pip install -r requirements.txt安裝依賴庫。最後通過一個簡單的命令查找子域名,這裡以freebuf為例子。python3 sublist3r.py -d freebuf.com網站內容越多查詢時間越慢,可以加一個-v來實時顯示找到的子域名。

代碼細節


代碼目錄


在Linux終端下,使用tree能列印當前目錄等結構樹:



入口函數


sublist3r的的主要代碼實現在sublist3r.py文件中。可以使用你喜歡的代碼編輯器,打開這個文件。為了便於閱讀,我們把所有的代碼塊(def、class)合上。你大概會看到如下的場景:



如果不是使用包引用,而是直接在控制台打開,會執行if name == "main":下的內容。這裡我們可以大概的了解到這裡的功能,主要是用於處理用戶在控制台輸入的參數,並將其作為參數去調用main函數。我們可以簡單的了解一下這些參數,domain是用戶輸入的主域名,比如freebuf.com;savefile是用於指定查找結束後子域名數據的保存目;verbose就是我們前面說的-v參數,通過這個參數來控制是否實時輸出信息;engines是查找引擎(搜索源),如果為空則表示查找全部的引擎,如果用戶指定了某個引擎(比如baidu),則只使用指定的引擎(比如baidu)進行查找。


main函數


一下是main這個函數的代碼,我省略了很多的細節和錯誤處理部分的代碼。



首先,代碼開頭根據本地的操作系統類型去聲明變數subdomains_queue,這個用於保存找到的子域名。接著你可以看到domain_check,這個用於驗證域名是否合法。字典變數supported_engines內即為今天的重頭戲——查找引擎。冒號前面的字元串比如『baidu』表示引擎的名字,冒號後面的BaiduEnum表示對應的類class BaiduEnum(enumratorBaseThreaded)



每一個引擎就是一個寫好的類,我們把類作為數據保存到列表enums裡面。最終我們通過for循環來依次調用每一個類。而這每一個類都對應了該網站的子域名查詢規則。就像BaiduEnum這個類,它裡面就寫好了如何在百度上查找關鍵詞,以及如何篩選數據等等內容。


類BaiduEnum


因為文章篇幅有限,我們就不一個一個類講過去,就從BaiduEnum這個類為例子,其他的類處理方法也差不多。BaiduEnum這個類繼承與enumratorBaseThreaded類,而enumratorBaseThreaded類又繼承於multiprocessing.Process類以及enumratorBase類。這2個類是所有引擎的基類。它們把引擎的基本功能提取出來,比如網路請求、http頭數據等等。如果不是很了解這個概念可以去查找一下面向對象編程中的繼承概念。我們來看看BaiduEnum的構造函數:



重點在於base_url,url中的{page_no}以及{query}就是需要最終替換的目標,query表示查詢參數,page_no表示頁數,也許很多人會以為這個頁數是我們通俗意義上的1表示第一頁,2表示第二頁。但如果你去仔細看代碼,你會發現在默認情況下這個page_no是每一次加10。這是因為百度和谷歌對於page_no的處理並不是以頁數為基礎,而是以搜索條數為基礎。每一頁顯示10條搜索內容,那麼下一頁就是源基礎上加上10。這樣說可能會有點抽象,說的簡單點,page_no為0的時候,搜索引擎默認顯示的是1-10條記錄,當page_no為10的時候,搜索引擎顯示的是第11-20條記錄,以此類推。這2個參數會在後續代碼中構造出來並替換。比如{query}在後續的代碼中它則會根據查找出來的子域名實時替換。


要理解這個,我們要先了解一下一個搜索的小技巧。如果我希望在搜索引擎上查找關於域名的知識,那我可以搜索域名。但是突然我覺得這樣搜索很不精準,我想把所有百度知道的內容排除掉,那我就可以搜索:域名 -百度知道。再進一步,我想把百度貼吧的數據也排除掉,那麼我的搜索詞應該是這樣的:域名 -百度知道 -貼吧。最後我發現,只有知乎上的信息比較符合我的要求,那我就可以直接指定查詢條件:域名 site:zhihu.com來查詢。這個技巧也用到了{query}身上。假設我們想尋找freebuf.com的子域名,那麼我們最開始的初始值應該是這樣的:site:freebuf.com,接著我們發現有一個子域名[www.freebuf.com](http://www.freebuf.com),那麼我們的查詢條件就變成了:site:freebuf.com -site:[www.freebuf.com](http://www.freebuf.com)。再接著,我們發現了一個新的子域名job.freebuf.com,那我們的查詢條件就變成了site:freebuf.com -site:[www.freebuf.com](http://www.freebuf.com) -site:job.freebuf.com以此類推,不斷的限制查詢條件直到找不到為止。好了,我們已經知道如何構建url鏈接去搜索,那麼它sublist3r又是如何通過搜索結果獲取域名的呢?在類BaiduEnumextract_domains方法里就實現了url地址的解析,如下所示。



其餘的代碼都是為上下文服務的,我們就來看看幾個關鍵代碼就好,比如re.compile("``?class="c-showurl".?>(.?)")這是一個正則表達式。找到所有class名稱為『c-showurl』的a標籤。我們可以在百度上隨便搜索一點東西,然後右鍵源代碼,看到搜索記錄的html代碼。我這裡的一個例子是這樣的:



沒錯,這個a標籤的class是c-showurl,且我們可以看到在a標籤包含下,有一個若隱若現的網址,雖然被隱藏了後面一半,我們還是可以看出它的子域名。第二個正則表達式re.sub("<.*?>|>|<| ", "", link)的目的是把找到的文本的細枝末節砍掉,留下我們需要的那一段域名。就這樣我們我們通過正則表達式找到了搜索記錄里的子域名,最後經過去重,拿到最終的子域名列表。代碼的其他細節我就沒有很詳細的描述,我希望這裡只是一個閱讀引導,更多代碼的細節由於篇幅有限就不在一行一行詳細描述。因為大部分的代碼寫出來是為了執行上下文而寫的,並不是為了原理而寫。我們只要知道代碼的執行原理,以及代碼的目的即可。


暴力枚舉子域名


暴力枚舉也是很普遍的一種方法。所謂的暴力枚舉真的很暴力,它是通過一個一個子域名試過去,看看目標子域名是否存在。暴力枚舉域名的代碼沒有寫在sublist3r.py代碼中,而是獨立包裝了一個庫,稱之為subbrute,代碼在/subbrute/subbrute.py文件中。它會根據你目前的參數去配置是否激活暴力枚舉。這一段代碼寫在main函數中,前面的main函數為了簡潔,我把暴力枚舉那一部分的代碼去掉了。如果要看完整版的可以去看官方的代碼。下面是通過sublist3r.py中main函數調用subbrute的代碼片段。



你可以看到,先通過enable_bruteforce變數判斷是否要激活(默認是激活狀態)暴力枚舉。然後讀入『names.txt』和『resolvers.txt』文件,最終,傳給包subbrute,得到枚舉後的子域名列表。並存儲到bruteforce_list內。subbrute的代碼大家可以自己去瀏覽一下。但是這裡可以簡單的講解一下它的原理。其實相對來說也是比較簡單的。暴力枚舉雖然暴力,但是並不傻。不會真的從a開始一直試到zzzzz……它是採用了把可能會使用到子域名都寫出來,然後再一個一個試過去。前面代碼中引入的『names.txt』就是可能用到的子域名。不行大家可以打開看看,裡面包含了大部分我們日常生活中會用到的子域名組合,比如』email,www』等等。至於『resolvers.txt』文件其實就是開放的DNS查詢地址,類似於8.8.8.8這種DNS服務的集合。


使用ssl證書枚舉子域名

現在帶有的ssl證書的越來越多,如果目標站點是全站https,一般就只有一個證書,然後,各個子域名都包含在證書裡面。我們可以通過對ssl證書的解析去獲取子域名數據。比如下面的這個例子:



你可以看到,這個證書頒發給了旗下的這麼多域名。但是在sublist3r中沒有採用自己下載ssl證書解析的形式,而是直接通過一個在線服務https://crt.sh/ 來查詢,相對來說會比較方便,但是隱藏了ssl子域名枚舉的技術細節,對於想通過代碼了解實際原理的小夥伴來說不太友好。另外還有一個通過DNS枚舉子域名也是通過在線的服務https://dnsdumpster.com來達到目的。至於dnsdumpster的底層細節我猜測可能是通過一些我們熟知的域傳送漏洞,dns反查,暴力枚舉等方法去實現。


總結


sublist3r代碼量不多,很適合初學者學習。從寫文章的角度來說,實在是難以一行一行代碼展開講。這也是我第一次寫代碼閱讀的文章,沒有什麼經驗,如果大家有什麼建議歡迎大家理性的提出來。


*本文作者:mscb,本文屬 FreeBuf 原創獎勵計劃,未經許可禁止轉載。


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 FreeBuf 的精彩文章:

淺析AMR智能合約批量轉賬溢出漏洞
看我如何回懟手機黑客?黑回去!

TAG:FreeBuf |