Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancement idea: Wildcards in SigningID rules #1163

Open
p-harrison opened this issue Aug 25, 2023 · 7 comments
Open

Enhancement idea: Wildcards in SigningID rules #1163

p-harrison opened this issue Aug 25, 2023 · 7 comments

Comments

@p-harrison
Copy link
Contributor

I wonder would it be feasible to support wildcards in SigningID rules? The usecase would be where you want to allow only specific applications from a developer, so a TeamID rule would be too broad, but the application contains multiple binaries. A Certificate rule might work, but again could be used by the developer across multiple applications, or conversely there might be multiple certificates used in a single application.

For example these rules would permit multiple binaries with a single rule, leading to a tidier more manageable rules database -

KL8N8XSYF4:com.brave.Browser*
   com.brave.Browser
   com.brave.Browser.helper
   com.brave.Browser.helper.renderer
   com.brave.Browser.framework
   com.brave.Browser.helper.plugin
EQHXZ8M8AV:com.google.Chrome.*
   com.google.Chrome.helper
   com.google.Chrome.helper.renderer
   com.google.Chrome.framework.AlertNotificationService
   com.google.Chrome.helper
   com.google.Chrome.framework
   com.google.Chrome
   com.google.Chrome.helper.plugin
VB5E2TV963:com.oracle.java*
   com.oracle.java.8u311.java
   com.oracle.java.Java-Updater
   com.oracle.java.11.0.17.jdk
   com.oracle.java.11.0.17.java
   com.oracle.java.11.0.17.javac
   com.oracle.java.8u371.java
@mlw
Copy link
Member

mlw commented Aug 25, 2023

I have mixed feelings about this... On the surface I think this is a reasonable request, but the implementation has some downsides.

Wildcard rules would definitely help from a standpoint of reducing overall policy size and likely improving readability of a policy. But I don't think they effectively reduce the amount of work required by a policy writer.

My assumption is that a policy writer would need to first enumerate the binaries contained in a bundle and collect the signing IDs and verify that they do indeed want to create policy for each of those binaries. Once the SIDs are collected, they would then need to find some common prefix(es) that suited their needs. Since bundles can obviously change over time, with binaries added/removed, wildcards remain flexible to potentially reduce toil maintaining policy, but with tradeoffs.

I think there are two potential goals of wildcards:

  1. Wanting to be selective about the items within a bundle to which a policy applies
    • Wildcards seem like a bad fit here because they would potentially be too permissive with future bundle changes
  2. Applying to a bundle, and not necessarily caring about future changes
    • This feels more reasonable and has had been discussed in the past (Add a Bundle ID rule type ? #828). We had concerns in that issue since overall task of identifying which bundle a binary lies within is complex, flaky, and time consuming.

Perhaps some limited wildcard support would effectively add a "BundleID rule" capability without having to rely on bundle identification? However the policy would still be susceptible to bundle changes that add binaries with non-matching wildcards and policy writers would still be required to perform this maintenance.

@p-harrison, I had a couple followup questions:

  1. Is what you're trying to do really more akin to a BundleID-style rule? Or was there some other use case you had ion mind?

  2. From the examples given, it seems like being able to state that a signing ID is a prefix would be sufficient, but I'm curious if you have any more complex examples/use cases? Prefixes would be easiest, safest, and most-performant route. But if we needed to support more powerful regexes, we could maybe opt for RE2 to allow more control and still provide safety compared to the shenanigans that can be done with full regex support.

@p-harrison
Copy link
Contributor Author

Thanks for the quick response Matt. All your points are well made! In answer to your follow-up questions -

  1. Yeah a BundleID-style rule would be more effective, given SigningID naming conventions are not always consistent and dependencies in the bundle might legitimately have completely separate SigningID roots. But as you say I think prefix SigningIDs could act as BundleID-lite rules, given the concerns with implementing the BundleID rule type.
  2. Yes sorry I should have stated that. I don't think wildcards need to be supported in any position in the SigningID, or indeed multiple wildcards or anything complex like that. You could support the wildcard character only in the last position of the SigningID.

@mlw
Copy link
Member

mlw commented Aug 25, 2023

Appreciate the responses!

I believe that:

  1. Presenting this as a BundleID-style use case makes a lot of sense (tho with the important caveats about future changes stated previously).
  2. Only allowing prefixes makes this more tenable

We're going to noodle on this a bit and will discuss more broadly when some folks get back from vacations.

@p-harrison
Copy link
Contributor Author

One point that may not be clear from my examples above - it would be great if the 'prefix' did not necessarily have to end at a full stop within a SigningID. I imagine you're just doing a string compare so perhaps this does not need to be stated...

JAMF is a good example -

com.jamf*
   com.jamf.management.JamfProCommService
   com.jamf.management.jamfAAD
   com.jamfsoftware.jamf

@p-harrison
Copy link
Contributor Author

Hey guys, I was just adding some SigningID rules for Firefox and it reminded me of this discussion. Wonder if you guys had any more thoughts on the viability of it?

@mlw
Copy link
Member

mlw commented Apr 24, 2024

I don't think I've been very sold on the idea yet. Given an admin would still need to enumerate binaries within a bundle and determine some common prefix manually, I don't think there is much of a time savings. I'd also have some concerns around rules applying automatically to new binaries in future versions of the bundle, but I suppose that's a risk an admin could take....

I think the largest problems are technical - I see a few issues that would need to be solved.

First, the current setup for doing a rule match requires a single query. For prefix matching, we'd have to figure out a good approach to do partial matching based on some given signing ID and presumably some number of various prefixes that could exist in the DB. We could maybe scope things to a given TeamID to help limit the number of potential matches, but we'd still need to iterate prefix results and match against the SID being authorized. We'd also have to decide how to handle multiple matches (e.g., longest rule match wins? Only allow one prefix rule per TID?).

Second, given the above, we'd either need multiple queries, or we'd have to change the query to return potentially more than one row. Either way, we'd then need to perform precedence ordering in code. Right now we solely rely on our query to enforce our precedence. But with multiple rows/queries, we'd have to replicate this logic, which would require a whole slew of new tests.

Third, I think we'd need some way to append extra metadata to a rule to indicate that the identifier is a prefix type. Just using * at the end is insufficient since it's technically a valid character in a signing ID. This would also need to be indicated in the DB for lookups. So this would likely require an expansion of keys supported in the rule download phase of the sync protocol, as well as adoption by sync servers to support. Perhaps there is some in-band way to do this, but I'm not sure I've had a good idea here yet.

All of these are fairly non-trivial and would require a bit of design to make sure edge cases are accounted for. Given the amount of effort to get something like this done, as well as the payoff not seemingly all that much (maybe a bit fewer rules per bundle), this is likely not going to be prioritized any time soon.

@pmarkowsky
Copy link
Contributor

Another idea to get something similar to bundle ID rules is that you could use a combination of bundle hash and signing ID in the Events to figure out what rules to generate. We do include the Signing IDs up to the server when a block event occurs, these events also have the bundle hash, which is derived from the binaries in the bundle.

In theory you could use this with your sync server to identify all of the related signing IDs in a bundle and then send the corresponding singing ID allow rules to run the bundle.

This is obviously more practical if you can get push notifications, which is still hard outside of Google's deployment.

sequenceDiagram
santa ->> "sync service": Upload Blocked event
santa ->> "sync service": Upload Bundle Events with Signing IDs
"sync service" ->> "sync service": Generate signing ID allow rules for bundle
"sync service" -->> santa: Allow rules for bundle

Alternatively to get the list of Signing IDs in a bundle a priori you can use find, xargs and santactl e.g.

$  find /Applications/Santa.app -type f -perm +111 | xargs santactl fileinfo --key "Signing ID"                         
com.google.santa.metricservice
com.google.santa.syncservice
com.google.santa
com.google.santa.bundleservice
com.google.santa.ctl
com.google.santa.daemon

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants