前言
平時掃描弱密碼一般都用超級弱密碼,前段時間做項目,發現在滲透過程中拿到一台Linux伺服器或者拿了一台Windows伺服器而這台Windows伺服器我們又不想開3389的情況下,掃描其内網弱密碼隻能使用超級弱密碼+sock形式。
而這種方式由于多了一層代理,受網絡波動比較大,形象點就是小針管上面接了一個高壓水槍,掃描出來的準确度就不用說了,而我們滲透時候又常用Webshell而非GUI來執行指令。是以我需要一款Windows/Linux雙用爆破工具,第一個想到的當然是Go。
本着不造輪子的思想,先搜尋了一下有沒有人寫過,發現了
x-crack
這款工具,讀了一遍後發現作者代碼寫的真的很好,比我自己寫代碼時東一榔頭西一棒槌好多了,想着寫篇文章分析一下工具代碼,這樣以後在看會比較快。
同時也向原作者緻敬和學習,感謝作者的付出。
代碼分析
先貼出工具位址:https://github.com/netxfly/x-crack
下面是工程目錄:
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SZzYWO2YGNzMmYzE2YyYzYmdjZ2AzMhZDOhhjY5EGOk9CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
cmd
目錄:存放指令行于程式互動的代碼,就是我們常見的-h等
logger
目錄:自定義log的輸出方式
model
目錄:一個檔案存放着利用go-cache開源項目對爆破結果進行處理的代碼,另一個檔案存放着軟體涉及到的資料結構
plugin
目錄:存放着各種爆破的代碼,如ftp、ssh
util
目錄:工具類,負責處理任務排程、檔案處理等内容
var
目錄:存放着項目用到的全局變量,如:字典檔案名、爆破協程數等
x-crack.go
:main方法,主要是啟動程式
cli
使用了
github.com/urfave/cli
的開源項目。
cmd.Scan
的内容如下:
代碼設計
1、全局變量設定:項目把所有的屬性類内容(如:目标檔案夾,掃描并發數等)統一放到了
vars.go
中,在項目運作中各階段代碼需要運用到這些變量的時候就可以直接從
vars
的全局變量中取走。
2、掃描子產品化:設定了一個關于掃描子產品的統一接口
ScanFunc
,所有掃描子產品都繼承該接口,便于後面規範化調用。同時在
plugins.go
的
init
方法下注冊各掃描子產品,如果後續需要添加子產品,在
plugins.go
裡面新增即可完成注冊。
FTP爆破子產品:
3、規範過程中資料結構
Service
:即爆破目标的相關資訊
ScanResult
:包含Service資料結構以及該條爆破是否成功
IpAddr
:包含目标的ip、端口、使用協定
執行流程
task.go
目錄下的
Scan
方法為程式的起始點,首先是一系列正常的判斷指令行中是否指定了屬性值,若指定了則指派給
vars.go
中的全局變量:
然後就是對目标、使用者名、密碼進行讀取、目标探活、生成爆破任務清單、執行任務等操作。在下圖的代碼中都有注釋,我們主要看
RunTask
是如何操作的:
代碼截圖:
首先是初始化一個進度條然後聲明一個
wg
用來防止程式在協程工作時主線程先結束。
之後建立了一個兩倍于指定協程數目的
channel
。而下面這段代碼就是一個
golang
實作的生産者-消費者模型:
我之前對于該模型的疑惑在于,如果有某一刻
for
循環中的
taskChan
不處于阻塞狀态了,被
close(taskChan)
關閉了,那消費者豈不是取不到
taskChan
中殘留的資料了?通過看網上大神的解答,大神給出了下面解釋。也就是說,直到通道關閉并且通道裡面為空,循環才會終止,通帶才會被結束。也就是說并不會出現我說的這種情況。
回到正題,接着看
crackPassword
方法的實作,直接從我下圖中畫紅線的地方看,前面的主要是一些輔助性工作。
我們看到首先判斷了目标協定,如果時
redis
、
ftp
、
snmp
,那麼
k=ip-port-protocol
,如果不是這些協定,
k=ip-port-username
。
然後這個
k
值會被
hash.MakeTaskHash
做一次
hash
,并校驗該
hash
。如果校驗通過則該次循環結束,直接進入下一次循環,如果不通過,則調用爆破子產品對此目标進行爆破。
對于這段代碼的作用,有心的人會發現這些協定都存在匿名通路,比如
redis
協定,如果目标的
redis
有未授權,那麼你用什麼使用者名密碼都能登入成功,最後輸出的結果就是一大堆爆破成功賬号密碼。
是以這裡對于這些有匿名通路的協定,爆破成功一次後會把其
k
值得
hash
放入一個
map
中維護,如果後面有同ip同端口且同協定得目标再來爆破,那就直接略過,不進行再次爆破。
最後産生得最直覺得結果就是,一個目标得
redis
未授權隻能爆破出來一組使用者名密碼,而一個目标得
mysql
如果賬号密碼都正确可以爆破出來多組使用者名密碼。
而具體得爆破工作則是由
fn(task)
來做,
fn
是從
plugins.ScanFuncMap
中根據協定取出來得,這也是之前爆破子產品那裡規範接口得好處,在這裡用的時候可以直接用一個
fn
表達出所有以注冊過得爆破子產品(如
ScanFtp
、
ScanSsh
),然後将爆破結果儲存到緩存中:
等所有得協程執行
crackPassword
結束後,把緩存中爆破成功得資料進行導出。在這之前作者還設計了一個爆破得時候防止有些協定沒有逾時選項是以自己設定了一個逾時中斷方法
WaitTimeout
,感興趣可以自己看看:
主要的思路就是如上所述這樣。
拓展
這個工具大緻符合我對于爆破得需要,支援協定也很全,缺陷有些地方不夠符合我的預期,于是我在這個工具上自己疊代了四個小版本。
在原工具基礎上又新增了一些符合我們平常滲透得一些輸入方式,比如指定一堆
ip
、
使用者名
、
密碼
,用指定得協定來對這些爆破和指定配置檔案進行操作等功能,同時又加了一個
oracle
和
wmi
爆破得插件。
下面是改變之後工具得部分功能展示:
結尾:再次向原作緻敬!