How Jamf Credentials Get Found and What Happens Next
Mac endpoints in enterprise environments tend to land with developers, cloud admins, and other high-privilege users. That makes them targets. Jamf Pro is the default MDM in most of those environments, and IT admins set it up once and rarely monitor it afterward.
In September or October of last year, Cain and Mayer found Jamf API credentials sitting in a compromised user’s shell history. From that single find, they moved laterally across an entire Mac fleet and executed code undetected against a major EDR for six to seven weeks. In follow-on assessments they started hunting for Jamf credentials in git commits and S3 buckets.
“we went months undetected against bigname edr vendors uh protecting customer environments uh moving across Mac OS” — Lance Cain
Jamf Permission Models and the Attack Graph
Jamf Pro exposes three permission layers: CRUD on JSS objects (managed systems, policies, scripts, user accounts), binary allow/deny for JSS actions (flushing logs, resetting passwords), and read/update for JSS settings (certificates, check-in intervals). Every JSS object also has a REST API endpoint, so any permission granted to an account or API client is scriptable.
Real tenant graphs are far messier than documented. Admins add new groups and API clients over time without updating their records. One favorite attack path: compromise a site admin or API client, enumerate which Mac devices privileged accounts log into, match emails back to tenant admins, then target those machines for further access. As a colleague put it, “anything stealthy until someone’s looking for it.”
Privilege Escalation Inside a Jamf Tenant
Two paths to higher Jamf privileges. First: if a compromised account carries create or update account permissions, those are always tenant-wide. One PUT request creates a new local account with arbitrary privileges, or resets the password on an existing admin account. Third-party apps using Jamf local accounts for group management almost always carry both permissions together.
In the Eve CLI privilege escalation demo (14:18), a Terraform service account with ID 13 carried create/update account permissions. A single update request using Eve’s template promoted it to full administrator. Second path: if account permissions aren’t available, create an API role with whatever permissions are needed, attach it to a new API client, then authenticate as that client to obtain a bearer token with those rights.
Three Code Execution Primitives Built Into Jamf
Three built-in execution primitives, each with different permission requirements. First: create a script object (any shebang, runs as root) and a policy that references it. Jamf policy checks in every 15 to 20 minutes. The Eve UI script-and-policy execution demo (24:12) triggered a popup on the next check-in. Second: a run-command tag inside policy XML delivers a shell one-liner with no script object required. Third: extension attributes embed a script that runs at jamf recon every 24 hours on every managed machine. The extension attribute execution demo (29:58) displayed: “Imagine this is a crypto miner. Extension attributes are a great way to get your Monero balance up relatively quickly.”
Defensive Recommendations for Jamf Tenants
Every API credential the team found was long-lived. Time-gating privileged credentials would have neutralized most of the access, since the team picked them up well after they were created. JSS access logs and Tomcat access logs show who hit which endpoints. Change management logs show object state at modification time, but they are unstructured text and don’t diff the before/after, so you need to snapshot previous state yourself to see what changed.
For network controls: firewall Jamf API endpoints so only bastion hosts can call them. Cloud-hosted Jamf tenants can request allow-listing through Jamf support. The Jamf team proactively contacted the researchers before this talk and worked with them on the recommendations.
Q&A
Have you used kernel extensions or similar Jamf primitives for red team activity? Not yet in the current tooling, but kernel extensions, package deployments, and profiles are on the roadmap for JHound as additional attack graph edges. ▶ 35:02
Notable Quotes
anything stealthy until someone’s looking for it Lance Cain (quoting colleague Lee) · ▶ 10:35
we went months undetected against bigname edr vendors uh protecting customer environments uh moving across Mac OS Lance Cain · ▶ 4:27
Imagine this is a crypto miner. Extension attributes are a great way to get your Monero balance up relatively quickly. Dan Mayer · ▶ 30:50
Key Takeaways
- Jamf API credentials found in shell history or S3 buckets enable fleet-wide lateral movement and months of undetected access.
- A single compromised account with create/update permissions can self-grant full Jamf admin rights in one API call.
- Three built-in execution primitives — script+policy, run-command tag, extension attributes — each require different permission sets to block.