Tools · Web testing tools · 05 / 23
Repeater: read one authorized request, then send it again
Repeater holds a single request you were already allowed to make, so you can read it slowly and send that same request again. On Harbor Ledger that means replaying Avery’s own invoice call and comparing the two responses, without wandering into other identifiers.
Repeater starts from history
Right-click the history row for GET /api/invoices/1042 and choose Send to Repeater. Burp opens a tab with that request in full: the request line, the Host header, Accept, and Avery’s session cookie. Name the tab GET invoice 1042. The name matters an hour later, when you have several tabs and only one of them is the baseline.
A blank Repeater tab is available, and it is the wrong start for this lesson. Typing a request from memory is how a host leaves scope. The history row is already known to be the lab, already known to be Avery, and already known to be an invoice the page loaded.
Send it, read it, send it again
Press Send once. The response pane fills with the status line, the headers, and the JSON. Read it in the same order as history: status, content type, id, title, owner, invoice status. For the seed data, owner is avery@ledger.lab and the invoice status is open. That first response is the baseline. Leave it visible. Repeater keeps a list of sends for the tab so you can click back.
Press Send a second time. If you want the two log rows to be easy to tell apart, add one header before the second send: X-Harbor-Lab: replay-2. Do not change the path. Do not change the cookie. A lab that is behaving returns the same id, owner, and status. You have confirmed that the history row was not a one-off drawing of the page, and you have done it with a request the account was already allowed to make.
GET /api/invoices/1042 HTTP/1.1 Host: 127.0.0.1:3000 Accept: application/json Cookie: session=lab-session-avery X-Harbor-Lab: replay-2
What you are allowed to change here
The label header is a note to yourself. Harbor Ledger, as this set describes it, ignores unknown headers, so the JSON stays the same and the header shows up in Burp’s log of the replay. If the app echoes the header into the body, write that down too. Echoing a header you set is an observation about the app, and it is still your header.
The path’s invoice id stays 1042 on this tab. Avery’s other invoice, 1048, gets its own tab, created the same way, from its own history row, if you want a pair. Replacing 1042 with an id the list never showed you is a different exercise, and it is not this one. If a response you already hold names an owner other than the account you signed in as, the finding is that response. Quote it. Stop.
Worked case: baseline for April retainer
From a fresh sign-in as Avery, load invoice 1042 in the browser so history has the row. Send it to Repeater. Send it unchanged. On a second send, add the label header and send again. Write four lines: tab name, status of send 1, status of send 2, and whether id, owner, and invoice status matched. Attach nothing else.
Then look at Logger or HTTP history and find the labeled request by the header. You should see the browser’s original call and your replay as separate rows. That is the whole point of Repeater in this set: one authorized request, readable on its own, repeatable, and traceable back to the click that created it.
Diagram
History, then one tab, then a second send
- Pick
In history, choose GET /api/invoices/1042, the call Avery’s page already made.
- Send to Repeater
Burp copies that request into its own tab. The copy still carries Avery’s lab cookie.
- Send
The first Send repeats the request. The response should match the history row.
- Send again
A second Send shows whether the lab answers the same way twice. You still have not changed the path.
The request you replay, and the response you compare
repeater · invoice 1042 · send 1
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 same request the page made.
- Owner matches the account that signed in.
- Keep this response on screen. It is the baseline.
repeater · invoice 1042 · send 2
GET /api/invoices/1042 HTTP/1.1 Host: 127.0.0.1:3000 Accept: application/json Cookie: session=lab-session-avery X-Harbor-Lab: replay-2
HTTP/1.1 200 OK
Content-Type: application/json
{"id":"1042","title":"April retainer","owner":"avery@ledger.lab","status":"open"}- The path and the cookie are unchanged.
- The extra header is a label for your notes, if the app ignores it.
- A matching owner and status means the replay agreed with the first send.
Tab name: GET invoice 1042 Request: the history row, unchanged Optional label header: X-Harbor-Lab: replay-2 Write down: status, content type, id, owner, status field Do not replace the invoice id or the cookie
Check yourself
1. Which history row is the right one to send to Repeater in this lesson?
2. You send that request twice. The second request adds X-Harbor-Lab: replay-2 and changes nothing else. What are you checking?
3. The first response shows owner avery@ledger.lab. The second shows a different owner, and you did not change the path or the cookie. What do you write?