Module 1: Web Requests
HTTP Fundamentals
HyperText Transfer Protocol (HTTP)
Overview
Definition: HTTP (HyperText Transfer Protocol) is an application-layer protocol for requesting and transferring resources over the web.
Purpose: Enables communication between a client (e.g., browser) and a server.
Default Port:
80
for HTTP443
for HTTPS (secure)
Process:
Client sends a request for a resource.
Server processes the request and responds with the requested data.
Example: Visiting
https://www.example.com
sends an HTTP request to fetch the site’s content.
URL Structure
A URL specifies how to access resources. It can include several components:
Scheme
http://
or https://
Protocol used; ends with ://
User Info
admin:password@
Optional credentials for authentication
Host
example.com
Domain or IP address of the resource
Port
:80
Optional; defaults to 80
(HTTP) or 443
(HTTPS)
Path
/dashboard.php
File or folder location; defaults to index.html
if omitted
Query
?login=true
Parameters for the request, separated by &
Fragment
#status
Client-side reference to a section within the resource
Minimum Required: Scheme + Host.
HTTP Request Flow
DNS Resolution
Browser queries DNS to resolve the domain into an IP address.
Local
/etc/hosts
is checked first (can be modified manually).
HTTP Request
Client sends a request (usually
GET
) to the server at the resolved IP.
Server Response
Server responds with a status code (e.g.,
200 OK
) and the requested resource.
Rendering
Browser interprets the response and displays it to the user.
cURL Basics
What it is:
cURL
(Client URL) is a command-line tool for sending web requests.Advantages:
Works with multiple protocols (including HTTP/HTTPS).
Useful for scripting, automation, and penetration testing.
Basic Usage:
curl example.com
Displays raw HTML (does not render content like a browser).
Common cURL Options
-O
Save output using remote file name
-o <filename>
Save output to a specific file
-s
Silent mode (no progress output)
-i
Include response headers
-d <data>
Send HTTP POST data
-u user:password
Authenticate with credentials
-A <user-agent>
Specify User-Agent header
-v
Verbose mode for detailed output
-h
or --help
Show help (categories or all options)
Examples:
Save page as
index.html
(remote filename):curl -O example.com/index.html
Save page as
custom.html
(custom filename):curl -o custom.html example.com/index.html
Silent download:
curl -s -O example.com/index.html
Tip: Use man curl
or curl --help all
for complete documentation.
HyperText Transfer Protocol Secure (HTTPS)
Overview
Problem with HTTP:
Data sent over HTTP is in clear-text.
Vulnerable to Man-in-the-Middle (MITM) attacks where attackers can intercept and read sensitive information.
Solution: HTTPS
Encrypts all communication between client and server.
Prevents third parties from easily reading intercepted data.
Widely adopted; most browsers block or warn against plain HTTP.
Identification:
URLs start with
https://
Browser shows a lock icon in the address bar.
Important Note:
While HTTPS encrypts data, DNS requests can still reveal visited domains unless using encrypted DNS (e.g.,
8.8.8.8
,1.1.1.1
) or a VPN.
HTTP vs HTTPS Example
HTTP (Insecure): Login credentials are visible in plain text if intercepted.
HTTPS (Secure): Data appears as encrypted binary; credentials are hidden from interception.
HTTPS Flow (High-Level)
Initial Request
User may start with
http://
request.Server responds with
HTTP 301 Moved Permanently
redirect tohttps://
(port443
).
TLS Handshake
Client sends Client Hello (capabilities & preferences).
Server responds with Server Hello and sends SSL certificate.
Keys are exchanged and verified.
Secure Communication
Encrypted HTTP traffic begins.
Same HTTP methods (
GET
,POST
, etc.) are now secured.
Note: Modern browsers protect against HTTP downgrade attacks (forcing HTTPS to HTTP).
cURL with HTTPS
Automatic Handling:
cURL
negotiates TLS and encrypts data automatically.Invalid Certificates:
By default,
cURL
refuses connections with invalid or expired SSL certificates.Example error:
curl: (60) SSL certificate problem: Invalid certificate chain
Bypassing Certificate Checks (Testing Only): Use
curl -k https://example.com
to skip certificate validation.
Key Points
HTTPS ensures confidentiality and integrity of transmitted data.
Always prefer
https://
for secure communications.Avoid disabling certificate checks except in controlled testing environments. HTTP Requests and Responses
HTTP Requests and Responses
Overview
HTTP communication is built around a simple request–response model:
HTTP Request: Sent by a client (e.g. browser,
cURL
) to request a resource.HTTP Response: Sent by the server in reply, containing the requested data or a status message.
The request includes details like:
The resource being requested (URL, path, parameters)
Headers (e.g.
User-Agent
,Host
,Cookie
)Optional request body (e.g. form data)
The server processes the request and returns a response, which includes:
A status code (e.g.
200 OK
,404 Not Found
)Headers (e.g.
Set-Cookie
,Content-Type
)An optional response body (HTML, JSON, images, etc.)
HTTP Request Structure
Example HTTP request:
GET /users/login.html HTTP/1.1
Host: inlanefreight.com
User-Agent: Mozilla/5.0
Cookie: PHPSESSID=c4ggt4jull9obt7aupa55o8vbf
Key components of the request:
Method: The action to perform (
GET
,POST
, etc.)Path: The resource being accessed
Version: HTTP protocol version (e.g.
HTTP/1.1
)Headers: Metadata like host name, cookies, accepted content types
Body (optional): Only used in some requests like
POST
,PUT
Note:
HTTP/1.x requests are plain-text with newline-separated fields.
HTTP/2 uses a binary format for efficiency and performance.
HTTP Response Structure
Example HTTP response:
HTTP/1.1 200 OK
Date: Tue, 21 Jul 2020 05:20:15 GMT
Server: Apache/2.4.41
Set-Cookie: PHPSESSID=m4u64rqlpfthrvvb12ai9voqgf
Content-Type: text/html; charset=UTF-8
<!DOCTYPE html>
<html>
<body>
<h1>Welcome</h1>
</body>
</html>
Key components of the response:
Status line: Contains the HTTP version and status code (e.g.
200 OK
)Headers: Metadata such as content type and cookies
Body (optional): The content returned (HTML, JSON, images, etc.)
The body is often HTML, but can be any type of data: images, PDFs, JavaScript, CSS, etc.
Using cURL to Inspect Requests & Responses
By default, cURL
only displays the response body:
curl inlanefreight.com
Use the -v
flag (verbose) to see the full HTTP request and response:
curl inlanefreight.com -v
Example verbose output (simplified):
> GET / HTTP/1.1
> Host: inlanefreight.com
> User-Agent: curl/7.65.3
> Accept: */*
< HTTP/1.1 401 Unauthorized
< Date: Tue, 21 Jul 2020 05:20:15 GMT
< Server: Apache/X.Y.ZZ (Ubuntu)
< WWW-Authenticate: Basic realm="Restricted Content"
< Content-Length: 464
< Content-Type: text/html; charset=iso-8859-1
Use -vvv
for even more detailed output.
This allows you to see:
Exactly what headers and methods were sent
What the server responded with (status, headers, and body)
Using Browser DevTools
Modern browsers like Chrome and Firefox include built-in Developer Tools (DevTools) that let you inspect HTTP traffic.
To open DevTools:
Press
Ctrl + Shift + I
orF12
Go to the Network tab, then refresh the page.
You’ll see:
All HTTP requests made by the browser
Request methods (e.g.
GET
,POST
)Response codes (e.g.
200
,404
)Requested paths and URLs
You can also:
Click any request to view its headers and body
Use filters to find specific requests
View the raw HTML/JSON response under the Response tab → click Raw
HTTP Headers
Overview
HTTP headers pass information between the client and the server. Some headers are specific to requests, others to responses, and some apply to both. Headers are written as Header-Name: value
and may contain multiple values separated by commas.
Headers are commonly categorized as:
General Headers
Entity Headers
Request Headers
Response Headers
Security Headers
General Headers
Used in both requests and responses to describe the message context.
Date:
Date: Wed, 16 Feb 2022 10:38:44 GMT
– Timestamp of the message (UTC recommended)Connection:
Connection: close
– Controls whether the connection stays open (keep-alive
) or closes after the request
Entity Headers
Describe the content being transferred. Common in responses and in POST
or PUT
requests.
Content-Type:
Content-Type: text/html; charset=UTF-8
– Type of resource and character encodingMedia-Type:
Media-Type: application/pdf
– Specifies the media/file typeBoundary:
boundary="b4e4fbd93540"
– Used to separate multipart contentContent-Length:
Content-Length: 385
– Size of the entity body in bytesContent-Encoding:
Content-Encoding: gzip
– Specifies transformations like compression
Request Headers
Sent by the client to describe request details.
Host:
Host: www.inlanefreight.com
– Target host or domainUser-Agent:
User-Agent: curl/7.77.0
– Identifies the client softwareReferer:
Referer: http://www.inlanefreight.com/
– Source page of the requestAccept:
Accept: */*
– Accepted content typesCookie:
Cookie: PHPSESSID=b4e4fbd93540
– Session or stored user dataAuthorization:
Authorization: BASIC cGFzc3dvcmQK
– Credentials or authentication token
Response Headers
Sent by the server to provide response details.
Server:
Server: Apache/2.2.14 (Win32)
– Server software and versionSet-Cookie:
Set-Cookie: PHPSESSID=b4e4fbd93540
– Cookies for client identificationWWW-Authenticate:
WWW-Authenticate: BASIC realm="localhost"
– Authentication requirements
Security Headers
Used to enforce security policies in the browser.
Content-Security-Policy:
Content-Security-Policy: script-src 'self'
– Restricts allowed content sourcesStrict-Transport-Security:
Strict-Transport-Security: max-age=31536000
– Forces HTTPS for a set durationReferrer-Policy:
Referrer-Policy: origin
– Controls referrer header behavior
Using cURL with Headers
Show only response headers:
curl -I https://www.inlanefreight.com
Show headers and body:
curl -i https://www.inlanefreight.com
Change User-Agent:
curl https://www.inlanefreight.com -A 'Mozilla/5.0'
Example -I
output:
Date: Sun, 06 Aug 2020 08:49:37 GMT
Connection: keep-alive
Content-Length: 26012
Content-Type: text/html; charset=ISO-8859-4
Content-Encoding: gzip
Server: Apache/2.2.14 (Win32)
Set-Cookie: name1=value1,name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT
WWW-Authenticate: BASIC realm="localhost"
Content-Security-Policy: script-src 'self'
Strict-Transport-Security: max-age=31536000
Referrer-Policy: origin
Viewing Headers in Browser DevTools
Open DevTools (
Ctrl + Shift + I
orF12
)Go to Network tab and refresh the page
Click a request to see Headers tab
Displays request and response headers
Option to view raw format
Cookies tab shows any cookies in the request
HTTP Methods
HTTP Methods and Codes
Overview
HTTP supports multiple methods for accessing and interacting with resources. These methods tell the server how to process the request and what kind of action to take. The server’s response includes a status code that indicates the result of the request.
With cURL
, using -v
shows the HTTP method in the first line (e.g., GET / HTTP/1.1
). In browser DevTools, the HTTP method appears in the Method column, while the status code appears in the Status column.
Common HTTP Methods
GET – Retrieves a specific resource. Extra parameters can be added via query strings (e.g.,
?param=value
).POST – Sends data to the server. Data is placed in the request body. Commonly used for forms, logins, or file uploads.
HEAD – Returns only headers, no body. Often used to check response size before downloading.
PUT – Creates or replaces a resource on the server. Requires strict controls to prevent uploading malicious files.
DELETE – Removes an existing resource. Poorly secured endpoints could allow deletion of important files.
OPTIONS – Returns server information, such as supported HTTP methods.
PATCH – Applies partial updates to a resource.
Most modern applications rely mainly on GET and POST. REST APIs frequently use PUT and DELETE for updating and removing data.
HTTP Status Codes
Status codes indicate the result of an HTTP request. They are grouped into five classes:
1xx – Informational responses, no effect on request processing
2xx – Successful requests
3xx – Redirect responses
4xx – Client errors (e.g., malformed requests, unauthorized access)
5xx – Server errors
Common Status Code Examples
200 OK – Successful request; body usually contains requested resource
302 Found – Redirect to another URL (e.g., redirect to dashboard after login)
400 Bad Request – Malformed request (e.g., missing line terminators)
403 Forbidden – Client lacks permission or input was blocked as malicious
404 Not Found – Resource doesn’t exist on the server
500 Internal Server Error – Server unable to process the request
Different providers (e.g., Cloudflare, AWS) may also implement their own non-standard codes.
GET
Overview
When we visit any URL, the browser makes a default GET
request to retrieve resources from the server. Once the initial page loads, additional GET
or other method-based requests may be made for assets like images, scripts, or API data. These can be viewed in the browser’s DevTools Network tab.
Exercise: Open any website, open the Network tab in DevTools, and monitor the HTTP activity to understand how the site communicates with its backend.
HTTP Basic Auth
Some pages require credentials via HTTP Basic Authentication, rather than a standard login form. This method is handled directly by the web server (not the application backend).
Example URL:
http://<SERVER_IP>:<PORT>/
When prompted, enter credentials admin:admin
.
Unauthenticated cURL Request:
curl -i http://<SERVER_IP>:<PORT>/
Response:
HTTP/1.1 401 Authorization Required
WWW-Authenticate: Basic realm="Access denied"
This confirms the page is protected with Basic Auth.
Authenticated cURL Requests:
Using -u
:
curl -u admin:admin http://<SERVER_IP>:<PORT>/
Embedding in URL:
curl http://admin:admin@<SERVER_IP>:<PORT>/
Add -i
to either command to see response headers.
HTTP Authorization Header
With -v
, we can inspect the full request/response, including the Authorization header:
curl -v http://admin:admin@<SERVER_IP>:<PORT>/
Part of the request:
> Authorization: Basic YWRtaW46YWRtaW4=
This is the base64 encoding of admin:admin
.
Manually setting the header:
curl -H 'Authorization: Basic YWRtaW46YWRtaW4=' http://<SERVER_IP>:<PORT>/
This achieves the same result and is useful when scripting or bypassing interactive credential prompts.
GET Parameters
After authentication, we gain access to a City Search function on the site. Typing a query like "le" triggers a request to the backend:
http://<SERVER_IP>:<PORT>/search.php?search=le
Use DevTools Network tab (shortcut: Ctrl+Shift+E
) to observe these requests.
Example cURL Request with GET Parameters:
curl 'http://<SERVER_IP>:<PORT>/search.php?search=le' -H 'Authorization: Basic YWRtaW46YWRtaW4='
Expected output:
Leeds (UK)
Leicester (UK)
Note: When copying as cURL from DevTools, unnecessary headers may be included. You can remove all except essential ones like Authorization
.
Fetch via JavaScript Console
You can also copy the request as JavaScript Fetch:
Right-click request → Copy > Copy as Fetch
Go to Console (
Ctrl+Shift+K
)Paste and execute the Fetch command to replicate the request
Example:
fetch("http://127.0.0.1/search.php?search=le", {
headers: {
"Authorization": "Basic YWRtaW46YWRtaW4="
}
})
.then(response => response.text())
.then(data => console.log(data));
This shows the response directly in the console and helps understand frontend-to-backend interaction.
POST
Overview
Unlike GET
, which places parameters in the URL, POST
sends parameters in the HTTP request body.
Benefits of POST:
No URL logging: Large file uploads or sensitive data aren’t logged in the URL.
Less encoding: Data in the body can include binary data without URL encoding.
Larger payload: URLs are limited in length (generally below 2,000 characters), while POST bodies can handle much larger data.
Login Forms
Example application uses a PHP login form:
http://<SERVER_IP>:<PORT>/
Credentials: admin:admin
Observed in DevTools Network tab, the POST request sends:
username=admin&password=admin
Crafting this request with cURL
:
curl -X POST -d 'username=admin&password=admin' http://<SERVER_IP>:<PORT>/
If authentication redirects to another page, follow redirects with -L
:
curl -L -X POST -d 'username=admin&password=admin' http://<SERVER_IP>:<PORT>/
Authenticated Cookies
After successful login, server returns a session cookie:
Set-Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1; path=/
Use cookie in subsequent requests with -b
:
curl -b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' http://<SERVER_IP>:<PORT>/
Or send cookie as a header:
curl -H 'Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' http://<SERVER_IP>:<PORT>/
In the browser:
Open Storage tab (
Shift+F9
) in DevToolsAdd or edit cookie
PHPSESSID
with authenticated value to bypass login
JSON Data
Search functionality sends a POST request with JSON data:
{"search":"london"}
Request headers include:
Content-Type: application/json
Cookie: PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1
Replicating with cURL
:
curl -X POST -d '{"search":"london"}' \
-b 'PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1' \
-H 'Content-Type: application/json' \
http://<SERVER_IP>:<PORT>/search.php
Response:
["London (UK)"]
Using Fetch in Browser Console
Right-click the request in DevTools → Copy → Copy as Fetch
Execute in Console (Ctrl+Shift+K
):
fetch("http://<SERVER_IP>:<PORT>/search.php", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Cookie": "PHPSESSID=c1nsa6op7vtk7kdis7bcnbadf1"
},
body: JSON.stringify({search:"london"})
})
.then(response => response.json())
.then(data => console.log(data));
Returns the same result as cURL, confirming direct interaction with backend without frontend login.
CRUD API
APIs
Web applications can expose APIs to allow programmatic interaction with resources, often connected to a backend database. These APIs typically follow a pattern where:
The table name is part of the URL (e.g.,
/city
)The row or record is also part of the URL (e.g.,
/city/london
)The HTTP method (GET, POST, PUT, DELETE) determines the action
Example:
curl -X PUT http://<SERVER_IP>:<PORT>/api.php/city/london
CRUD
Common operations supported by REST-style APIs:
Create
POST
Adds new data to the database
Read
GET
Retrieves existing data
Update
PUT
Modifies existing data
Delete
DELETE
Removes existing data
Read
To read a single city entry:
curl http://<SERVER_IP>:<PORT>/api.php/city/london
Formatted with jq
:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/london | jq
To read all cities matching a search term:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/le | jq
To read all entries:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/ | jq
You can also test these URLs in the browser to view the raw JSON output.
Create
To create a new city using POST
:
curl -X POST http://<SERVER_IP>:<PORT>/api.php/city/ \
-d '{"city_name":"HTB_City", "country_name":"HTB"}' \
-H 'Content-Type: application/json'
To confirm it was added:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/HTB_City | jq
Exercise: Try using a JavaScript fetch
POST request in the browser DevTools Console to add a city.
Update
To update an existing city using PUT
:
curl -X PUT http://<SERVER_IP>:<PORT>/api.php/city/london \
-d '{"city_name":"New_HTB_City", "country_name":"HTB"}' \
-H 'Content-Type: application/json'
Confirm the update:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/london | jq
curl -s http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_City | jq
Note: Some APIs allow PUT to also create entries if the target doesn't exist. Try updating a non-existent city to test behavior.
Delete
To delete a city:
curl -X DELETE http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_City
Then verify it's gone:
curl -s http://<SERVER_IP>:<PORT>/api.php/city/New_HTB_City | jq
Expected output: []
Exercise: Try deleting any other city you previously added and confirm with a read request.
With this approach, you can fully manage CRUD operations through an API using cURL
.
In real-world applications:
These API actions are typically restricted to authorized users
Authentication might be required via cookies or Authorization headers (e.g., JWT)
Write operations (create, update, delete) should be protected with proper access control policies.
Last updated