Approved by Somebody Else: Finding the Actor Behind a sub Claim
The challenge
A 240,000 euro refund was approved at 03:11 on a Sunday. The payments audit trail names Dele Okonkwo, finance director, who was asleep in another time zone and whose laptop was in a hotel safe. His account was not compromised: there is no login at 03:11, no new device, no failed multi-factor prompt, nothing. The audit trail is telling the truth about the token it was given. This is that token, exactly as it arrived at the payments API. Somebody else is in it. Name them.
What you'll learn
- Read every claim in a JWT payload, including nested objects
- Distinguish the subject of a token from the actor using it
- Recognise amr values as evidence of how a session was created
- Explain why an audit trail that logs only sub misattributes delegated actions
- Describe the controls that a misattributed identity silently bypasses
Skills tested
Prerequisites
- What a JWT is and that its payload is encoded, not encrypted
How it works
A token normally answers one question: who is this. Delegation adds a second, and the two answers are not the same. sub is the subject, the identity whose permissions the request will run with. act is the actor, the identity that is genuinely driving it. Support consoles, on-call break-glass tools and automated agents all produce tokens with both, and the format is standardised for exactly that reason.
Nothing about this is an attack on its own. The token is correctly signed, the payments API validates it correctly, and the refund goes through with the director's authority because that is what delegation is for. The failure is downstream: an audit trail that records sub and nothing else turns a support agent's action into the director's action, permanently and convincingly.
What that misattribution costs is every control keyed to identity. Second approver rules, out-of-hours review, anomaly detection on privileged accounts and the investigation itself all look at a name. Give them the wrong name and they all agree that nothing unusual happened, which is exactly what the Harbourline team found when they went looking.
Common mistakes
- Answering d.okonkwo. That is
sub, the authority being borrowed. The audit trail already said that, and it is what made the incident confusing. - Looking for a forged signature. The token is valid. Assuming every token puzzle is a forgery is the habit this one is built to break.
- Stopping at the claims you recognise.
iss,aud,sub,expare all ordinary. The answer is in the claim that is an object. - Answering console.harbourline.example. That is where the delegation came from, not who performed it.
How to defend against it
Log both identities, and treat delegated authority as its own privilege level.
- Record
act.subalongsidesubin every audit event, and render it in the interface people actually read. If the field is missing from the log schema, it will be missing from the investigation. - Do not let delegation inherit the full permission set. A support agent acting as a director should be able to read and reproduce, not approve a payment.
- Cap value and scope on delegated sessions, require the subject to consent per session, and expire them in minutes.
- Alert on delegated sessions that perform privileged actions out of hours. This refund would have fired on both conditions.