The lab
here is how portswigger describes it
This lab has a stock check feature which fetches data from an internal system.
To solve the lab, change the stock check URL to access the admin interface at http://localhost/admin and delete the user carlos.
The developer has deployed two weak anti-SSRF defenses that you will need to bypass.
The idea#
a blacklist tries to name the bad things and block them, here it is blocking the obvious ways of writing the local address and blocking the word admin. the trouble with that approach is that there are usually many ways to write the same thing, and a filter only catches the exact spellings its author thought of. so the whole lab is about finding equivalent spellings, an address that still points at the loopback but is not the literal string being blocked, and a path that still reads as admin once the server decodes it but does not look like admin to the filter
Step 1 - see the first Filter block localhost#
we visit product page click check stock, intercept the request, and set the stockApi parameter to the plain loopback address.

stockApi=http://127.0.0.1/
the request is blocked. the filter recognises 127.0.0.1, and it would recognise localhost too, so writing the loopback the normal way is a dead end.

Step 2 - Bypass it with an Alternate loopback spelling#
we change the address to this and it goes through
stockApi=http://127.1/

the reason 127.1 works is that it is still the loopback address, just written in a shorthand. an ipv4 address is really a single 32 bit number, and the dotted form is only one way to write it. when there are fewer than four parts, the last part is stretched to fill the rest, so 127.1 is read as 127.0.0.1. the filter is doing a dumb string match for 127.0.0.1 and localhost, so this equivalent spelling sails past it while still resolving to the same place.
there are several more spellings of loopback worth keeping in your pocket for filters like this, all of them equal to 127.0.0.1.
http://127.1/
http://2130706433/
http://0x7f000001/
http://0177.0.0.1/
http://[::1]/
Step 3 - Hit the second filter on the admin path#
with the loopback spelling sorted, we try to reach the admin path
stockApi=http://127.1/admin
it is blocked again, so the second filter is watching for the word admin in the path.

Step 4 - Bypass it with double url encoding#
we obfuscate the a in admin by double url encoding it, which gets it past the filter.
stockApi=http%3a//127.1/%2561dmin

here is what %2561 is doing. normally a url encodes to %61. double encoding means we then encode the percent sign of that too, and % encodes to %25, so %61 becomes %2561. now there are two layers. when the filter inspects the input it sees %2561dmin, which does not contain the word admin, so it lets it through. but the request then gets url decoded on its way to being fetched, %2561 decodes to %61, and a further decode turns %61 back into a, so by the time the server actually makes the request the path reads admin again. the filter judged the outer spelling while the server acted on the fully decoded one, and that gap is the bypass.
Step 5 - Delete carlos acc#
now we combine both bypasses and aim at the delete endpoint, double encoding the a characters throughout so nothing trips the admin filter.
stockApi=http%3a//127.1/%2561dmin/delete?usern%2561me=c%2561rlos

the server decodes it fetches http://127.1/admin/delete?username=carlos from loopback, the admin endpoint accepts it and carlos acc is deleted

with this, we solved the lab!
