wazuh
wazuh copied to clipboard
Enable detect installed packages on MacOS
Module | Component | Install method | Platform |
---|---|---|---|
Syscollector | Agent | Packages | macOS |
In order to finalize the research issue #15570 and following his related Spike, to improve the installed software detection in MacOS environment.
Proposed changes
Add the next paths:
/private/var/db/receipts
/Library/Apple/System/Library/Receipts\
into:
sysinfoMac.cpp
DoD
- [ ] Add changes to include .pkgs files in software relevant.
- [ ] Add UT for new code added
Hey team! Please add your planning poker estimate with Zenhub @MiguelazoDS @tdrauncieal
Please add your planning poker estimate with Zenhub @Dwordcito
Quick exploratory :green_circle:
Packages number before and after the implementation
Expand
Packages before
Packages after
Diff analysis
There's only one package before
that is not included after
due to the missing version
Expand
Several location information has changed after the implementation.
Exploratory :green_circle:
Environment
- macOS Catalina 10.15.7
- macOS High Sierra 10.13.6
- macOS Monterey 12.6.1
All the files used for these tests
Monterey
Packages before
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/001.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = macports
count(*) = 1
format = pkg
count(*) = 183
Packages without version
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/001.db "SELECT count(*) from sys_programs where version = ' ' OR version = ''"
-- Loading resources from /root/.sqliterc
count(*) = 2
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/001.db "SELECT * from sys_programs where version = ' ' OR version = ''"
-- Loading resources from /root/.sqliterc
scan_id = 0
scan_time = 2023/08/28 23:25:21
format = pkg
name = Install Command Line Developer Tools
priority =
section = public.app-category.developer-tools
size = 0
vendor = apple
install_time =
version =
architecture =
multiarch =
source = utilities
description = com.apple.dt.CommandLineTools.installondemand
location = /System/Library/CoreServices/Install Command Line Developer Tools.app/Contents/Info.plist
triaged = 0
cpe =
msu_name =
checksum = afce62543f50806ec448e4cb822141df7ed8269d
item_id = 82d859f209e4b0a96bc0201eebaa98e581f3e51f
scan_id = 0
scan_time = 2023/08/28 23:25:23
format = pkg
name = Contacts
priority =
section = public.app-category.productivity
size = 0
vendor = apple
install_time =
version =
architecture =
multiarch =
source = utilities
description = com.apple.AddressBook
location = /System/Applications/Contacts.app/Contents/Info.plist
triaged = 0
cpe =
msu_name =
checksum = dc633e9e723f5db606e9ce5642414c2cfaa931b0
item_id = a8ef64f1c1cdb9b951c53d2a31c4f09cb997d2a6
Packages after
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/004.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = macports
count(*) = 1
format = pkg
count(*) = 333
format = rcp
count(*) = 1
There are no packages without version.
New packages
Details
sqlite> SELECT count(*) from newdb.sys_programs AS a LEFT JOIN main.sys_programs AS b ON a.name = b.name WHERE b.name is NULL;
count(*) = 152
High Sierra
Packages before
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/002.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = pkg
count(*) = 146
Packages without version
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/002.db "SELECT count(*) from sys_programs where version = ' ' OR version = ''"
-- Loading resources from /root/.sqliterc
count(*) = 0
Packages after
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/005.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = pkg
count(*) = 291
There are no packages without version.
New packages
Details
sqlite> SELECT count(*) from newdb.sys_programs AS a LEFT JOIN main.sys_programs AS b ON a.name = b.name WHERE b.name is NULL;
count(*) = 145
Catalina
Packages before
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/003.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = pkg
count(*) = 141
Packages without version
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/003.db "SELECT count(*) from sys_programs where version = ' ' OR version = ''"
-- Loading resources from /root/.sqliterc
count(*) = 1
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/003.db "SELECT * from sys_programs where version = ' ' OR version = ''"
-- Loading resources from /root/.sqliterc
scan_id = 0
scan_time = 2023/08/28 23:26:08
format = pkg
name = Install Command Line Developer Tools
priority =
section = public.app-category.developer-tools
size = 0
vendor = apple
install_time =
version =
architecture =
multiarch =
source = utilities
description = com.apple.dt.CommandLineTools.installondemand
location = /System/Library/CoreServices/Install Command Line Developer Tools.app/Contents/Info.plist
triaged = 0
cpe =
msu_name =
checksum = afce62543f50806ec448e4cb822141df7ed8269d
item_id = 82d859f209e4b0a96bc0201eebaa98e581f3e51f
Packages after
Total
Details
root@ubuntu-jammy:/var/ossec# sqlite3 queue/db/006.db "SELECT format, count(*) FROM sys_programs group by format;"
-- Loading resources from /root/.sqliterc
format = pkg
count(*) = 281
There are no packages without version.
New packages
Details
sqlite> SELECT count(*) from newdb.sys_programs AS a LEFT JOIN main.sys_programs AS b ON a.name = b.name WHERE b.name is NULL;
count(*) = 141
Exploratory
Environment
MacOS Catalina
Master branch
Number of packages
Using the sysinfo_test_tool five times we get that the time consumed for gathering the inventory packages is between 60 and 70ms.
Expand
Developer branch
Number of packages
Using the sysinfo_test_tool five times we get that the time consumed for gathering is aprox. 1400ms.
Expand
Adding some logs to check what is the most time-consuming function we get. The function getPackagesFromPath when looking inside the receipts directories takes longer than other paths.
Expand
Script
Expand
Packages
Besides the number of packages added as part of this implementation, the following changes are detected.
- Multiarch field as expected after this implementation is NULL. Note: Pypi and NPM packages have multiarch as space string and should be fixed according to https://github.com/wazuh/wazuh/pull/18324
- Source field changes from
utilities
toapplications
- Some packages have a different location (i.e Feedback Assistant)
- There's only one package that was present in master branch and it is not present in the dev branch
Time consumed
After the changes, the package detection takes around 420ms.
The number of packages detected did not change.
Update
The issue is being re-analyzed after many different approaches.
To summarize, the current approach
- Calls a non-documented function to extract the installed pkgs faster. This kind of approaches is hard to debug and mantain.
- Reads the BOM files from the pkgs' receipts and extracts the
.plist
file location. This adds too much logic and failure points managing binary data. Also, sometimes the pkgs are distributed without this file.
A slightly different and simpler implementation is proposed.
The new receipts folders will be scanned and the corresponding plist
files will be read, because that capability is already implemented in the PKGWrapper
. Then, the new tags will be processed and all the information available will be extracted.
PoC
These are the proposed changes https://github.com/wazuh/wazuh/commit/618fe629f4d48b56f1f9ce81e370d40976d6c761
Note: Consider that we should separate the paths to avoid reading plist
files from the previously added folders. For example, using the RCP
enum proposed in the current PR.
The sysinfo_test_tool was run for macOS High Sierra, Monterey, Ventura and Sonoma to verify the output. A common file contains the following fields
vmware@vmwares-iMac wazuh % plutil -p /private/var/db/receipts/com.wazuh.pkg.wazuh-agent.plist
{
"InstallDate" => 2024-04-19 15:10:20 +0000
"InstallPrefixPath" => ""
"InstallProcessName" => "installer"
"PackageFileName" => "agent.pkg"
"PackageIdentifier" => "com.wazuh.pkg.wazuh-agent"
"PackageVersion" => "4.7.3-1.intel64"
}
And this is the resulting output
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-19T15:10:20Z",
"location": "/private/var/db/receipts/com.wazuh.pkg.wazuh-agent.plist",
"multiarch": " ",
"name": "wazuh-agent",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.wazuh.pkg",
"version": "4.7.3-1.intel64"
}
So we can extract PackageVersion
and InstallDate
with no problem.
The package name presents some complications considering the PackageIdentifier
format (reverse domain name format):
- Using it like it is, will result in a presentation not very natural for the user
- Parsing it using the dot as a separator could give us a "vendor" and a name, but this presents some complications (see examples below)
The fields InstallProcessName
and PackageFileName
seem useless here.
We should also define the source
file, currently installer
.
More examples:
Details
vmware@vmwares-iMac wazuh % plutil -p /private/var/db/receipts/com.vmware.tools.macos.pkg.files.plist
{
"InstallDate" => 2024-04-12 14:22:51 +0000
"InstallPrefixPath" => ""
"InstallProcessName" => "Installer"
"PackageFileName" => "files.pkg"
"PackageIdentifier" => "com.vmware.tools.macos.pkg.files"
"PackageVersion" => "12.1.0"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-12T14:22:51Z",
"location": "/private/var/db/receipts/com.vmware.tools.macos.pkg.files.plist",
"multiarch": " ",
"name": "files",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.vmware.tools.macos.pkg",
"version": "12.1.0"
}
root@macVMs-iMac:/Users/macvm/wazuh# plutil -p /private/var/db/receipts/io.osque
{
"InstallDate" => 2023-08-16 03:15:40 +0000
"InstallPrefixPath" => ""
"InstallProcessName" => "installer"
"PackageFileName" => "osquery-5.9.1.pkg"
"PackageIdentifier" => "io.osquery.agent"
"PackageVersion" => "5.9.1"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2023-08-16T03:15:40Z",
"location": "/private/var/db/receipts/io.osquery.agent.plist",
"multiarch": " ",
"name": "agent",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "io.osquery",
"version": "5.9.1"
}
vmware@vmwares-iMac wazuh % plutil -p /private/var/db/receipts/com.microsoft.office.en.quit.pkg.14.0.0.plist
{
"InstallDate" => 2024-04-12 14:22:14 +0000
"InstallPrefixPath" => "tmp"
"InstallProcessName" => "Installer"
"PackageFileName" => "Office2011_en_quit.pkg"
"PackageIdentifier" => "com.microsoft.office.en.quit.pkg.14.0.0"
"PackageVersion" => "14.0.0"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-12T14:22:14Z",
"location": "/private/var/db/receipts/com.microsoft.office.en.quit.pkg.14.0.0.plist",
"multiarch": " ",
"name": "0",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.microsoft.office.en.quit.pkg.14.0",
"version": "14.0.0"
}
vmware@vmwares-iMac wazuh % plutil -p /Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SDK_macOS13.plist
{
"InstallDate" => 2024-04-12 20:02:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "softwareupdated"
"PackageFileName" => "CLTools_macOSNMOS_SDK.pkg"
"PackageIdentifier" => "com.apple.pkg.CLTools_SDK_macOS13"
"PackageVersion" => "14.3.1.0.1.1683849156"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-12T20:02:43Z",
"location": "/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SDK_macOS13.plist",
"multiarch": " ",
"name": "CLTools_SDK_macOS13",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.apple.pkg",
"version": "14.3.1.0.1.1683849156"
}
vmware@vmwares-iMac wazuh % plutil -p /Library/Apple/System/Library/Receipts/com.apple.pkg.XProtectPlistConfigData_10_15.16U4308.plist
{
"InstallDate" => 2024-04-24 02:57:31 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "softwareupdated"
"PackageFileName" => "XProtectPlistConfigData_10_15.pkg"
"PackageGroups" => [
0 => "com.apple.FindSystemFiles.pkg-group"
]
"PackageIdentifier" => "com.apple.pkg.XProtectPlistConfigData_10_15.16U4308"
"PackageVersion" => "2192.1.1713551019"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-24T02:57:31Z",
"location": "/Library/Apple/System/Library/Receipts/com.apple.pkg.XProtectPlistConfigData_10_15.16U4308.plist",
"multiarch": " ",
"name": "16U4308",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.apple.pkg.XProtectPlistConfigData_10_15",
"version": "2192.1.1713551019"
}
This example is interesting, because the new folder contains an .app
name
vmware@vmwares-iMac wazuh % plutil -p /private/var/db/receipts/com.microsoft.package.Microsoft_AutoUpdate.app.plist
{
"InstallDate" => 2024-04-12 15:31:13 +0000
"InstallPrefixPath" => "Library/Application Support/Microsoft/MAU2.0"
"InstallProcessName" => "Installer"
"PackageFileName" => "Office16_all_autoupdate.pkg"
"PackageIdentifier" => "com.microsoft.package.Microsoft_AutoUpdate.app"
"PackageVersion" => "4.69.24031120"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-12T15:31:13Z",
"location": "/private/var/db/receipts/com.microsoft.package.Microsoft_AutoUpdate.app.plist",
"multiarch": " ",
"name": "app",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.microsoft.package.Microsoft_AutoUpdate",
"version": "4.69.24031120"
}
vmware@vmwares-iMac wazuh % plutil -p /private/var/db/receipts/com.microsoft.office.en.rdc.pkg.14.0.0.plist
{
"InstallDate" => 2024-04-12 14:22:16 +0000
"InstallPrefixPath" => "Applications"
"InstallProcessName" => "Installer"
"PackageFileName" => "Office2011_en_rdc.pkg"
"PackageIdentifier" => "com.microsoft.office.en.rdc.pkg.14.0.0"
"PackageVersion" => "14.0.0"
}
{
"architecture": " ",
"description": " ",
"format": "pkg",
"groups": " ",
"install_time": "2024-04-12T14:22:16Z",
"location": "/private/var/db/receipts/com.microsoft.office.en.rdc.pkg.14.0.0.plist",
"multiarch": " ",
"name": "0",
"priority": " ",
"size": 0,
"source": "installer",
"vendor": "com.microsoft.office.en.rdc.pkg.14.0",
"version": "14.0.0"
}
Conclusion
The approach and the details of the implementation will be discussed with @wazuh/devel-core2-div1
Update
The approach described above was reviewed.
It isn't viable to show the packages' names in a reverse DNS format, and extracting the product name from that string produces some errors (like name: 0
).
The possibility to read the InstallHistory.plist
to retrieve the display name was considered, but:
- This is only a list of events, it doesn't contain the currently installed packages
- It is a complex array XML file and currently the sysinfo module is only doing a simple read
Details
The information of every package would have to be compared with this file, resulting in complex logic (sometimes the version is present only in the package's .plist
, etc.)
So finally, the approach tested with vulnerability detector was the following:
- The
vendor
is extracted from the reverse DNS field, considering the second word - The
name
will be the package file name, without the extension and replacing all_
characters - The description will contain the full package identifier (reverse DNS field) to be consistent with the original PKG wrapper
Here are some examples of the packages obtained:
Details
scan_id = 0
scan_time = 2024/05/02 05:11:23
format = pkg
name = XProtectPlistConfigData 10 15
priority =
section =
size = 0
vendor = apple
install_time = 2024-04-24T02:57:31Z
version = 2192.1.1713551019
architecture =
multiarch =
source = receipts
description = com.apple.pkg.XProtectPlistConfigData_10_15.16U4308
location = /Library/Apple/System/Library/Receipts/com.apple.pkg.XProtectPlistConfigData_10_15.16U4308.plist
cpe =
msu_name =
checksum = 66502aeaedf43217be447702580464537e85c8e1
item_id = f578362dae5c591adb83af584fb616f8cf1bd3d1
scan_id = 0
scan_time = 2024/05/02 05:11:21
format = pkg
name = agent
priority =
section =
size = 0
vendor = wazuh
install_time = 2024-04-22T21:34:44Z
version = 4.8.0-1.intel64
architecture =
multiarch =
source = receipts
description = com.wazuh.pkg.wazuh-agent
location = /private/var/db/receipts/com.wazuh.pkg.wazuh-agent.plist
cpe =
msu_name =
checksum = 60b73e20f1b24704b3acf8eb86be5698e405de68
item_id = d837b39d3748ef9a1681c996b0ed82e55867e1b3
scan_id = 0
scan_time = 2024/05/02 05:11:21
format = pkg
name = files
priority =
section =
size = 0
vendor = vmware
install_time = 2024-04-12T14:22:51Z
version = 12.1.0
architecture =
multiarch =
source = receipts
description = com.vmware.tools.macos.pkg.files
location = /private/var/db/receipts/com.vmware.tools.macos.pkg.files.plist
cpe =
msu_name =
checksum = f89b8b559bf1bd9dd4d4f5198c72ee1dfd08c652
item_id = d12d0ad05cbc1aa19e60094e0c8f0666b0577691
scan_id = 0
scan_time = 2024/05/02 05:11:09
format = pkg
name = CLTools macOSLMOS SDK
priority =
section =
size = 0
vendor = apple
install_time = 2024-04-12T20:03:13Z
version = 15.3.0.0.1.1708646388
architecture =
multiarch =
source = receipts
description = com.apple.pkg.CLTools_SDK_macOS13
location = /Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SDK_macOS13.plist
cpe =
msu_name =
checksum = 47b4bf58651ba94b2853300047429c44627f382f
item_id = 3b348b5998f262b52ef4f92c4fa93e8e1bdc60a3
scan_id = 0
scan_time = 2024/05/02 05:11:07
format = pkg
name = MacPorts-2.9.3-component
priority =
section =
size = 0
vendor = macports
install_time = 2024-04-13T02:47:48Z
version = 0.2.9.3.0.0.0.0.0
architecture =
multiarch =
source = receipts
description = org.macports.MacPorts
location = /private/var/db/receipts/org.macports.MacPorts.plist
cpe =
msu_name =
checksum = 8d71b4845720d2f3ad7640d27e37dda82c62fbe3
item_id = 2b585dd67d8c14e7974e16798e227e38b537c502
scan_id = 0
scan_time = 2024/05/02 05:11:37
format = pkg
name = Microsoft Outlook Internal
priority =
section =
size = 0
vendor = Microsoft
install_time = 2024-04-12T15:31:13Z
version = 16.83.24031120
architecture =
multiarch =
source = receipts
description = com.microsoft.package.Microsoft_Outlook.app
location = /private/var/db/receipts/com.microsoft.package.Microsoft_Outlook.app.plist
cpe =
msu_name =
checksum = f4679134ecfb86deda6a3b82ff0fe90177590f04
item_id = fec24b7e49a8803f016fc81f688f0b10b05e8c13
scan_id = 0
scan_time = 2024/05/02 05:11:34
format = pkg
name = XProtectPlistConfigData 10 15
priority =
section =
size = 0
vendor = apple
install_time = 2024-04-12T13:18:48Z
version = 2191.1.1711129719
architecture =
multiarch =
source = receipts
description = com.apple.pkg.XProtectPlistConfigData_10_15.16U4305
location = /Library/Apple/System/Library/Receipts/com.apple.pkg.XProtectPlistConfigData_10_15.16U4305.plist
cpe =
msu_name =
checksum = 413f816efa3ddf747d67232b80d1727679a6aac6
item_id = e9ae6b039a2b23060b17803921efcc35bc2a1cfe
scan_id = 0
scan_time = 2024/05/02 05:11:34
format = pkg
name = Office2011 en word
priority =
section =
size = 0
vendor = microsoft
install_time = 2024-04-12T14:22:15Z
version = 14.0.0
architecture =
multiarch =
source = receipts
description = com.microsoft.office.en.word.pkg.14.0.0
location = /private/var/db/receipts/com.microsoft.office.en.word.pkg.14.0.0.plist
cpe =
msu_name =
checksum = 818139bd562cb2abf1045d740af80b60560a9007
item_id = e515985cc2d222a07d9cbe650660271fb4a35901
scan_id = 0
scan_time = 2024/05/02 05:18:12
format = pkg
name = osquery-5.9.1
priority =
section =
size = 0
vendor = osquery
install_time = 2023-08-16T03:15:40Z
version = 5.9.1
architecture =
multiarch =
source = receipts
description = io.osquery.agent
location = /private/var/db/receipts/io.osquery.agent.plist
cpe =
msu_name =
checksum = 95cd19cc978c7636085afedcd4aa41f0ef24b8f9
item_id = 389bcae6a21391b8b4b159aebe739ca2e2d51d1e
A vulnerability scan was run with the same four macOS agents (using the branch that still doesn't have the vendor changes)
The packages will need a translation because of the incorrect name as expected
2024/05/02 05:11:18 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:335 at handleRequest(): DEBUG: Initiating a vulnerability scan for package 'osquery-5.12.1' (pkg) (osquery) with CVE Numbering Authorities (CNA) 'nvd' on Agent 'macSonoma.local' (ID: '001', Version: 'v4.9.0').
2024/05/02 05:11:18 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:361 at handleRequest(): DEBUG: Vulnerability scan for package 'osquery-5.12.1' on Agent '001' has completed.
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:335 at handleRequest(): DEBUG: Initiating a vulnerability scan for package 'agent' (pkg) (wazuh) with CVE Numbering Authorities (CNA) 'nvd' on Agent 'macSonoma.local' (ID: '001', Version: 'v4.9.0').
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:146 at operator()(): DEBUG: Scanning package - 'agent' (Installed Version: 4.8.0-1.intel64, Security Vulnerability: CVE-2008-1357). Identified vulnerability: Version: 4.0. Required Version Threshold: . Required Version Threshold (or Equal): .
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] versionMatcher.hpp:151 at createVersionObject(): DEBUG: Error creating VersionObject (CalVer). Version string doesn't match the specified type. Version string: 4.8.0-1.intel64
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] versionMatcher.hpp:162 at createVersionObject(): DEBUG: Error creating VersionObject (PEP440). Version string doesn't match the specified type. Version string: 4.8.0-1.intel64
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] versionMatcher.hpp:173 at createVersionObject(): DEBUG: Error creating VersionObject (MajorMinor). Version string doesn't match the specified type. Version string: 4.8.0-1.intel64
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] versionMatcher.hpp:151 at createVersionObject(): DEBUG: Error creating VersionObject (CalVer). Version string doesn't match the specified type. Version string: 4.0
2024/05/02 05:11:18 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:335 at handleRequest(): DEBUG: Initiating a vulnerability scan for package 'macports-2.9.3-component' (pkg) (macports) with CVE Numbering Authorities (CNA) 'nvd' on Agent 'macVentura.local' (ID: '002', Version: 'v4.8.0').
2024/05/02 05:11:18 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:361 at handleRequest(): DEBUG: Vulnerability scan for package 'macports-2.9.3-component' on Agent '002' has completed.
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:335 at handleRequest(): DEBUG: Initiating a vulnerability scan for package 'microsoft word internal' (pkg) (Microsoft) with CVE Numbering Authorities (CNA) 'nvd' on Agent 'macVentura.local' (ID: '002', Version: 'v4.8.0').
2024/05/02 05:11:27 wazuh-modulesd:vulnerability-scanner[42591] packageScanner.hpp:361 at handleRequest(): DEBUG: Vulnerability scan for package 'microsoft word internal' on Agent '002' has completed.
Thanks @pereyra-m for the investigation!
Issue blocked - Awaiting for definitions from management team
The current proposal is simple to implement, as it works with the current tools available to the agents. But the matching process on the vulnerability scanner will be complicated, as the package names won't align with the ones provided by the NVD
Current proposal
- The vendor is extracted from the reverse DNS field, considering the second word
- The name will be the package file name, without the extension and replacing all _ characters
- The description will contain the full package identifier (reverse DNS field) to be consistent with the original PKG wrapper
- We generate the translations for every package
Possible Solution (not tested)
A possible solution will be to add a proper XML parser on the agents (but this will prove difficult for compatibility reasons). The implementation won't be easy though, as described here (use of InstallHistory.plist)
We will revisit this in the future, as the current implementation does not fit with the current agent state.
Update
(10/10/2024) Researching and consulting the team on all the performed work and investigations related to this topic. We need to set a scope for this issue since the are many points to take into account. (11/10/2024) This comment, pretends to analyze all the investigations and developments carried about in this issue and the implications the different approaches have.
To understand the context of the presented problem, we have to remember that the root reason seems to be the lack of a well-established standard regarding the .pkg
files in the Mac OS systems. This situation leads the different developers to create the installable packages under their perspective making extracting the installed packages' information hard.
Different options have been studied:
Option 1 .bom
files
Details
When a .pkg
package, such as the wazuh-agent, is installed, a .bom
file is also deployed. This file contains information related to the files that a package contains. This kind of file can not be directly read as plain text, the lsbom
tool must be used to read their content. The following test has been performed to test the content of the .bom
files:
vagrant@idr-1657-sonoma-14-6719 Desktop % sw_vers
ProductName: macOS
ProductVersion: 14.4.1
BuildVersion: 23E224
vagrant@idr-1657-sonoma-14-6719 Desktop % sudo insataller pkg wazuh-agent-4.9.0-1.intel64.pkg -target /
...
vagrant@idr-1657-sonoma-14-6719 Desktop % find / -name "*wazuh*.bom" 2>/dev/null | while read file; do file "$file"; done
/System/Volumes/Data/private/var/db/receipts/com.wazuh.pkg.wazuh-agent.bom: Mac OS X bill of materials (BOM) file
vagrant@idr-1657-sonoma-14-6719 Desktop % lsbom /System/Volumes/Data/private/var/db/receipts/com.wazuh.pkg.wazuh-agent.bom
. 40755 0/0
./Library 40755 0/0
./Library/Ossec 40750 0/0
./Library/Ossec/.ssh 40700 0/0
./Library/Ossec/active-response 40750 0/0
./Library/Ossec/active-response/bin 40750 0/0
./Library/Ossec/active-response/bin/default-firewall-drop 100750 0/0 45104 1638564222
./Library/Ossec/active-response/bin/disable-account 100750 0/0 40864 175171903
...
The .bom
file in our case contains all the installed files by the selected package and information related to their ownership, permissions, size and timestamp. But it not contains a reference to a .plist
file.
For example, if we list more .bom
files, it's observed that not all the packages have a .plist
file while others have more than one.
vagrant@idr-1657-sonoma-14-6719 Desktop % find / -name "*.bom" 2>/dev/null | while read file; do file "$file"; done
/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SDK_macOS13.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_Executables.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.files.data-template.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SDK_macOS14.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.pkg.MRTConfigData_10_15.16U4211.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_SwiftBackDeploy.bom: Mac OS X bill of materials (BOM) file
/Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_macOS_SDK.bom: Mac OS X bill of materials (BOM) file
^C
No plist
file:
vagrant@idr-1657-sonoma-14-6719 Desktop % lsbom -s /Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_macOS_SDK.bom
.
./Library
./Library/Developer
./Library/Developer/CommandLineTools
./Library/Developer/CommandLineTools/SDKs
./Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
Multiple .plist
files
vagrant@idr-1657-sonoma-14-6719 Desktop % lsbom -s /Library/Apple/System/Library/Receipts/com.apple.pkg.CLTools_Executables.bom | grep "plist"
./Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Info.plist
./Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/Info.plist
./Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/Python.app/Contents/version.plist
./Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/Resources/version.plist
./Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/plistlib.py
./Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/Info.plist
./Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/Resources/version.plist
./Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/XPCServices/RootDebuggingXPCService.xpc/Contents/Info.plist
./Library/Developer/CommandLineTools/Library/PrivateFrameworks/LLDB.framework/Versions/A/XPCServices/RootDebuggingXPCService.xpc/Contents/version.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitd.framework/Versions/A/Resources/Info.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitd.framework/Versions/A/Resources/version.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitd.framework/Versions/A/XPCServices/SourceKitService.xpc/Contents/Info.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitd.framework/Versions/A/XPCServices/SourceKitService.xpc/Contents/version.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitdInProc.framework/Versions/A/Resources/Info.plist
./Library/Developer/CommandLineTools/usr/lib/sourcekitdInProc.framework/Versions/A/Resources/version.plist
./Library/Developer/CommandLineTools/usr/lib/swift/pm/llbuild/llbuild.framework/Versions/A/Resources/Info.plist
./Library/Developer/CommandLineTools/usr/lib/swift/pm/llbuild/llbuild.framework/Versions/A/Resources/version.plist
Also, the content of this kind of file is not consistent and may vary between binary content or plain text. The implementation of these options is also not desired, since we should rely on a non-documented API which seems to be deprecated if we want to avoid finding all the .bom
files. Related information in this comment and in the mac OS API documentation.
Summary
Trying to retrieve package information based on the .plist
files is not a good option since the retrieved information is not clear. This adds too much logic and failure points managing binary data and we still should deal with packages without this type of file.
Option 2 receipts
folders 👈
Details
Another possible approach is the one studied in this PoC. Although not all the .plist files are listed in the /private/var/db/receipts
folder it seem to contain multiple ones, and all their content is readable as it can be seen:
vagrant@idr-1657-sonoma-14-6719 Desktop % find /private/var/db/receipts -name "*.plist" 2>/dev/null | while read file; do echo $file; plutil -p "$file"; done
/private/var/db/receipts/com.parallels.pkg.guestostools.sf.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools SharedFolders.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.sf"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.hosttime.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools HostTime.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.hosttime"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.coherence.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools Coherence.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.coherence"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.ts.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools TimeSync.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.ts"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.video.plist
{
"InstallDate" => 2024-04-25 15:38:42 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools Video 10.9.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.video"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.copypaste.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools CopyPaste.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.copypaste"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.dragdrop.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools DragDrop.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.dragdrop"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.wazuh.pkg.wazuh-agent.plist
{
"InstallDate" => 2024-10-11 09:02:05 +0000
"InstallPrefixPath" => ""
"InstallProcessName" => "installer"
"PackageFileName" => "agent.pkg"
"PackageIdentifier" => "com.wazuh.pkg.wazuh-agent"
"PackageVersion" => "wazuh-agent-4.9.0-1.intel64"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.ut.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools Utilities.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.ut"
"PackageVersion" => "19.3.0.54924"
}
/private/var/db/receipts/com.parallels.pkg.guestostools.iagent.plist
{
"InstallDate" => 2024-04-25 15:38:43 +0000
"InstallPrefixPath" => "/"
"InstallProcessName" => "installer"
"PackageFileName" => "Parallels Tools InstallationAgent.pkg"
"PackageIdentifier" => "com.parallels.pkg.guestostools.iagent"
"PackageVersion" => "19.3.0.54924"
}
Summary This approach makes the information more easily accessed, but still we have to deal with two main problems:
- Not all
.pkg
files are ensured to be tracked - The extracted data, although it's consistent between read files, is poor and lacks relevant information for us such a clear vendor, size, or even the package name.
To deal with it we should get the package missing data from the PackageIdentifier
field, which can lead to weird cases since not all the PackageIdentifier
can be treated equally.
The more advanced development following this approach is the performed by @pereyra-m, who has helped a lot to understand the issue status and research, placed in this branch. The packages' data is read using the receipts folders' content, and the extracted information is sanitized manually to try to get coherent data. Result can be observed here.
Option 3 InstallHistory.plist
file
Details
Other option would consist in parsing the /Library/Receipts/InstallHistory.plist
.
Content of /Library/Receipts/InstallHistory.plist
vagrant@idr-1657-sonoma-14-6719 Desktop % cat /Library/Receipts/InstallHistory.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>date</key>
<date>2024-04-25T14:23:16Z</date>
<key>displayName</key>
<string>macOS 13.6.6</string>
<key>displayVersion</key>
<string>13.6.6</string>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>contentType</key>
<string>config-data</string>
<key>date</key>
<date>2024-04-25T14:38:30Z</date>
<key>displayName</key>
<string>XProtectPlistConfigData</string>
<key>displayVersion</key>
<string>2192</string>
<key>packageIdentifiers</key>
<array>
<string>com.apple.pkg.XProtectPlistConfigData_10_15.16U4308</string>
</array>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>contentType</key>
<string>config-data</string>
<key>date</key>
<date>2024-04-25T14:38:33Z</date>
<key>displayName</key>
<string>MRTConfigData</string>
<key>displayVersion</key>
<string>1.93</string>
<key>packageIdentifiers</key>
<array>
<string>com.apple.pkg.MRTConfigData_10_15.16U4211</string>
</array>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>contentType</key>
<string>config-data</string>
<key>date</key>
<date>2024-04-25T14:38:37Z</date>
<key>displayName</key>
<string>XProtectPayloads</string>
<key>displayVersion</key>
<string>131</string>
<key>packageIdentifiers</key>
<array>
<string>com.apple.pkg.XProtectPayloads_10_15.16U4307</string>
</array>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>date</key>
<date>2024-04-25T15:39:04Z</date>
<key>displayName</key>
<string>Parallels Tools for Mac</string>
<key>displayVersion</key>
<string></string>
<key>packageIdentifiers</key>
<array>
<string>com.parallels.pkg.guestostools.video</string>
<string>com.parallels.pkg.guestostools.hosttime</string>
<string>com.parallels.pkg.guestostools.sf</string>
<string>com.parallels.pkg.guestostools.ts</string>
<string>com.parallels.pkg.guestostools.ut</string>
<string>com.parallels.pkg.guestostools.coherence</string>
<string>com.parallels.pkg.guestostools.iagent</string>
<string>com.parallels.pkg.guestostools.copypaste</string>
<string>com.parallels.pkg.guestostools.dragdrop</string>
</array>
<key>processName</key>
<string>installer</string>
</dict>
<dict>
<key>date</key>
<date>2024-04-29T17:34:32Z</date>
<key>displayName</key>
<string>macOS 14.4.1</string>
<key>displayVersion</key>
<string>14.4.1</string>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>contentType</key>
<string>config-data</string>
<key>date</key>
<date>2024-04-29T17:38:25Z</date>
<key>displayName</key>
<string>MRTConfigData</string>
<key>displayVersion</key>
<string>1.93</string>
<key>packageIdentifiers</key>
<array>
<string>com.apple.pkg.MRTConfigData_10_15.16U4211</string>
</array>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>date</key>
<date>2024-10-10T14:11:43Z</date>
<key>displayName</key>
<string>Command Line Tools for Xcode</string>
<key>displayVersion</key>
<string>15.3</string>
<key>packageIdentifiers</key>
<array>
<string>com.apple.pkg.CLTools_Executables</string>
<string>com.apple.pkg.CLTools_SDK_macOS14</string>
<string>com.apple.pkg.CLTools_SDK_macOS13</string>
<string>com.apple.pkg.CLTools_macOS_SDK</string>
<string>com.apple.pkg.CLTools_SwiftBackDeploy</string>
</array>
<key>processName</key>
<string>softwareupdated</string>
</dict>
<dict>
<key>date</key>
<date>2024-10-11T09:02:05Z</date>
<key>displayName</key>
<string>Wazuh Agent</string>
<key>displayVersion</key>
<string></string>
<key>packageIdentifiers</key>
<array>
<string>com.wazuh.pkg.wazuh-agent</string>
</array>
<key>processName</key>
<string>installer</string>
</dict>
</array>
</plist>
The content of this file could help us to at least, get a clear package name since the displayName
key seems to reference this field. But we still should use a more complex data parsing mechanism and we still would not have solved the problem related to the lack of installed packages reference. This thread reports that this inspected file does not reference all the installed packages.
We should also deal with the lack of information related to the packages, which is still a problem for us, having the data that VD manages.