【技術原創】Sophos UTM利用分析——匯出配置檔案

語言: CN / TW / HK

0x00 前言

對於Sophos UTM裝置,介紹利用方法的資料很少,本文將要介紹從零研究匯出配置檔案的過程,記錄細節,開源利用指令碼。

0x01 簡介

本文將要介紹以下內容:

Sophos UTM測試環境搭建

匯出配置檔案的研究過程

開源指令碼

0x02 Sophos UTM測試環境搭建

1.下載映象

下載頁面:http://www.sophos.com/en-us/support/downloads/utm-downloads

這裡選擇版本9.711-5.1,分別有以下兩個映象檔案:

ssi-9.711-5.1.iso,需要在Sophos裝置上安裝,如果直接在VM中安裝,會提示"No appliance hardware has been detected" on appliance hardware

asg-9.711-5.1.iso,可在VM中安裝

測試環境使用VMware搭建,所以下載asg-9.711-5.1.iso

2.安裝映象

配置好後等待系統重啟,訪問配置頁面:http://<  ip >:4444/

設定admin account password,作為登入配置頁面的使用者名稱和口令

3.配置

需要填入License

4.開啟ssh登入

進入配置頁面後,依次選擇Management->System Settings->Shell Access,分別設定root使用者和loginuser使用者的口令

如下圖

5.允許root使用者口令登入ssh

sed -i "s/PermitRootLogin no/PermitRootLogin yes /g" /etc/ssh/sshd_config
/var/mdw/scripts/sshd restart

0x03 匯出配置檔案的研究過程

1.查詢postgresql資料庫

配置檔案的位置:/var/storage/pgsql92/data/postgresql.conf

預設配置下,連線資料庫不需要口令

連線命令:

psql -h localhost -U postgres

資料庫內容如下圖

但我在資料庫中沒有找到配置資訊

2.查詢文件獲得檢視配置的思路

依次執行以下命令:

cc
webadmin
port$

獲得了webadmin的port資訊,如下圖

從輸出內容上,發現cc命令連線了127.0.0.1的4472埠,接下來打算從埠入手

3.定位同4472埠相關的程序

獲得4472埠對應的程序pid:

netstat -ltp | grep 4472

返回內容如下圖

從返回內容可以看到對應的程序pid為4407

4.檢視pid 4407的程序資訊

依次執行以下命令:

cd /proc/4407/cwd
ls

返回內容如下圖

從返回內容獲得以下資訊:

目錄為/var/confd

配置檔案為config.pm

主程式為confd.plx,無法直接檢視原始碼

5.反編譯confd.plx

經過搜尋,在《網路裝置分析實戰 | Sophos UTM韌體反編譯Perl原始碼》獲得提示: .plx檔案是由PerlAPP工具編譯而來,可通過動態除錯的方法使用IDA反編譯出原始碼

經過搜尋,在《Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223》獲得更為簡單的反編譯方法:通過Python實現靜態反編譯

參照《Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223》中的方法在反編譯confd.plx的過程中,會遇到bug,我們需要修改《Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223》中提到的bfs_extract.py

整合yank.py和bfs.py,修復bfs_extract.py中的bug,完整的程式碼已上傳至github,地址如下:

http://github.com/3gstudent/Homework-of-Python/blob/master/SophosUTM_plxDecrypter.py

使用SophosUTM_plxDecrypter.py能夠獲得confd.plx的反編譯程式碼

6.程式碼分析

經過分析,得知Export-confd.plx\confd.pl為主要功能,在程式碼中發現配置檔案的位置為$config::storage_dir/cfg

如下圖

對應的絕對路徑為/var/confd/var/storage/cfg

7.檔案格式分析

檢視cfg的檔案格式:

file /var/confd/var/storage/cfg

返回結果:

/var/confd/var/storage/cfg: perl Storable (v0.7) data (major 2) (minor 7)

得知格式為perl Storable data,這是Perl經過序列化(Perl中稱為凍結)生成的二進位制資料

8.檔案格式解析

(1)檔案提取

這裡可以使用Python的storable模組提取資料

安裝storable模組:

pip install storable

簡單使用:

from storable import retrieve
data = retrieve('cfg')
print(data)

輸出結果為json資料

(2)檔案分析

為了便於分析json資料,這裡使用Sublime Text的pretty json外掛,安裝方法如下:

在Sublime text中依次選擇Tools -> Command Palette...,打開面板,輸入pci,選中PackageControl: Install Package,在彈出的輸出框中填入pretty json

設定呼叫pretty json外掛的快捷鍵為ctrl+alt+j:

在Sublime Text中依次選擇Preferences -> Key Bindings,在彈出的右側視窗新增如下內容:

[
    { "keys": ["ctrl+alt+j"], "command": "pretty_json" },
]

在使用pretty json解析json時會提示格式錯誤,按照提示逐個修復即可

最終顯示的格式如下圖

9.資料提取

為了提高效率,這裡可以使用Python提取出關鍵資料,開發細節如下:

(1)提取使用者資訊

通過分析json檔案,發現data['exclusive'][b'email_user']['u2v']中的key為每個使用者資訊的標誌,例如user: REF_AaaUseVpn1

再通過對應標誌位置的鍵值能夠獲取使用者的完整資訊,位置為data['objects'][< flag >]['data'],對應例子的位置為data['objects']['REF_AaaUseVpn1']['data']

實現程式碼:

def GetUserDataFull(file):
    data = retrieve(file)
    print("[*] Try to get the full data of user")
    for key, value in data['exclusive'][b'email_user']['u2v'].items():
        index = key.rfind(":")
        indexobject = data['objects'][key[index+1:]]['data']
        print("[+] " + data['objects'][key[index+1:]]['data']['name'])
        for key1, value1 in indexobject.items():
            print("    " + str(key1) + ": " + str(value1))

(2)提取網路配置資訊

通過分析json檔案,發現data['index']['network']中的value為每個網路配置的標誌,例如REF_DefaultInternalNetwork

再通過對應標誌位置的鍵值讀取完整資訊,位置為data['objects'][< flag >]['data'],對應例子的位置為data['objects']['REF_DefaultInternalNetwork']['data']

實現程式碼:

def GetNetworkConfig(file):
    data = retrieve(file)
    print("[*] Try to get the config of network")
    for key, value in data['index']['network'].items():
        print("[+] " + str(key))
        for objectvalue in value:
            print("  - " + objectvalue)
            for key1, value1 in data['objects'][objectvalue]['data'].items():
                print("    " + str(key1) + ": " + str(value1))

(3)提取LastChange資訊

位置:data['lastchange']

需要注意時間格式,預設為數字形式,例如1652930086,需要進行轉換

實現程式碼:

def GetLastChange(file):
    data = retrieve(file)
    print("[*] Try to get the data of LastChange")
    print("")
    for key, value in data['lastchange'].items():
        print("[+] " + str(key))
        for key1, value1 in value.items():
            if str(key1) == "time":
                print("    time: "+str(datetime.fromtimestamp(value['time'])))  
            else:
                print("    " + str(key1) + ": " + str(value1))

完整的程式碼已上傳至github,地址如下:

http://github.com/3gstudent/Homework-of-Python/blob/master/SophosUTM_ConfigParser.py

程式碼支援以下功能:

GetAdminDataFull,提取出管理員使用者的完整資訊

GetAdminHash,提取出管理員使用者的md4 hash

GetLastChange,提取出LastChange資訊

GetNetworkConfig,提取出網路配置資訊

GetRemoteAccess,提取出VPN配置資訊

GetSSHConfig,提取出SSH連線資訊

GetUserDataFull,提取出使用者的完整資訊

GetUserHash,提取出使用者的md4 hash

Parsefile,提取出完整資訊

0x04 小結

本文介紹了匯出Sophos UTM配置檔案的研究過程,開源利用指令碼以提高分析效率。

如若轉載,請註明原文地址