wazuh icon indicating copy to clipboard operation
wazuh copied to clipboard

Enable detect installed packages on MacOS

Open tdrauncieal opened this issue 2 years ago • 9 comments

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 image

DoD

  • [ ] Add changes to include .pkgs files in software relevant.
  • [ ] Add UT for new code added

tdrauncieal avatar Dec 26 '22 17:12 tdrauncieal

Hey team! Please add your planning poker estimate with Zenhub @MiguelazoDS @tdrauncieal

pereyra-m avatar Jan 12 '23 20:01 pereyra-m

Please add your planning poker estimate with Zenhub @Dwordcito

pereyra-m avatar Jan 12 '23 20:01 pereyra-m

Quick exploratory :green_circle:

Packages number before and after the implementation

Expand

image image image

Packages before

before_dump.txt

Packages after

after_dump.txt

Diff analysis

There's only one package before that is not included after due to the missing version

Expand

image

Several location information has changed after the implementation.

MiguelazoDS avatar Aug 28 '23 15:08 MiguelazoDS

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

dbs.zip

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



diff1.txt

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



diff2.txt

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


diff3.txt

pereyra-m avatar Aug 29 '23 02:08 pereyra-m

Exploratory

Environment

MacOS Catalina

Master branch

Number of packages

image

Using the sysinfo_test_tool five times we get that the time consumed for gathering the inventory packages is between 60 and 70ms.

Expand

2023-10-09_10-49

Developer branch

Number of packages

image

Using the sysinfo_test_tool five times we get that the time consumed for gathering is aprox. 1400ms.

Expand

2023-10-09_11-07

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

2023-10-09_11-45

Script

Expand

2023-10-09_11-46

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 to applications
  • 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 image

MiguelazoDS avatar Oct 09 '23 16:10 MiguelazoDS

Time consumed

After the changes, the package detection takes around 420ms.

image

The number of packages detected did not change.

image

MiguelazoDS avatar Oct 12 '23 12:10 MiguelazoDS

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

pereyra-m avatar Apr 30 '24 15:04 pereyra-m

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

2024-05-02_02-43

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)

ossec_basic_log.zip

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.

pereyra-m avatar May 02 '24 05:05 pereyra-m

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)

sebasfalcone avatar May 13 '24 14:05 sebasfalcone

We will revisit this in the future, as the current implementation does not fit with the current agent state.

gdiazlo avatar Jun 10 '24 14:06 gdiazlo

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.

mjcr99 avatar Oct 10 '24 15:10 mjcr99