Unit 1: Encoding, hashing and encryption · Lesson 5 of 5 · 22 min

Case file: the HAR file that held a login

Find the live session cookie and token inside a customer's HAR file, read the token without any key, and send back a clean copy.

mission

You are
You are on Fernhill's support engineering team.
Situation
A customer attached a HAR file to support case 48213 so the team can debug a failed shipment edit. Policy says attachments are checked before anyone opens them.
Goal
Find every live credential in the file and produce a sanitised copy.
Hand in
A clean HAR and a list of what you removed.

case file

Okta support system breach

Okta · 2023

Between 28 September and 17 October 2023 an attacker used a service account in Okta's support case system to download files that 134 customers had attached to support cases. Some were HAR files containing session tokens, which the attacker used to hijack sessions at five customers.

What went wrong

A service account password was saved in an employee's personal browser profile, and HAR files uploaded by customers still held live session tokens.

What would have stopped it

  • Sanitise HAR files, stripping cookies and tokens, before upload
  • Keep service account credentials in a vault, never in a browser profile
  • Bind admin sessions to device or network context and re-authenticate on change

What defenders could have seen

  • A service account downloading support attachments at unusual volume
  • The same admin session token used from a new IP address

sourcessec.okta.comthehackernews.com

What rides along in a HAR file

01

See what was recorded

A HAR file is JSON. jq reads it like any other structured log.

learner@crypto-lab
cat README.txt
Attached by a customer to support case 48213: 'Shipment edit fails with 409, HAR attached.'
The support portal keeps attachments for 90 days.
jq '.log.entries | length' support-case-48213.har
7
jq -r '.log.entries[] | "\(.request.method) \(.request.url)"' support-case-48213.har
POST https://portal.fernhill.example/login
GET https://portal.fernhill.example/dashboard
GET https://portal.fernhill.example/api/v2/shipments?status=held
GET https://portal.fernhill.example/api/v2/shipments/88213
PATCH https://portal.fernhill.example/api/v2/shipments/88213
GET https://portal.fernhill.example/api/v2/users/me
GET https://portal.fernhill.example/static/app.js

you should see Seven requests, including the login and four API calls.

02

Find the credentials in the headers

learner@crypto-lab
jq -r '.log.entries[].request.headers[] | select(.name=="Cookie" or .name=="Authorization") | .name' support-case-48213.har | sort | uniq -c
      4 Authorization
      5 Cookie
jq -r '.log.entries[1].request.headers[] | select(.name=="Cookie") | .value' support-case-48213.har
fh_session=t8FJxtr68V9VptIzcDFoY96BmNRWkVhBNgAD9bZKkfE; fh_theme=dark

you should see Five requests carry the session cookie and four carry a bearer token.

defender tip HAR files also keep request bodies. A recording that includes the login form can hold the password itself, so check postData too.

03

Read the token without a key

A JWT is three base64url parts. The middle part holds the claims, readable by anyone.

learner@crypto-lab
jq -r '.log.entries[2].request.headers[] | select(.name=="Authorization") | .value' support-case-48213.har | cut -c1-72
Bearer eyJhbGciOiJFUzI1NiIsImtpZCI6InBvcnRhbC0yMDI2IiwidHlwIjoiSldUIn0.e
jq -r '.log.entries[2].request.headers[] | select(.name=="Authorization") | .value' support-case-48213.har | cut -d. -f2 | tr '_-' '/+' | jq -Rr '@base64d' | jq .
{
  "sub": "maya.okafor@fernhill.example",
  "role": "admin",
  "iat": 1791976800,
  "exp": 1792004400,
  "sid": "c1f0a9"
}
date -u -d @1792004400
Wed Oct 14 19:00:00 UTC 2026

you should see An admin token for maya.okafor, valid until 19:00 UTC on 14 October.

04

Redact and check

learner@crypto-lab
jq '(.log.entries[].request.headers[] | select(.name=="Cookie" or .name=="Authorization") | .value) |= "REDACTED" | (.log.entries[].response.headers[] | select(.name=="Set-Cookie") | .value) |= "REDACTED"' support-case-48213.har > /tmp/case-48213-clean.har && grep -c REDACTED /tmp/case-48213-clean.har
10
grep -cE 'fh_session=|Bearer ' /tmp/case-48213-clean.har
0

you should see Ten values replaced and no cookie or bearer value left.

defender tip If a raw HAR has already left the building, end the sessions in it. Redacting a copy does not log anyone out.

Same request, before and after

Raw HAR
{
  "name": "Cookie",
  "value": "fh_session=t8FJxtr6...kfE"
}

Anyone who opens it can replay the session.

Sanitised HAR
{
  "name": "Cookie",
  "value": "REDACTED"
}

Support still sees every request and status code.

What a defender takes away

  1. 1A HAR file holds live cookies and tokens, not just URLs.
  2. 2Base64 hides nothing: anyone can read a JWT's claims.
  3. 3Sanitise before upload, and end sessions when a raw HAR has leaked.

Questions

0 of 4 solved

Answer each one from what you find on your lab machine.

  1. Show hint

    Look at the Cookie header of request 2.

  2. Show hint

    Decode the middle part of the token.

  3. Show hint

    Count header names with uniq -c.

  4. Show hint

    `date -u -d @` with the exp value.