Chris Long

3 minute read


Upon reading Mandiant’s “North Korea Leverages SaaS Provider in a Targeted Supply Chain Attack”, one of the artifacts that stood out to me was the usage of XProtect’s Behavior Service DB. Until now, I had assumed all XProtect detections were signature based, but it sounds like Apple may be testing some behavioral-based rules to flag suspicious process executions in newer versions of MacOS.

Examining the DB locally using sqlite3

If you’d like to take a look at the DB on your own system, you can simply run sudo sqlite3 /var/protected/xprotect/XPdb:

SQLite version 3.39.5 2022-10-14 20:58:05
Enter ".help" for usage hints.
sqlite> .mode line
sqlite> select * from events;
                      id = 298
           violated_rule = BastionRule-1
               exec_path = /usr/sbin/lsof
             exec_cdhash = 62c8e638c90f2fe3672d89cb134f37a010561e29
         exec_signing_id =
            exec_team_id =
             exec_sha256 = f8a6987f682de1174ece536deaa9da730b5103ef4af086a45c9c533068296709
       exec_is_notarized = 0
        responsible_path = /Users/user/Library/Google/GoogleSoftwareUpdate/GoogleSoftwareUpdate.bundle/Contents/Helpers/
      responsible_cdhash = 8c87d6eb2d85e5b18d68088ebc7d1a36d28c1930
  responsible_signing_id =
     responsible_team_id = EQHXZ8M8AV
      responsible_sha256 = e89dbda1bbdcfca7a9d559fb92bf0d7d9d275a0ad74a9e27098329dd766e3d34
responsible_is_notarized = 1
                reported = 1
            profile_hash = 5998098849390627319
                      dt = 2023-06-30 06:34:28

From this entry, we can see XProtect flagged the GoogleSoftwareUpdateAgent binary (signed with team_id EQHXZ8M8AV) because it executed the /usr/sbin/lsof binary. Something about this execution caused it to trigger the BastionRule-1 rule. I have a bunch of entries in my DB, and all of them appear to be false positives, but it’s quite clear how this could be a useful place to check for suspicious process executions. It clearly paid off for Mandiant!

Examining the XPDB at scale

One of the lesser known features of osquery is called Automatic Table Creation or “ATC” for short. Kolide has a pretty good write up on what the feature is and how to use it. Assuming you’re using some sort of osquery management tool like FleetDM or Kolide, you’ll be able to leverage ATC to query the XPDB on all of your hosts.

I personally use the open source version of FleetDM, so I added an entry to my config that looks like this:

              - id
              - violated_rule
              - exec_path
              - exec_cdhash
              - exec_signing_id
              - exec_team_id
              - exec_sha256
              - exec_is_notarized
              - responsible_path
              - responsible_cdhash
              - responsible_signing_id
              - responsible_team_id
              - responsible_sha256
              - responsible_is_notarized
              - reported
              - profile_hash
              - dt
              path: /var/protected/xprotect/XPdb
              query: SELECT * FROM events WHERE responsible_team_id NOT IN (<list of team_ids I trust>)
                AND exec_team_id NOT IN (<list of team_ids I trust>)

If you’re less trusting of certain organizations than I am, you could of course just SELECT * without any WHERE clauses. After adding this to the config, xpdb is exposed as a table like any other osquery table. I set up a scheduled query that basically runs SELECT * FROM xpdb and logs any additions (ignores removals) to the database on all my hosts across the fleet.

Other ATC Considerations

There’s quite a bit of valuable information stored in SQLite databases on MacOS, so consider monitoring things like your users’ TCC system and user entries, quarantine events, and maybe some application settings that are stored in sqlite databases.

comments powered by Disqus