Web Requests

The vast majority of the apps and websites we use every day communicate over the web. At the heart of that communication is HTTP — the Hypertext Transfer Protocol. In simple terms, HTTP is the language clients (browsers, mobile apps, scripts) and servers use to request and deliver resources (HTML pages, images, JSON APIs, files). This article walks through the core ideas, real-world examples, and why understanding HTTP matters for development, debugging, and security work.

What is HTTP?

HTTP (Hypertext Transfer Protocol) is an application-level protocol designed for fetching resources over the World Wide Web. “Hypertext” refers to text that contains links to other resources — the building block of web browsing.

HTTP defines:

  • How a client asks for a resource (the request).
  • How a server replies with the resource or status information (the response).
  • A set of methods, headers, status codes and semantics that structure the conversation.

Client ↔ Server: The Basic Flow

  1. Client (browser, mobile app, script) wants a resource — e.g., a webpage or API data.
  2. Client sends an HTTP request to a server.
  3. Server processes the request and returns an HTTP response (the resource, or an error/status).
  4. Client renders or consumes the response.

Example (human-friendly):

  • You type https://www.hackthedome.com into your browser → browser sends an HTTP request → server responds with HTML → your browser renders the page.

URLs, FQDNs, and Ports

  • URL (Uniform Resource Locator) — the address for a resource (e.g., https://www.example.com/path?query=1).
  • FQDN (Fully Qualified Domain Name) — the host portion of the URL that uniquely identifies a machine on the internet (e.g., www.hackthedome.com).
  • Ports — network endpoints on the server. Default ports:
    • HTTP → 80
    • HTTPS (HTTP over TLS) → 443

Servers can host HTTP on non-standard ports (e.g., http://example.com:8080).

HTTP Requests: Components & Common Methods

An HTTP request consists of:

  • Request line: method, path, HTTP version (e.g., GET /index.html HTTP/1.1)
  • Headers: metadata about the request (User-Agent, Host, Accept, Cookie, Authorization, etc.)
  • Body (optional): data sent to the server (used in POST, PUT, etc.)

Common methods:

  • GET — retrieve a resource (safe, idempotent).
  • POST — submit data to be processed (e.g., form submission).
  • PUT — replace/overwrite a resource.
  • PATCH — partially modify a resource.
  • DELETE — remove a resource.
  • HEAD — same as GET but only fetches headers.

HTTP Responses: Status Codes & Payloads

An HTTP response contains:

  • Status line: HTTP version and status code (e.g., HTTP/1.1 200 OK)
  • Headers: content-type, cache-control, set-cookie, etc.
  • Body: the resource (HTML, JSON, image, binary data).

Common status codes:

  • 200 OK — request succeeded.
  • 301 / 302 — redirects.
  • 400 Bad Request — client-side error.
  • 401 Unauthorized — authentication required.
  • 403 Forbidden — authenticated but not allowed.
  • 404 Not Found — resource missing.
  • 500 Internal Server Error — server-side failure.

Content Types & Resources

Servers tell clients what kind of data the body contains using Content-Type header:

  • text/html — HTML pages
  • application/json — JSON APIs
  • image/jpeg, image/png — images
  • application/octet-stream — generic binary

This helps browsers and apps decide how to process/display the content.

Why HTTP Matters for Developers, Ops, and Security

  • Developers: understanding HTTP methods, headers, and status codes is essential for building RESTful APIs and debugging client-server issues.
  • Operations / SRE: HTTP logs and status codes are core observability signals for uptime, latency, and error analysis.
  • Security / IR / Pentesters: HTTP traffic often contains sensitive data (cookies, tokens, forms) or reveals application logic — a prime target for testing and monitoring. Unencrypted HTTP (port 80) exposes payloads to eavesdroppers; prefer HTTPS.

Quick Examples

GET request:

GET /api/users/123 HTTP/1.1
Host: api.example.com
User-Agent: curl/7.79.1
Accept: application/json

Response:

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 85

{"id":123,"name":"Alice","email":"alice@example.com"}

Practical Tips

  • Always use HTTPS in production to protect confidentiality and integrity.
  • Use proper status codes — they help clients and monitoring tools behave correctly.
  • Cache-control headers can drastically improve performance when used wisely.
  • Inspect HTTP traffic with tools such as browser devtools, curl, or network analyzers (Wireshark, tshark) when debugging.
  • Watch for sensitive data in requests/responses (auth tokens, personal data) and protect or redact as needed.

Key Takeaways

  • HTTP is the core protocol used by web and mobile applications to exchange resources.
  • Communication follows a request → response model between client and server.
  • Default HTTP port is 80, HTTPS is 443 — but ports can be customized.
  • Knowing methods, headers, status codes, and content types is essential for building, debugging, and securing web applications.
  • Prefer HTTPS for any sensitive or production traffic to prevent eavesdropping and tampering.

To get the flag, start the above exercise, then use cURL to download the file returned by ‘/download.php’ in the server shown above.

Just open your terminal and use the command bellow:

$ curl -i http://127.0.0.1:53659/download.php
HTTP/1.1 200 OK
Date: Mon, 22 Sep 2025 20:36:16 GMT
Server: Apache/2.4.41 (Ubuntu)
Content-Description: File Transfer
Cache-Control: no-cache, must-revalidate
Expires: 0
Content-Disposition: attachment; filename="flag.txt"
Content-Length: 20
Pragma: public
Content-Type: text

[REDACTED]

Hypertext Transfer Protocol Secure (HTTPS)

In the last section, we saw how HTTP works. The problem? HTTP sends everything in plain text. That means anyone on the path — an attacker on public Wi-Fi, for example — could launch a Man-in-the-Middle (MiTM) attack and read your data.

The solution is HTTPS (HTTP Secure). By using encryption, HTTPS makes intercepted traffic unreadable. Even if someone captures the data, they can’t extract useful information.

Today, HTTPS is the standard across the web. In fact, many browsers already block or warn users when visiting plain HTTP sites. The internet is quickly moving to a fully secure-by-default model.

HTTP Requests and Responses

Every HTTP exchange has two parts: a request and a response.

  • HTTP Request – Sent by the client (like a browser or cURL). It includes the resource being asked for (URL, path, parameters), along with headers and any extra data.
  • HTTP Response – Sent back by the server. It contains a status code (e.g., success or error) and, if allowed, the requested resource data.

This simple back-and-forth is the foundation of how browsers and servers talk to each other across the web.

What is the HTTP method used while intercepting the request? (case-sensitive)

Use the verbose mode to get the answer:

$ curl -v http://127.0.0.1:53659
*   Trying 127.0.0.1:53659...
* Connected to 127.0.0.1 (127.0.0.1) port 53659
> [REDACTED] / HTTP/1.1
> Host: 127.0.0.1:53659
> User-Agent: curl/8.15.0
> Accept: */*
> 
* Request completely sent off
< HTTP/1.1 200 OK
< Date: Mon, 22 Sep 2025 20:47:19 GMT
< Server: Apache/2.4.41 (Ubuntu)
< Vary: Accept-Encoding
< Content-Length: 348
< Content-Type: text/html; charset=UTF-8
< 
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blank Page</title>
</head>

<body>
    This page is intentionally left blank.
    <br>
    Using cURL should be enough.
</body>

* Connection #0 to host 127.0.0.1 left intact
</html>

Send a GET request to the above server, and read the response headers to find the version of Apache running on the server, then submit it as the answer. (answer format: X.Y.ZZ)

Execute the command to get the answer.

$ curl -s -D - http://127.0.0.1:53659/
HTTP/1.1 200 OK
Date: Mon, 22 Sep 2025 20:50:05 GMT
Server: Apache/[REDACTED] (Ubuntu)
Vary: Accept-Encoding
Content-Length: 348
Content-Type: text/html; charset=UTF-8

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Blank Page</title>
</head>

<body>
    This page is intentionally left blank.
    <br>
    Using cURL should be enough.
</body>

</html>

HTTP Headers

HTTP headers are small pieces of information passed between the client and server. Some are specific to requests, others to responses, and a few apply to both.

A header follows a simple format:

Header-Name: value

Multiple values can also be listed after the colon.

Headers are usually grouped into categories:

  • General Headers – Apply to both requests and responses.
  • Entity Headers – Provide details about the resource itself.
  • Request Headers – Sent by the client to describe what it wants.
  • Response Headers – Sent by the server to describe the result.
  • Security Headers – Help enforce policies and protect against attacks.

The server above loads the flag after the page is loaded. Use the Network tab in the browser devtools to see what requests are made by the page, and find the request to the flag.

Open the page on your browser. Right click, and choose Inspector. Go to the tab Network tab and reload the page. You will find a request that contains the flag.

GET

When you type a URL, your browser sends a GET request by default to fetch the page. But that’s just the start — once the page loads, the browser often makes additional requests using different HTTP methods (like POST, PUT, or DELETE) to grab images, scripts, or interact with APIs.

You can easily see this in action with your browser’s Network tab inside DevTools. It shows every request and response as they happen.

Quick Exercise

  1. Open the Network tab in DevTools.
  2. Visit any website.
  3. Watch the requests being made in real time.

This is a powerful way to understand how a site communicates with its backend — a skill that’s especially useful for web assessments or bug bounty hunting.

Key Takeaway: A single page load often triggers dozens of hidden requests. Monitoring them reveals how the application really works behind the scenes.

The exercise above seems to be broken, as it returns incorrect results. Use the browser devtools to see what is the request it is sending when we search, and use cURL to search for ‘flag’ and obtain the flag.

Open the page and insert the username and password (admin:admin). Open the inspector on the tab Network. Search for anything.

Right click on the request and choose Copy -> Copy URL.

Open your terminal and use the command above to get the flag.

$ curl -u admin:admin curl http://127.0.0.1:37034/search.php?search='flag'
curl: (6) Could not resolve host: curl
flag: [REDACTED]

POST

Browsers default to GET when you visit a URL, but web apps use POST whenever they need to send larger or private data — for example, file uploads, form submissions, or moving parameters out of the URL. The key difference is that GET puts parameters in the URL, while POST puts them in the request body.

Main advantages of POST over GET

  • No noisy logging in the URL: Large uploads or sensitive data shouldn’t appear in the URL (where servers, proxies or logs may store them). POST keeps that data in the body.
  • Fewer encoding constraints: Body data can be binary or complex (files, JSON, multipart), so you don’t need to percent-encode everything like in a URL.
  • Can send much more data: URLs have practical length limits (varying by browser, server, CDNs). POST bodies avoid those limits so you can transmit larger payloads.

Quick examples

Inspect or send POSTs with:

  • DevTools → Network tab to view request bodies and headers in real time.
  • cURL example (JSON):
curl -X POST https://example.com/api/upload \
  -H "Content-Type: application/json" \
  -d '{"name":"alex","action":"submit"}
  • cURL example (file upload, multipart):
curl -X POST https://example.com/upload \
  -F "file=@/path/to/file.jpg"

Key takeaway: Use POST when you need privacy, binary/complex payloads, or larger data transfers. GET is for simple, cacheable retrievals where parameters in the URL make sense.

Obtain a session cookie through a valid login, and then use the cookie with cURL to search for the flag through a JSON POST request to ‘/search.php’

Open the page. Right Click and choose Inspector. Login on the page using admin:admin. Go to the Application tab and choose the Cookies folder.

Copy this value and use the curl command above to get the flag.

curl -b 'PHPSESSID=6dibgmdr6c1ktu56205dqivqt8' -d '{"search":"flag"}' -H 'Content-Type: application/json' http://127.0.0.1:35398/search.php

CRUD API

Earlier, we looked at a City Search app that used PHP parameters in the URL to search for city names. That’s the traditional way many older web apps handle data.

Now, let’s take it a step further: instead of sending parameters to a PHP page, the app can call an API endpoint. APIs provide a cleaner, more flexible way to interact with the backend.

With APIs, we can:

  • Send structured requests (often in JSON).
  • Get responses that are easier for both apps and developers to work with.
  • Interact directly using tools like cURL or browser DevTools.

First, try to update any city’s name to be ‘flag’. Then, delete any city. Once done, search for a city named ‘flag’ to get the flag.

Open your terminal. First need want to see all the cities.

[{"city_name":"London","country_name":"(UK)"},{"city_name":"Birmingham","country_name":"(UK)"},{"city_name":"Leeds","country_name":"(UK)"},{"city_name":"Glasgow","country_name":"(UK)"},{"city_name":"Sheffield","country_name":"(UK)"},{"city_name":"Bradford","country_name":"(UK)"},{"city_name":"Liverpool","country_name":"(UK)"},{"city_name":"Edinburgh","country_name":"(UK)"},{"city_name":"Manchester","country_name":"(UK)"},{"city_name":"Bristol","country_name":"(UK)"},{"city_name":"Cardiff","country_name":"(UK)"},{"city_name":"Stoke","country_name":"(UK)"},{"city_name":"Coventry","country_name":"(UK)"},{"city_name":"Leicester","country_name":"(UK)"},{"city_name":"Sunderland","country_name":"(UK)"},{"city_name":"Belfast","country_name":"(UK)"},{"city_name":"Nottingham","country_name":"(UK)"},{"city_name":"Newcastle","country_name":"(UK)"},{"city_name":"Brighton","country_name":"(UK)"},{"city_name":"Doncaster","country_name":"(UK)"},{"city_name":"Stockport","country_name":"(UK)"},{"city_name":"Plymouth","country_name":"(UK)"},{"city_name":"Rotherham","country_name":"(UK)"},{"city_name":"Blackpool","country_name":"(UK)"},{"city_name":"Southampton","country_name":"(UK)"},{"city_name":"Wolverhampton","country_name":"(UK)"},{"city_name":"Salford","country_name":"(UK)"},{"city_name":"Derby","country_name":"(UK)"},{"city_name":"Swindon","country_name":"(UK)"},{"city_name":"Newport","country_name":"(UK)"},{"city_name":"Mansfield","country_name":"(UK)"},{"city_name":"Baton","country_name":"(USA)"},{"city_name":"New York","country_name":"(US)"},{"city_name":"Los Angeles","country_name":"(US)"},{"city_name":"Chicago","country_name":"(US)"},{"city_name":"Houston","country_name":"(US)"},{"city_name":"Phoenix","country_name":"(US)"},{"city_name":"Philadelphia","country_name":"(US)"},{"city_name":"San Antonio","country_name":"(US)"},{"city_name":"San Diego","country_name":"(US)"},{"city_name":"Dallas","country_name":"(US)"},{"city_name":"San Jose","country_name":"(US)"},{"city_name":"Austin","country_name":"(US)"},{"city_name":"Jacksonville","country_name":"(US)"},{"city_name":"Fort Worth","country_name":"(US)"},{"city_name":"Columbus","country_name":"(US)"},{"city_name":"Charlotte","country_name":"(US)"},{"city_name":"San Francisco","country_name":"(US)"},{"city_name":"Indianapolis","country_name":"(US)"},{"city_name":"Seattle","country_name":"(US)"},{"city_name":"Denver","country_name":"(US)]()

Now, we need to insert a city called flag.

$ curl -X PUT http://127.0.0.1:32609/api.php/city/london -d '{"city_name":"flag","country_name":"(BR)"}' -H 'Content-Type: application/json'

The exercise says that we must have the same number of cities from the beginning of the exercise. So we need to delete one city.

$ curl -X DELETE http://127.0.0.1:32698/api.php/city/baltimore

And now search for the flag city to get the answer

curl -s http://127.0.0.1:32698/api.php/city/flag