HackBlue

Tools · Web testing tools · 10 / 23

Walkthrough: map Harbor Ledger from a cold start

This is the full pass: temporary project, listener, scope, intercept off, one clerk’s click-through, then history, the site map, a single Repeater replay, and a note someone else can check. Nothing in the pass leaves 127.0.0.1:3000.

22 min read · practice only with authorization

Prepare the desk before the first click

Start Harbor Ledger so http://127.0.0.1:3000 answers on the same machine. The lab README has the start command and the seed accounts. Use that command. Start Burp and choose a temporary project. Confirm the proxy listener is 127.0.0.1 port 8080 and is bound to loopback only. Add one scope include: protocol http, host 127.0.0.1, port 3000, all paths. Turn intercept off.

Open the built-in browser. If you use a spare Firefox profile instead, its proxy points at 127.0.0.1:8080 and its certificate store is the only place the lab CA lives. Visit the lab origin. You should see the sign-in page, and history should show a request to 127.0.0.1:3000 and not a forest of other hosts. If the page does not load, check which of the two ports you typed. The address bar gets 3000. The browser’s proxy setting gets 8080.

  • App: http://127.0.0.1:3000
  • Proxy listener: 127.0.0.1:8080
  • Project: temporary
  • Intercept: off
  • Include: http://127.0.0.1:3000/

Browse as Avery, once, slowly

Sign in with Avery’s seed account from the lab README. Do not reuse a password from anywhere else, and do not type the seed password into a note. Open the invoice list. Open April retainer, invoice 1042. Go back and open March hosting, invoice 1048. Open http://127.0.0.1:3000/health in the address bar. Stop clicking. You have a clerk’s first minute, and that is the whole specimen.

If the app offers a note field, leave it for the intercept lesson. This pass is a map of reads plus the pages that caused them. Signing out is optional. If you do sign out, do it last, and mark that request in the note so the later rows are not mistaken for Avery’s session.

Read the site map, then the filtered history

On Target, the site map under 127.0.0.1:3000 should list the document paths, the two invoice pages, the API paths, /health, and the static files. That list is the inventory. Compare it to the address bar paths you remember. Anything on the map you do not remember is something the page requested for you, usually the script, the stylesheet, or the API. Those still belong on the inventory.

On Proxy, HTTP history, enable “Show only in-scope items” and search for /api/. You want the collection and the two invoice fetches. Open 1042 and read the owner. Open 1048 and read the owner. Both should be avery@ledger.lab. Write the inventory and those three API lines before you touch Repeater.

Snippet
Site map under http://127.0.0.1:3000
  /
  /invoices
  /invoices/1042
  /invoices/1048
  /api/invoices
  /api/invoices/1042
  /api/invoices/1048
  /health
  /static/app.js
  /static/app.css

One replay, then the note

Send GET /api/invoices/1042 to Repeater. Send it unchanged. Send it once more with the header X-Harbor-Lab: replay-2 and with the path still exactly /api/invoices/1042. The owner and the invoice status should match the history row. In Logger, if you enabled it with the lab capture rule, the labeled send is the easy row to find. If you did not enable Logger, history still shows the replay as long as it went through the proxy, and Repeater’s own send list shows it either way.

Write the note in the block at the top of this lesson’s diagram: lab origin, listener, project type, account, include rule, paths, API lines, replay result, and an explicit “every other host stayed out of scope.” Quit the built-in browser. Quit Burp. Because the project was temporary, the cookie dies with the process. The note is what you keep.

Worked case: the stop rule, rehearsed

The seed data is supposed to show Avery’s own owner field. Rehearse the other branch anyway, in writing, before you need it. If either response’s owner is not avery@ledger.lab, you copy method, path, status, the account you signed in as, and the owner value into the note, and you end the pass. You do not change the id. You do not open a second account to compare. You do not paste the cookie beside the owner “so it can be reproduced.” The reproduction is the history row inside a project that stays on this machine, described well enough that you can reload the same page as Avery and point at the same field.

That stop rule is the difference between a map and a fishing trip. The map is done when the paths are listed, one authorized replay agrees, and every host that is not the lab is still absent from the include list.

Diagram

A mapping pass in order

  1. Prepare

    The app listens on 127.0.0.1:3000. Burp listens on 127.0.0.1:8080. The include list is the app origin.

  2. Browse

    Intercept is off. Avery signs in and opens the list, invoice 1042, invoice 1048, and /health.

  3. Read

    History filtered to /api/ shows the collection and the two invoices. The site map shows the paths.

  4. Confirm

    One Repeater replay of invoice 1042 matches the owner. The note is five lines per request, and the project stays temporary.

The map you should be able to point at

Site mapOne API row

target · site map · 127.0.0.1:3000

http://127.0.0.1:3000
  /
  /invoices
  /invoices/1042
  /invoices/1048
  /api/invoices
  /api/invoices/1042
  /api/invoices/1048
  /api/notes
  /health
  /static/app.js
  /static/app.css
Out of scope, if they appeared:
  any host other than 127.0.0.1
  any port other than 3000
  • Every path here was produced by a click or by the page that click loaded.
  • The static files are part of the map even when a later exclude hides them.
  • A host that is not on this list does not get added to scope.

history · GET /api/invoices/1042

GET /api/invoices/1042 HTTP/1.1
Host: 127.0.0.1:3000
Accept: application/json
Cookie: session=lab-session-avery
HTTP/1.1 200 OK
Content-Type: application/json

{"id":"1042","title":"April retainer","owner":"avery@ledger.lab","status":"open"}
  • This is the row you will replay once.
  • Owner matches Avery, the account you signed in as.
  • The note quotes this row and does not quote the cookie.
Map note
Lab: http://127.0.0.1:3000
Proxy: 127.0.0.1:8080
Project: temporary
Account: Avery (seed)
Scope include: http://127.0.0.1:3000/

Visited: /  /invoices  /invoices/1042  /invoices/1048  /health
API: GET /api/invoices  GET /api/invoices/1042  GET /api/invoices/1048
Replay: GET /api/invoices/1042 twice, owner matched both times
Left out of scope: every other host

Check yourself

1. What is the first thing you configure after choosing a temporary project?

2. During the click-through, intercept is off. Why?

3. The replay of GET /api/invoices/1042 returns owner blake@ledger.lab. You signed in as Avery and you did not change the path. What is the pass supposed to do?

4. Which line belongs in the finished map note?