[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$ft7Z-kJj4opGdduWYI3YeSdYGXDtZxKKvE9da5qt-eH4":3},{"id":4,"question":5,"answer":6,"answerHtml":7,"slug":8,"keywords":9,"article":10,"status":34,"aiModel":39,"aiConfidence":39,"updatedAt":51,"createdAt":51,"_status":50},920,"What type of sensitive data can be extracted from a Sophos UTM configuration file?","Extracting the `cfg` file yields administrator user information (via `data['exclusive']['email_user']['u2v']`), network configuration details (via `data['index']['network']`), and `lastchange` timestamps. Python scripts can automate extraction of full user data, network configs, and convert Unix timestamps to human-readable format. This data can be leveraged for lateral movement or privilege escalation. For example, similar extraction techniques are used in analyzing [Zimbra Deserialization Vulnerability](\u002Fnews\u002Fzimbra-deserialization-vulnerability-cve-2019-6980-exploitation-test) and [F5 BIG-IP Vulnerability Debugging](\u002Fnews\u002Ff5-big-ip-vulnerability-debugging-environment-setup).","\u003Cp>Extracting the `cfg` file yields administrator user information (via `data[&#39;exclusive&#39;][&#39;email_user&#39;][&#39;u2v&#39;]`), network configuration details (via `data[&#39;index&#39;][&#39;network&#39;]`), and `lastchange` timestamps. Python scripts can automate extraction of full user data, network configs, and convert Unix timestamps to human-readable format. This data can be leveraged for lateral movement or privilege escalation. For example, similar extraction techniques are used in analyzing [Zimbra Deserialization Vulnerability](\u002Fnews\u002Fzimbra-deserialization-vulnerability-cve-2019-6980-exploitation-test) and [F5 BIG-IP Vulnerability Debugging](\u002Fnews\u002Ff5-big-ip-vulnerability-debugging-environment-setup).\u003C\u002Fp>\u003Cp>\u003Ca href=\"\u002Fnews\u002Fsophos-utm-exploitation-analysis-exporting-configuration-files\">Read the related One Day Sec article\u003C\u002Fa>\u003C\u002Fp>","what-type-of-sensitive-data-can-be-extracted-from-a-sophos-utm-configuration-fil-1777481330429","configuration extraction, administrator credentials, network config, sensitive data, Sophos UTM",{"id":11,"title":12,"slug":13,"description":14,"content":15,"contentHtml":30,"cover":31,"author":32,"views":19,"readingTime":33,"status":34,"publishedAt":35,"seo":36,"tags":41,"qaPairs":42,"meta":47,"updatedAt":48,"createdAt":49,"_status":50},223,"Sophos UTM Exploitation Analysis - Exporting Configuration Files","sophos-utm-exploitation-analysis-exporting-configuration-files","Step-by-step guide on exploiting Sophos UTM to export configuration files, including environment setup, research process, and open-source scripts.",{"root":16},{"type":17,"format":18,"indent":19,"version":20,"children":21,"direction":29},"root","",0,1,[22],{"type":23,"format":18,"indent":19,"version":20,"children":24,"direction":29},"paragraph",[25],{"mode":26,"text":27,"type":28,"style":18,"detail":19,"format":19,"version":20},"normal","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>There is limited documentation on exploitation methods for Sophos UTM devices. This article will introduce the process of researching configuration file export from scratch, record details, and open-source exploitation scripts.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Sophos UTM test environment setup\u003C\u002Fli>\u003Cli>Research process for exporting configuration files\u003C\u002Fli>\u003Cli>Open-source scripts\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Sophos UTM Test Environment Setup\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Download the image\u003C\u002Fh3>\u003Cp>Download page: https:\u002F\u002Fwww.sophos.com\u002Fen-us\u002Fsupport\u002Fdownloads\u002Futm-downloads\u003C\u002Fp>\u003Cp>Here, version 9.711-5.1 is selected, with the following two image files:\u003C\u002Fp>\u003Cul>\u003Cli>ssi-9.711-5.1.iso, must be installed on Sophos hardware appliances. If installed directly in a VM, it will prompt \"No appliance hardware has been detected\" on appliance hardware\u003C\u002Fli>\u003Cli>asg-9.711-5.1.iso, can be installed in a VM\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The test environment is built using VMware, so download asg-9.711-5.1.iso\u003C\u002Fp>\u003Ch3>2. Install the image\u003C\u002Fh3>\u003Cp>After configuration, wait for the system to reboot, then access the configuration page: https:\u002F\u002F\u003Cip>:4444\u002F\u003C\u002Fip>\u003C\u002Fp>\u003Cp>Set the admin account password, which will be used as the username and password to log into the configuration page\u003C\u002Fp>\u003Ch3>3. Configuration\u003C\u002Fh3>\u003Cp>License needs to be entered\u003C\u002Fp>\u003Ch3>4. Enable SSH login\u003C\u002Fh3>\u003Cp>After entering the configuration page, navigate to Management-&gt;System Settings-&gt;Shell Access, and set passwords for the root user and loginuser user respectively\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017323383_0_1e9ef25fa2.png\">\u003C\u002Fp>\u003Ch3>5. Allow root user password login via SSH\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>sed -i \"s\u002FPermitRootLogin no\u002FPermitRootLogin yes \u002Fg\" \u002Fetc\u002Fssh\u002Fsshd_config\u003Cbr>\u002Fvar\u002Fmdw\u002Fscripts\u002Fsshd restart\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 Research process of exporting configuration files\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Query the PostgreSQL database\u003C\u002Fh3>\u003Cp>Location of configuration file: \u002Fvar\u002Fstorage\u002Fpgsql92\u002Fdata\u002Fpostgresql.conf\u003C\u002Fp>\u003Cp>Under default configuration, no password is required to connect to the database\u003C\u002Fp>\u003Cp>Connection command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>psql -h localhost -U postgres\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Database content as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017376988_1_88d956f7b2.png\">\u003C\u002Fp>\u003Cp>But I did not find configuration information in the database\u003C\u002Fp>\u003Ch3>2. Obtain ideas for viewing configuration by querying documentation\u003C\u002Fh3>\u003Cp>Execute the following commands in sequence:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>cc\u003Cbr>webadmin\u003Cbr>port$\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Obtained the port information for webadmin, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017398089_2_c3563cd901.png\">\u003C\u002Fp>\u003Cp>From the output content, it was found that the cc command connected to port 4472 of 127.0.0.1. Next, we plan to proceed from the port.\u003C\u002Fp>\u003Ch3>3. Locate processes related to port 4472\u003C\u002Fh3>\u003Cp>Obtain the process pid corresponding to port 4472:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>netstat -ltp | grep 4472\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The returned content is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017445281_3_64f003aadb.png\">\u003C\u002Fp>\u003Cp>From the returned content, it can be seen that the corresponding process pid is 4407\u003C\u002Fp>\u003Ch3>4. View process information for pid 4407\u003C\u002Fh3>\u003Cp>Execute the following commands in sequence:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>cd \u002Fproc\u002F4407\u002Fcwd\u003Cbr>ls\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The returned content is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017468234_4_50c9d5ae39.png\">\u003C\u002Fp>\u003Cp>From the returned content, the following information is obtained:\u003C\u002Fp>\u003Cul>\u003Cli>The directory is \u002Fvar\u002Fconfd\u003C\u002Fli>\u003Cli>The configuration file is config.pm\u003C\u002Fli>\u003Cli>The main program is confd.plx, and the source code cannot be viewed directly\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>5. Decompile confd.plx\u003C\u002Fh3>\u003Cp>After searching, a hint was obtained from 'Network Device Analysis Practice: Decompiling Perl Source Code in Sophos UTM Firmware': .plx files are compiled by the PerlAPP tool and can be decompiled into source code using IDA through dynamic debugging methods\u003C\u002Fp>\u003Cp>After searching, a simpler decompilation method was obtained from 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223': static decompilation implemented via Python\u003C\u002Fp>\u003Cp>Following the method in 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223', bugs are encountered during the decompilation of confd.plx. We need to modify bfs_extract.py mentioned in 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223'\u003C\u002Fp>\u003Cp>Integrate yank.py and bfs.py, fix the bug in bfs_extract.py. The complete code has been uploaded to GitHub, with the address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Using SophosUTM_plxDecrypter.py, the decompiled code of confd.plx can be obtained\u003C\u002Fp>\u003Ch3>6. Code Analysis\u003C\u002Fh3>\u003Cp>After analysis, it is learned that Export-confd.plx\\confd.pl is the main functionality. In the code, the location of the configuration file is found to be $config::storage_dir\u002Fcfg\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017482082_5_f54399f60c.png\">\u003C\u002Fp>\u003Cp>The corresponding absolute path is \u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg\u003C\u002Fp>\u003Ch3>7. File Format Analysis\u003C\u002Fh3>\u003Cp>Check the file format of cfg:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>file \u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Return result:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg: perl Storable (v0.7) data (major 2) (minor 7)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The format is identified as perl Storable data, which is binary data generated through serialization (referred to as freezing in Perl) in Perl\u003C\u002Fp>\u003Ch3>8. File Format Parsing\u003C\u002Fh3>\u003Ch4>(1) File Extraction\u003C\u002Fh4>\u003Cp>Here, the storable module in Python can be used to extract the data\u003C\u002Fp>\u003Cp>Install the storable module:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>pip install storable\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Simple usage:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from storable import retrieve\u003Cbr>data = retrieve('cfg')\u003Cbr>print(data)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is JSON data\u003C\u002Fp>\u003Ch4>(2) File Analysis\u003C\u002Fh4>\u003Cp>To facilitate the analysis of JSON data, the Pretty JSON plugin for Sublime Text is used here. The installation method is as follows:\u003C\u002Fp>\u003Cp>In Sublime Text, select Tools -&gt; Command Palette... to open the panel, enter pci, select Package Control: Install Package, and then enter pretty json in the pop-up output box.\u003C\u002Fp>\u003Cp>Set the shortcut key for calling the Pretty JSON plugin to ctrl+alt+j:\u003C\u002Fp>\u003Cp>In Sublime Text, select Preferences -&gt; Key Bindings, and add the following content in the pop-up right window:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>[\u003Cbr>    { \"keys\": [\"ctrl+alt+j\"], \"command\": \"pretty_json\" },\u003Cbr>]\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using Pretty JSON to parse JSON, format errors may be prompted. Fix them one by one according to the prompts.\u003C\u002Fp>\u003Cp>The final displayed format is shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fuploads\u002Fdocx_image_1770017494788_6_61c4f29183.png\">\u003C\u002Fp>\u003Ch3>9. Data Extraction\u003C\u002Fh3>\u003Cp>To improve efficiency, Python can be used here to extract key data. The development details are as follows:\u003C\u002Fp>\u003Ch4>(1) Extract user information\u003C\u002Fh4>\u003Cp>By analyzing the json file, it is found that the key in data['exclusive'][b'email_user']['u2v'] serves as the identifier for each user's information, e.g., user: REF_AaaUseVpn1\u003C\u002Fp>\u003Cp>Then, the complete user information can be obtained through the key-value at the corresponding identifier position, located at data['objects'][\u003Cflag>]['data']. For the example, the position is data['objects']['REF_AaaUseVpn1']['data']\u003C\u002Fflag>\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetUserDataFull(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the full data of user\")\u003Cbr>    for key, value in data['exclusive'][b'email_user']['u2v'].items():\u003Cbr>        index = key.rfind(\":\")\u003Cbr>        indexobject = data['objects'][key[index+1:]]['data']\u003Cbr>        print(\"[+] \" + data['objects'][key[index+1:]]['data']['name'])\u003Cbr>        for key1, value1 in indexobject.items():\u003Cbr>            print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Extract network configuration information\u003C\u002Fh4>\u003Cp>By analyzing the json file, it is found that the value in data['index']['network'] serves as the identifier for each network configuration, e.g., REF_DefaultInternalNetwork\u003C\u002Fp>\u003Cp>Then read the complete information through the key value corresponding to the flag position, which is data['objects'][\u003Cflag>]['data']. The corresponding example position is data['objects']['REF_DefaultInternalNetwork']['data']\u003C\u002Fflag>\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetNetworkConfig(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the config of network\")\u003Cbr>    for key, value in data['index']['network'].items():\u003Cbr>        print(\"[+] \" + str(key))\u003Cbr>        for objectvalue in value:\u003Cbr>            print(\"  - \" + objectvalue)\u003Cbr>            for key1, value1 in data['objects'][objectvalue]['data'].items():\u003Cbr>                print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3) Extract LastChange information\u003C\u002Fh4>\u003Cp>Location: data['lastchange']\u003C\u002Fp>\u003Cp>Note the time format, which defaults to numeric form, e.g., 1652930086, and needs to be converted\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetLastChange(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the data of LastChange\")\u003Cbr>    print(\"\")\u003Cbr>    for key, value in data['lastchange'].items():\u003Cbr>        print(\"[+] \" + str(key))\u003Cbr>        for key1, value1 in value.items():\u003Cbr>            if str(key1) == \"time\":\u003Cbr>                print(\"    time: \"+str(datetime.fromtimestamp(value['time'])))\u003Cbr>            else:\u003Cbr>                print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The complete code has been uploaded to GitHub, the address is as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>The code supports the following features:\u003C\u002Fp>\u003Cul>\u003Cli>GetAdminDataFull, extracts complete information of administrator users\u003C\u002Fli>\u003Cli>GetAdminHash, extract the md4 hash of the administrator user\u003C\u002Fli>\u003Cli>GetLastChange, extract the LastChange information\u003C\u002Fli>\u003Cli>GetNetworkConfig, extract the network configuration information\u003C\u002Fli>\u003Cli>GetRemoteAccess, extract the VPN configuration information\u003C\u002Fli>\u003Cli>GetSSHConfig, extract the SSH connection information\u003C\u002Fli>\u003Cli>GetUserDataFull, extract the user's complete information\u003C\u002Fli>\u003Cli>GetUserHash, extract the user's md4 hash\u003C\u002Fli>\u003Cli>Parsefile, extract the complete information\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the research process of exporting Sophos UTM configuration files and open-sources the exploitation script to improve analysis efficiency.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>","text","ltr","\u003Chtml>\u003Chead>\u003C\u002Fhead>\u003Cbody>\u003Ch2>0x00 Preface\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>There is limited documentation on exploitation methods for Sophos UTM devices. This article will introduce the process of researching configuration file export from scratch, record details, and open-source exploitation scripts.\u003C\u002Fp>\u003Ch2>0x01 Introduction\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article will cover the following:\u003C\u002Fp>\u003Cul>\u003Cli>Sophos UTM test environment setup\u003C\u002Fli>\u003Cli>Research process for exporting configuration files\u003C\u002Fli>\u003Cli>Open-source scripts\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x02 Sophos UTM Test Environment Setup\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Download the image\u003C\u002Fh3>\u003Cp>Download page: https:\u002F\u002Fwww.sophos.com\u002Fen-us\u002Fsupport\u002Fdownloads\u002Futm-downloads\u003C\u002Fp>\u003Cp>Here, version 9.711-5.1 is selected, with the following two image files:\u003C\u002Fp>\u003Cul>\u003Cli>ssi-9.711-5.1.iso, must be installed on Sophos hardware appliances. If installed directly in a VM, it will prompt \"No appliance hardware has been detected\" on appliance hardware\u003C\u002Fli>\u003Cli>asg-9.711-5.1.iso, can be installed in a VM\u003C\u002Fli>\u003C\u002Ful>\u003Cp>The test environment is built using VMware, so download asg-9.711-5.1.iso\u003C\u002Fp>\u003Ch3>2. Install the image\u003C\u002Fh3>\u003Cp>After configuration, wait for the system to reboot, then access the configuration page: https:\u002F\u002F\u003Cip>:4444\u002F\u003C\u002Fip>\u003C\u002Fp>\u003Cp>Set the admin account password, which will be used as the username and password to log into the configuration page\u003C\u002Fp>\u003Ch3>3. Configuration\u003C\u002Fh3>\u003Cp>License needs to be entered\u003C\u002Fp>\u003Ch3>4. Enable SSH login\u003C\u002Fh3>\u003Cp>After entering the configuration page, navigate to Management-&gt;System Settings-&gt;Shell Access, and set passwords for the root user and loginuser user respectively\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017323383_0_1e9ef25fa2-1.png\">\u003C\u002Fp>\u003Ch3>5. Allow root user password login via SSH\u003C\u002Fh3>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>sed -i \"s\u002FPermitRootLogin no\u002FPermitRootLogin yes \u002Fg\" \u002Fetc\u002Fssh\u002Fsshd_config\u003Cbr>\u002Fvar\u002Fmdw\u002Fscripts\u002Fsshd restart\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch2>0x03 Research process of exporting configuration files\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Ch3>1. Query the PostgreSQL database\u003C\u002Fh3>\u003Cp>Location of configuration file: \u002Fvar\u002Fstorage\u002Fpgsql92\u002Fdata\u002Fpostgresql.conf\u003C\u002Fp>\u003Cp>Under default configuration, no password is required to connect to the database\u003C\u002Fp>\u003Cp>Connection command:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>psql -h localhost -U postgres\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Database content as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017376988_1_88d956f7b2-1.png\">\u003C\u002Fp>\u003Cp>But I did not find configuration information in the database\u003C\u002Fp>\u003Ch3>2. Obtain ideas for viewing configuration by querying documentation\u003C\u002Fh3>\u003Cp>Execute the following commands in sequence:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>cc\u003Cbr>webadmin\u003Cbr>port$\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Obtained the port information for webadmin, as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017398089_2_c3563cd901-1.png\">\u003C\u002Fp>\u003Cp>From the output content, it was found that the cc command connected to port 4472 of 127.0.0.1. Next, we plan to proceed from the port.\u003C\u002Fp>\u003Ch3>3. Locate processes related to port 4472\u003C\u002Fh3>\u003Cp>Obtain the process pid corresponding to port 4472:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>netstat -ltp | grep 4472\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The returned content is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017445281_3_64f003aadb-1.png\">\u003C\u002Fp>\u003Cp>From the returned content, it can be seen that the corresponding process pid is 4407\u003C\u002Fp>\u003Ch3>4. View process information for pid 4407\u003C\u002Fh3>\u003Cp>Execute the following commands in sequence:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>cd \u002Fproc\u002F4407\u002Fcwd\u003Cbr>ls\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The returned content is as shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017468234_4_50c9d5ae39-1.png\">\u003C\u002Fp>\u003Cp>From the returned content, the following information is obtained:\u003C\u002Fp>\u003Cul>\u003Cli>The directory is \u002Fvar\u002Fconfd\u003C\u002Fli>\u003Cli>The configuration file is config.pm\u003C\u002Fli>\u003Cli>The main program is confd.plx, and the source code cannot be viewed directly\u003C\u002Fli>\u003C\u002Ful>\u003Ch3>5. Decompile confd.plx\u003C\u002Fh3>\u003Cp>After searching, a hint was obtained from 'Network Device Analysis Practice: Decompiling Perl Source Code in Sophos UTM Firmware': .plx files are compiled by the PerlAPP tool and can be decompiled into source code using IDA through dynamic debugging methods\u003C\u002Fp>\u003Cp>After searching, a simpler decompilation method was obtained from 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223': static decompilation implemented via Python\u003C\u002Fp>\u003Cp>Following the method in 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223', bugs are encountered during the decompilation of confd.plx. We need to modify bfs_extract.py mentioned in 'Sophos UTM Preauth RCE: A Deep Dive into CVE-2020-25223'\u003C\u002Fp>\u003Cp>Integrate yank.py and bfs.py, fix the bug in bfs_extract.py. The complete code has been uploaded to GitHub, with the address as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>Using SophosUTM_plxDecrypter.py, the decompiled code of confd.plx can be obtained\u003C\u002Fp>\u003Ch3>6. Code Analysis\u003C\u002Fh3>\u003Cp>After analysis, it is learned that Export-confd.plx\\confd.pl is the main functionality. In the code, the location of the configuration file is found to be $config::storage_dir\u002Fcfg\u003C\u002Fp>\u003Cp>As shown in the figure below\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017482082_5_f54399f60c-1.png\">\u003C\u002Fp>\u003Cp>The corresponding absolute path is \u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg\u003C\u002Fp>\u003Ch3>7. File Format Analysis\u003C\u002Fh3>\u003Cp>Check the file format of cfg:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>file \u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Return result:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>\u002Fvar\u002Fconfd\u002Fvar\u002Fstorage\u002Fcfg: perl Storable (v0.7) data (major 2) (minor 7)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The format is identified as perl Storable data, which is binary data generated through serialization (referred to as freezing in Perl) in Perl\u003C\u002Fp>\u003Ch3>8. File Format Parsing\u003C\u002Fh3>\u003Ch4>(1) File Extraction\u003C\u002Fh4>\u003Cp>Here, the storable module in Python can be used to extract the data\u003C\u002Fp>\u003Cp>Install the storable module:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>pip install storable\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>Simple usage:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>from storable import retrieve\u003Cbr>data = retrieve('cfg')\u003Cbr>print(data)\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The output result is JSON data\u003C\u002Fp>\u003Ch4>(2) File Analysis\u003C\u002Fh4>\u003Cp>To facilitate the analysis of JSON data, the Pretty JSON plugin for Sublime Text is used here. The installation method is as follows:\u003C\u002Fp>\u003Cp>In Sublime Text, select Tools -&gt; Command Palette... to open the panel, enter pci, select Package Control: Install Package, and then enter pretty json in the pop-up output box.\u003C\u002Fp>\u003Cp>Set the shortcut key for calling the Pretty JSON plugin to ctrl+alt+j:\u003C\u002Fp>\u003Cp>In Sublime Text, select Preferences -&gt; Key Bindings, and add the following content in the pop-up right window:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>[\u003Cbr>    { \"keys\": [\"ctrl+alt+j\"], \"command\": \"pretty_json\" },\u003Cbr>]\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>When using Pretty JSON to parse JSON, format errors may be prompted. Fix them one by one according to the prompts.\u003C\u002Fp>\u003Cp>The final displayed format is shown in the figure below.\u003C\u002Fp>\u003Cp>\u003Cimg alt=\"Alt text\" src=\"\u002Fapi\u002Fmedia\u002Ffile\u002Fdocx_image_1770017494788_6_61c4f29183-1.png\">\u003C\u002Fp>\u003Ch3>9. Data Extraction\u003C\u002Fh3>\u003Cp>To improve efficiency, Python can be used here to extract key data. The development details are as follows:\u003C\u002Fp>\u003Ch4>(1) Extract user information\u003C\u002Fh4>\u003Cp>By analyzing the json file, it is found that the key in data['exclusive'][b'email_user']['u2v'] serves as the identifier for each user's information, e.g., user: REF_AaaUseVpn1\u003C\u002Fp>\u003Cp>Then, the complete user information can be obtained through the key-value at the corresponding identifier position, located at data['objects'][\u003Cflag>]['data']. For the example, the position is data['objects']['REF_AaaUseVpn1']['data']\u003C\u002Fflag>\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetUserDataFull(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the full data of user\")\u003Cbr>    for key, value in data['exclusive'][b'email_user']['u2v'].items():\u003Cbr>        index = key.rfind(\":\")\u003Cbr>        indexobject = data['objects'][key[index+1:]]['data']\u003Cbr>        print(\"[+] \" + data['objects'][key[index+1:]]['data']['name'])\u003Cbr>        for key1, value1 in indexobject.items():\u003Cbr>            print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(2) Extract network configuration information\u003C\u002Fh4>\u003Cp>By analyzing the json file, it is found that the value in data['index']['network'] serves as the identifier for each network configuration, e.g., REF_DefaultInternalNetwork\u003C\u002Fp>\u003Cp>Then read the complete information through the key value corresponding to the flag position, which is data['objects'][\u003Cflag>]['data']. The corresponding example position is data['objects']['REF_DefaultInternalNetwork']['data']\u003C\u002Fflag>\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetNetworkConfig(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the config of network\")\u003Cbr>    for key, value in data['index']['network'].items():\u003Cbr>        print(\"[+] \" + str(key))\u003Cbr>        for objectvalue in value:\u003Cbr>            print(\"  - \" + objectvalue)\u003Cbr>            for key1, value1 in data['objects'][objectvalue]['data'].items():\u003Cbr>                print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Ch4>(3) Extract LastChange information\u003C\u002Fh4>\u003Cp>Location: data['lastchange']\u003C\u002Fp>\u003Cp>Note the time format, which defaults to numeric form, e.g., 1652930086, and needs to be converted\u003C\u002Fp>\u003Cp>Implementation code:\u003C\u002Fp>\u003Ctable>\u003Ctbody>\u003Ctr>\u003Ctd>\u003Cp>def GetLastChange(file):\u003Cbr>    data = retrieve(file)\u003Cbr>    print(\"[*] Try to get the data of LastChange\")\u003Cbr>    print(\"\")\u003Cbr>    for key, value in data['lastchange'].items():\u003Cbr>        print(\"[+] \" + str(key))\u003Cbr>        for key1, value1 in value.items():\u003Cbr>            if str(key1) == \"time\":\u003Cbr>                print(\"    time: \"+str(datetime.fromtimestamp(value['time'])))\u003Cbr>            else:\u003Cbr>                print(\"    \" + str(key1) + \": \" + str(value1))\u003C\u002Fp>\u003C\u002Ftd>\u003C\u002Ftr>\u003C\u002Ftbody>\u003C\u002Ftable>\u003Cp>The complete code has been uploaded to GitHub, the address is as follows:\u003C\u002Fp>\u003Cp>An open-source project\u003C\u002Fp>\u003Cp>The code supports the following features:\u003C\u002Fp>\u003Cul>\u003Cli>GetAdminDataFull, extracts complete information of administrator users\u003C\u002Fli>\u003Cli>GetAdminHash, extract the md4 hash of the administrator user\u003C\u002Fli>\u003Cli>GetLastChange, extract the LastChange information\u003C\u002Fli>\u003Cli>GetNetworkConfig, extract the network configuration information\u003C\u002Fli>\u003Cli>GetRemoteAccess, extract the VPN configuration information\u003C\u002Fli>\u003Cli>GetSSHConfig, extract the SSH connection information\u003C\u002Fli>\u003Cli>GetUserDataFull, extract the user's complete information\u003C\u002Fli>\u003Cli>GetUserHash, extract the user's md4 hash\u003C\u002Fli>\u003Cli>Parsefile, extract the complete information\u003C\u002Fli>\u003C\u002Ful>\u003Ch2>0x04 Summary\u003C\u002Fh2>\u003Cp>---\u003C\u002Fp>\u003Cp>This article introduces the research process of exporting Sophos UTM configuration files and open-sources the exploitation script to improve analysis efficiency.\u003C\u002Fp>\u003C\u002Fbody>\u003C\u002Fhtml>",637,"Onedaysec",6,"published","2026-02-02T07:38:21.176Z",{"title":37,"description":14,"keywords":38,"ogImage":39,"canonicalUrl":39,"noIndex":40},"Sophos UTM Exploitation: Exporting Configuration Files Analysis","Sophos UTM, configuration export, exploitation analysis, security research, UTM vulnerabilities",null,false,[],{"docs":43,"hasNextPage":40},[4,44,45,46],919,918,917,{"title":39,"description":39,"image":39},"2026-07-24T15:37:10.811Z","2026-07-23T16:02:16.128Z","draft","2026-07-23T16:15:33.114Z"]