Security Handbook 🌐 VI

Chapter 12 — Penetration Testing & Vulnerability Assessment

Overview

An overlooked vulnerability doesn't disappear on its own — it just sits there waiting for someone to find it first, and the only question that matters is who gets there first, your team or the attacker. That's why this chapter matters: it covers the two ways of proactively hunting for weaknesses in a system (web, server, network) before they turn into a data leak, since a single overlooked vulnerability is enough to expose all of a user's data.

The chapter opens by drawing a clean line between vulnerability scanning — automatically matching a system's fingerprint against a database of known vulnerabilities, broad and shallow, detecting rather than exploiting — and penetration testing, where a human simulates a real attack and actually exploits what's found to demonstrate impact, narrower and deeper but far more dependent on human judgment. From there it follows the standard OWASP web testing process (WSTG): recon, mapping, testing, exploit, report — then digs into the mechanics of three flagship tools. Burp Suite is an intercepting proxy sitting between browser and server, letting you view and edit every request and response; Acunetix is a commercial DAST scanner that crawls, audits, and reports automatically, complementing rather than replacing Burp; Nmap maps a network down to host discovery, port scanning, and version/OS detection. The chapter closes on scope and legality — the boundary you're authorized to test has to be spelled out in writing, because running outside scope is unauthorized access no matter how good the intent.

The throughline: understand the mechanics down to individual packets, and have a real runnable command for every tool, not just theory.


12.1. Distinguishing Vulnerability Scanning from Penetration Testing

12.1.1. Definition and Nature

Vulnerability Scanning is the process of automatically detecting known vulnerabilities on a system by matching signatures/fingerprints against a vulnerability database such as NVD (National Vulnerability Database), a CVE feed, or a vendor's own database. Its nature is breadth-first (broad and shallow): it scans many targets and checks many signatures, but does NOT exploit.

Penetration Testing is the process of simulating a deliberate attack, in which a person (or person + tools) attempts to actually exploit vulnerabilities to demonstrate impact, the kill chain, and the level of access achieved. Its nature is depth-first (deep and narrow): it focuses on a specific target, chains vulnerabilities, and leverages business logic.

12.1.2. Detailed Comparison Table

Criterion Vulnerability Scanning Penetration Testing
Goal Enumerate known vulnerabilities Prove exploitability + impact
Level of automation High (almost fully automated) Manual + tool-assisted
Detecting logic flaws (IDOR, business logic) Almost never Yes (a key strength)
Real-world exploitation No (detection only) Yes (PoC, exploit)
Proving false positives Difficult Yes (manual confirmation)
Frequency Continuous/periodic (weekly, daily in CI) Periodic (quarterly/yearly) or event-driven
Cost Low (license + automation) High (experts + time)
Output List of CVEs + severity Kill chain report + evidence
Risk of harming the system Low (a safe mode exists) Higher (can cause downtime)
Scope All assets Focused per agreement
Reference standards CVSS, CVE, CWE OWASP, PTES, OSSTMM, NIST SP 800-115

12.1.3. Why Both Are Needed

Vulnerability scanning answers the question "how many suspicious doors are there?" while a pentest answers "how far can an attacker really get in, and what can they do?". A scanner reports "port 443 runs OpenSSL with CVE-2014-0160 (Heartbleed)" — but only a pentest can prove that a private key can actually be pulled out of RAM. In the DevSecOps model, scanning is embedded into the pipeline (shift-left, continuous), while a pentest is a periodic, deeper validation. Scanning is a necessary condition (fast, cheap, broad) but not sufficient; a pentest provides the exploitation context and the real risk level needed to prioritize remediation.


12.2. The OWASP Web Testing Process

OWASP WSTG (Web Security Testing Guide) divides the process into phases. Below is the real-world lifecycle as applied to a web pentest:

+-------------+    +-------------+    +-------------+    +--------------+    +-------------+
|  1. Recon   | -> | 2. Mapping  | -> | 3. Testing  | -> | 4. Exploit   | -> | 5. Report   |
| (gathering) |    | (mapping)   |    | (testing)   |    | (exploit)    |    | (reporting) |
+-------------+    +-------------+    +-------------+    +--------------+    +-------------+
       ^                                                                          |
       |__________________________ (repeat when a new surface is found) _________|

12.2.1. Phase 1 — Reconnaissance (information gathering)

Divided into passive (no contact with the target) and active (sending packets to the target).

Passive recon — generates no traffic to the target, using public sources: - DNS records, certificate transparency logs (crt.sh) to enumerate subdomains. - WHOIS, Shodan, Censys, Google dorking (site:, inurl:, filetype:). - Finding leaked secrets on GitHub, the Wayback Machine (archive.org).

Example of enumerating subdomains via Certificate Transparency:

# Query crt.sh, filter for unique subdomains
curl -s 'https://crt.sh/?q=%25.example.com&output=json' \
  | jq -r '.[].name_value' \
  | sed 's/\*\.//g' | sort -u

Active recon — port scanning (Nmap, section 12.5), banner grabbing, technology fingerprinting:

# Identify web technology (Server header, X-Powered-By, cookies)
curl -sI https://example.com | grep -iE 'server|x-powered-by|set-cookie'
whatweb https://example.com

12.2.2. Phase 2 — Mapping (application mapping)

Goal: build a complete site map of endpoints, parameters, and technologies. This is when Burp Suite Proxy + the Target site map come into play (section 12.3.4). Techniques: - Spidering/Crawling: automatically following links. - Forced browsing / content discovery: guessing hidden paths (/admin, /.git/, /backup.zip) using ffuf, gobuster, dirsearch. - Analyzing robots.txt, sitemap.xml, and JS bundles to find API endpoints.

# Content discovery with ffuf
ffuf -u https://example.com/FUZZ -w /usr/share/wordlists/dirb/common.txt \
     -mc 200,204,301,302,307,401,403 -fs 0
# -u : URL with the keyword FUZZ replaced by each line of the wordlist
# -w : wordlist
# -mc: match HTTP status code (only show responses with this code)
# -fs: filter by response size (drop junk pages of the same size)

12.2.3. Phase 3 — Testing (vulnerability testing)

Cross-referenced with the OWASP Top 10 and WSTG. Each group of tests has a checklist: - Injection (SQLi, NoSQLi, command injection, LDAPi). - Broken Access Control (IDOR, privilege escalation, path traversal). - Authentication & Session (brute force, session fixation, weak token entropy). - XSS (reflected, stored, DOM-based). - SSRF, XXE, deserialization, business logic.

12.2.4. Phase 4 — Exploitation

Demonstrate impact: data exfiltration, privilege escalation, RCE. Stay strictly within scope — see 12.6. Record requests/responses as evidence. Avoid destructive actions unless the RoE permits.

12.2.5. Phase 5 — Reporting

The report includes: an Executive Summary (for leadership) and detailed technical content (for engineers), with each finding containing: a description, severity (CVSS), evidence (PoC, screenshot, request/response), impact, and specific remediation recommendations.

CVSS v3.1 — Base Score vector (essential for scoring severity):

Metric Symbol Values Meaning
Attack Vector AV N/A/L/P Network/Adjacent/Local/Physical
Attack Complexity AC L/H Low/High
Privileges Required PR N/L/H None/Low/High
User Interaction UI N/R None/Required
Scope S U/C Unchanged/Changed
Confidentiality C N/L/H None/Low/High
Integrity I N/L/H None/Low/High
Availability A N/L/H None/Low/High

Example vector string: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H = 9.8 (Critical) — typical of unauthenticated RCE over the network.

CVSS 4.0 (worth knowing): FIRST has released CVSS v4.0 (strings start with CVSS:4.0/...), which drops the Scope metric, splits Base into Exploitability + Vulnerable/Subsequent System Impact, and adds Safety (human harm) plus Supplemental/Threat/Environmental groups. Many sources still use v3.1 in parallel, so always state the version when quoting a score. (exact version/adoption to be verified over time)

Don't patch by Base score alone. The Base score only says how bad a flaw is "in theory" — not whether it's actually being exploited or even reachable in your system. In practice, prioritize patching by the combination of: (a) reachability — is the vulnerable component actually on the execution path / exposed externally (a lib present in the image but never called is low risk); (b) EPSS (Exploit Prediction Scoring System by FIRST) — probability of exploitation in the next 30 days; (c) CISA KEV (Known Exploited Vulnerabilities) — the catalog of CVEs actively exploited in the wild, which almost always jump the queue. A CVE 9.8 that isn't on a code path and isn't in KEV usually ranks below a CVE 7.5 already in KEV with a high EPSS.


12.3. Burp Suite — Detailed Analysis

Burp Suite (PortSwigger) is the flagship tool for manual web testing. There are three editions: Community (free, limited, Intruder is throttled, no Scanner), Professional (full Scanner, full Intruder), and Enterprise (CI/CD, large-scale automated scanning). Burp is written in Java and runs on the JVM.

12.3.1. The MITM Proxy Architecture

Burp acts as an intercepting proxy (man-in-the-middle) placed between the browser and the server. Data flow:

+---------+        +------------------+        +-----------+
| Browser | <----> |  Burp Proxy      | <----> |  Server   |
| (client)| HTTP/S |  127.0.0.1:8080  | HTTP/S |  (target) |
+---------+        +------------------+        +-----------+
                   |  - Intercept     |
                   |  - Re-issue cert |
                   |  - Log site map  |
                   +------------------+

By default Burp listens on 127.0.0.1:8080. The browser is configured to point its proxy here. Burp receives the request, can pause it (intercept), edit it, and then forward it to the server. When the server responds, Burp can again edit the response before delivering it to the browser.

Why a CA certificate must be installed

With plaintext HTTP, MITM is easy — Burp reads it directly. But with HTTPS, TLS encrypts everything. To be able to read/edit, Burp must terminate TLS on its side: it performs two separate TLS sessions — one with the browser, one with the server.

When the browser sends CONNECT example.com:443, Burp: 1. Generates, on-the-fly, a certificate for example.com, signed by Burp's root CA (named PortSwigger CA by default). 2. Presents this fake certificate to the browser. 3. The browser checks the chain of trust. If Burp's root CA has been installed into the OS/browser trust store → valid → no warning. If not installed → the warning NET::ERR_CERT_AUTHORITY_INVALID appears.

This is precisely why Burp's CA cert must be installed: so the browser trusts the certs Burp generates, allowing HTTPS MITM without warnings, while keeping the TLS session with the server genuinely valid.

Obtaining and installing the CA cert:

1. Configure the browser proxy to 127.0.0.1:8080
2. Visit http://burp  (or http://burpsuite)
3. Click "CA Certificate" -> download the cacert.der file
4. Install into the trust store:
   - Linux: convert DER->PEM then place it in /usr/local/share/ca-certificates/
   - Firefox: Settings -> Privacy & Security -> Certificates -> Import
     (check "Trust to identify websites")
# Convert DER to PEM and view the cert contents
openssl x509 -inform der -in cacert.der -out burp-ca.pem
openssl x509 -in burp-ca.pem -noout -text | grep -A2 'Subject:'
# Linux system-wide:
sudo cp burp-ca.pem /usr/local/share/ca-certificates/burp.crt
sudo update-ca-certificates

Security note: Burp's CA private key is stored in the user's configuration. If this key leaks, an attacker can MITM any machine that has installed that CA. Each Burp installation generates its own CA — do NOT share it. Remove the CA from the trust store after testing on a non-dedicated machine.

12.3.2. The HTTP Request Structure that Burp Manipulates

Burp displays raw HTTP requests in exact RFC 7230 format. Understanding each part is a prerequisite for editing accurately.

POST /api/v1/login HTTP/1.1\r\n          <- Request line: METHOD SP URI SP VERSION CRLF
Host: example.com\r\n                    <- Header
User-Agent: Mozilla/5.0\r\n
Content-Type: application/json\r\n
Content-Length: 41\r\n
Cookie: session=abc123\r\n
\r\n                                      <- Empty line (CRLF) separating header and body
{"username":"admin","password":"secret"} <- Message body (Content-Length bytes long)

Table of each part of an HTTP/1.1 request:

Component Size Meaning Example
Method variable (token) HTTP verb POST, GET
SP 1 byte (0x20) Separating space
Request-URI variable Path + query /api/v1/login
HTTP-Version 8 bytes Protocol version HTTP/1.1
CRLF 2 bytes (0x0D 0x0A) End of line \r\n
Header name token Field name Content-Type
: 2 bytes name/value separator :
Header value variable Value application/json
Empty line 2 bytes (CRLF) header/body boundary \r\n
Body = Content-Length Payload {...}

Why: Content-Length MUST match the actual number of body bytes. When editing the body in Repeater, if you do not update Content-Length, the server may hang (waiting for more bytes) or truncate the body. Burp Repeater has an "Update Content-Length" option to do this automatically. The HTTP Request Smuggling vulnerability exploits exactly this inconsistency between Content-Length and Transfer-Encoding: chunked that the front-end and back-end interpret differently.

12.3.3. The Proxy Module

Functions: Intercept, HTTP history, Match & Replace, WebSockets history.

Intercept on/off: When enabled, each request is paused at Burp and displayed for you to edit. Click "Forward" to send it on, "Drop" to discard it.

Match & Replace — rules that automatically replace content on every request/response. The structure of a rule:

Field Meaning Example
Type Scope of application Request header / Request body / Response header...
Match Regex or literal to find ^User-Agent:.*$
Replace Replacement string User-Agent: CustomAgent/1.0

A real-world example: add X-Forwarded-For: 127.0.0.1 to every request to test bypassing an IP allowlist:

Type:    Request header
Match:   (leave empty - add a new header)
Replace: X-Forwarded-For: 127.0.0.1

Scope filtering: History can grow very large. It is best to limit it by scope (next section) so that only legitimate targets are logged, avoiding logging personal traffic and avoiding touching out-of-scope hosts.

12.3.4. Target — Site Map and Scope

The Site Map is a hierarchical tree of host → directory → endpoint, accumulated from every request that passes through Burp (proxy, repeater, scanner). Each node stores the requests/responses seen.

Scope defines the "legitimate targets". It is configured under Target → Scope. There are two modes: - Include in scope: a list of allowed hosts/URLs. - Exclude from scope: exclusions (e.g., a logout page, a page that signs you out of SSO).

Scope affects: whether the Proxy logs, whether the Scanner scans, and whether Intruder/Repeater warn. An advanced scope definition:

Include:
  Protocol: HTTPS
  Host:     ^.*\.example\.com$
  Port:     ^443$
  File:     ^/api/.*$

Why (legal): Scope is a legal boundary. Scanning/exploiting outside scope = unauthorized access = breaking the law (see 12.6). The "Drop all out-of-scope traffic" option in the Proxy options prevents accidentally sending requests to out-of-scope hosts.

12.3.5. Repeater — Resending and Editing Requests

Repeater lets you send a single request multiple times with manual edits, viewing the response immediately. This is the primary tool for verifying and refining vulnerabilities. Send a request to Repeater from anywhere by right-clicking → "Send to Repeater" (Ctrl+R).

Example: testing IDOR (Insecure Direct Object Reference)

IDOR: the application allows access to another user's object simply by changing the ID, due to a missing server-side authorization check.

Original request (user A, id=1001):

GET /api/v1/orders/1001 HTTP/1.1
Host: shop.example.com
Cookie: session=eyJ1c2VyIjoiYWxpY2UifQ
Accept: application/json

Response: Alice's order (200 OK).

Test step: change 1001 → 1002 (someone else's order) and resend in Repeater:

GET /api/v1/orders/1002 HTTP/1.1
Host: shop.example.com
Cookie: session=eyJ1c2VyIjoiYWxpY2UifQ
Accept: application/json
  • If the response returns another user's order (200 + data) → IDOR confirmed. Alice can view someone else's order even though the session is still Alice's.
  • If it returns 403 Forbidden / 404 → access control is working correctly.

Defense: enforce server-side authorization (object-level access control), checking resource.owner_id == session.user_id; hard-to-guess UUIDs help but do NOT replace authorization.

Example: testing SQL Injection

Original request:

POST /api/v1/search HTTP/1.1
Host: shop.example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 10

q=keyboard

Test 1 — detecting a syntax error (error-based): insert a single quote:

q=keyboard'

If the response returns 500 with the message SQL syntax error near ''' → the backend concatenates SQL strings without parameterization → likely SQLi.

Test 2 — boolean-based: compare two conditions:

q=keyboard' AND '1'='1   -> returns normal results (TRUE)
q=keyboard' AND '1'='2   -> returns empty (FALSE)

Different behavior between TRUE/FALSE confirms injection.

Test 3 — UNION-based data extraction (after determining the column count):

q=keyboard' UNION SELECT username,password,NULL FROM users-- -

The -- - comments out the rest of the SQL. If the result returns usernames/passwords → data extraction succeeded.

Note: always update Content-Length when editing the body. URL-encode special characters when needed (' → %27, space → + or %20) depending on the Content-Type.

Defense: prepared statements / parameterized queries, a safe ORM, least privilege for the DB account, and a WAF as an additional defensive layer (not a replacement for the root fix).

12.3.6. Intruder — Automating Parameterized Attacks

Intruder sends many requests, substituting payloads into marked positions (denoted by §). There are 4 attack types:

Attack type Payload sets Distribution Number of requests Use case
Sniper 1 One position at a time, other positions unchanged (positions) × (payloads) Fuzz one parameter at a time
Battering ram 1 The same payload into ALL positions at once (payloads) When the same value is needed in several places
Pitchfork multiple (1/position) Taken in parallel by index: payload[i] at each position min(set lengths) Matching username+password pairs (credential stuffing)
Cluster bomb multiple (1/position) Cartesian product: every combination product of lengths Brute force all combinations of user × pass

How to mark payload positions

Burp places a pair of § characters around the value to fuzz:

POST /login HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 29

username=§admin§&password=§x§

Here there are 2 positions. With Cluster bomb + set1 (usernames) of 10 elements and set2 (passwords) of 100 elements → 1000 requests.

Example: brute-forcing login (Cluster bomb)

Attack type: Cluster bomb
Position 1 (username): payload = Simple list [admin, root, user, test]
Position 2 (password): payload = Runtime file / wordlist (trimmed rockyou)

Analyzing results: sort by the Status and Length columns. A failed login usually returns 200 + a body "Invalid credentials" of fixed length; a successful login may return 302 (redirect) or a body of a different length. Use the Length column to filter anomalies. Add a Grep-Match rule (e.g., look for the string "Welcome") to flag successful requests.

Example: parameter fuzzing (Sniper) to find SQLi/XSS

Attack type: Sniper
Position: §value§ in q=§test§
Payload set: SQLi fuzz list  (', '', ", `, ;, ' OR '1'='1, <script>...)
Payload processing: URL-encode all characters
Grep - Match: "SQL syntax", "ORA-", "ODBC"

Payload types in Intruder:

Payload type Description Example
Simple list A static list wordlist
Runtime file Read from a large file (not loaded entirely into RAM) rockyou.txt
Numbers Generate a range of numbers 1–10000, step 1
Brute forcer Generate character combinations charset abc, len 4
Username generator Generate usernames from names john.doe, jdoe
Bit flipper Flip each bit (test padding oracle, CSRF token) —

Security & operational notes: Intruder in Community Edition is throttled (slowed down). Brute forcing generates large amounts of traffic — it can cause account lockouts, WAF blocking, or accidental DoS. Always stay in scope. Use "Resource pool" to limit concurrent requests and set a delay to avoid locking accounts.

12.3.7. Decoder

Transforms and decodes data. It supports: URL, HTML entity, Base64, ASCII hex, Octal, Binary, Gzip, and Hash (MD5, SHA...). The "Smart decode" mode automatically guesses the encoding.

Example of decoding a JWT (3 parts header.payload.signature separated by .):

Input:  eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyIjoiYWRtaW4ifQ.<sig>
Decode as Base64 (part 1): {"alg":"HS256"}
Decode as Base64 (part 2): {"user":"admin"}

JWT uses Base64URL (replacing +→-, /→_, dropping = padding). Burp's Base64 decoder can handle it; note that you may need to add = padding.

12.3.8. Comparer

Compares two pieces of data by word or by byte, highlighting the differences in color. Used to: compare an admin account's response vs a normal user's (finding access-control discrepancies), compare TRUE vs FALSE responses in blind SQLi, and compare two tokens to analyze their structure.

12.3.9. Sequencer — Analyzing Token Entropy

Sequencer checks the randomness of session tokens / CSRF tokens / reset tokens. A guessable token = a serious vulnerability (session hijacking).

Mechanism: collect a large number of tokens (ideally several thousand samples), then run standard FIPS 140-2 statistical tests and Burp's own tests:

Test What it measures
FIPS Monobit The ratio of 0 and 1 bits is balanced
FIPS Poker The distribution of 4-bit groups
FIPS Runs The length of consecutive bit runs
FIPS Long runs Whether there is an excessively long run
Character/Bit transitions Correlation between positions

The result is measured in bits of effective entropy at a significance level (1% by default). A "good" token needs high entropy. A token generated from time (a timestamp) or an incrementing counter → low entropy → guessable.

Note: high entropy does not guarantee safety if the generation algorithm (PRNG) is not a CSPRNG. Sequencer only detects statistical patterns; it does not inspect the source algorithm.

12.3.10. Scanner (Professional only)

Burp's Scanner includes a passive part (analyzing already-seen traffic without sending additional requests — detecting cookies missing Secure/HttpOnly, sensitive information) and an active part (sending probing payloads — detecting SQLi, XSS, SSRF...). It is configured via "Scan configuration": choosing audit checks, crawl strategy, and depth.

Warning: An active scan sends real attack payloads (which can create junk data, trigger emails, modify state). Do NOT run an active scan on sensitive production systems without explicit authorization.

12.3.11. Complete Workflow for Testing a Vulnerability with Burp

Example: testing and confirming a Reflected XSS from start to finish.

Step 1 (Recon/Mapping): Enable the Proxy and browse the application normally.
        The site map accumulates the endpoint /search?q=...
Step 2 (Identifying the entry point): In the Proxy History, observe that the value of `q`
        is reflected into the HTML response.
Step 3 (Send to Repeater): Ctrl+R the request /search?q=test
Step 4 (Probing): Send q=<b>test</b>.
        - Inspect the response: if it returns `<b>test</b>` unescaped -> HTML reflect.
Step 5 (Proving JS execution):
        q=<script>alert(document.domain)</script>
        URL-encoded: q=%3Cscript%3Ealert(document.domain)%3C%2Fscript%3E
        - If the response contains <script>...</script> intact (not HTML-encoded)
          -> the payload will execute in the browser.
Step 6 (Verifying context): Use Comparer to compare the benign vs payload response
        to pinpoint exactly where it reflects and which filter is applied.
Step 7 (Bypass the filter if any): if < is filtered, try variants:
        - events: q="><img src=x onerror=alert(1)>
        - escape the attribute context
Step 8 (Evidence): capture the request/response, build a complete PoC URL.
Step 9 (Report): description, CVSS, PoC, recommendations (context-aware output encoding,
        CSP, set HttpOnly cookies).

XSS defense: context-aware output encoding (HTML, attribute, JS, URL), Content-Security-Policy, framework auto-escaping (React, Angular), and HttpOnly cookies so JS cannot read the session.


12.4. Acunetix — Automated DAST

12.4.1. What DAST Is and Where Acunetix Fits

DAST (Dynamic Application Security Testing) tests a running application from the outside (black-box) without needing source code — in contrast to SAST (Static, analyzing source code) and IAST (Interactive, with an agent inside the application). Acunetix is a commercial DAST scanner with a high degree of automation: it crawls, audits, and generates reports automatically.

Core differences between Acunetix and Burp:

Criterion Acunetix (automated DAST) Burp Suite (manual + Scanner)
Model Comprehensive automation Mainly manual, with a Scanner (Pro)
Users Run periodically, little intervention Experts working deeply
Business logic / IDOR Weak (machines struggle with logic) Strong (humans reason)
Scale Scan many sites, on a schedule Focused on one target
CI/CD integration Yes (API, scheduler) Enterprise edition
Payload tuning Limited Maximum flexibility

The two tools complement each other: Acunetix scans broadly to find low-hanging fruit, while Burp digs deep to verify and exploit logic.

12.4.2. Configuring a Scan

Acunetix calls a target a Target. The process for creating a scan:

1. Add Target: enter the root URL (https://app.example.com)
   - Description, Business Criticality (importance level for prioritization)
2. Target Settings:
   - Scan Speed: Slow/Moderate/Fast/Sequential (trade-off of speed vs server load)
   - Site Login:
       * Automatic (provide username/password, Acunetix logs in itself)
       * Recorded login sequence (record a complex login sequence)
   - Authentication: HTTP Basic/NTLM/custom header
   - Custom headers / cookies (e.g., Authorization: Bearer ...)
   - Excluded paths (e.g., /logout, /admin/delete-all)
   - Allowed hosts (limit scope to subdomains)
3. Scan Profile (Scan Type):
   - Full Scan / High Risk / Cross-site Scripting / SQL Injection /
     Weak Passwords / Crawl Only
4. Schedule: run now or on a periodic schedule (cron-like)
5. Launch Scan

A Recorded login sequence is important because many endpoints lie behind authentication. Acunetix uses AcuSensor (an optional IAST agent installed on PHP/.NET/Java servers) to improve accuracy and enable deeper detection (gray-box), reducing false positives.

12.4.3. The Crawl + Audit Mechanism

Acunetix runs in 2 stages:

Stage 1 — Crawl (DeepScan): uses an engine that browses like a real browser, executing JavaScript (supporting SPAs, AJAX), discovering every link, form, API endpoint, and parameter. The result: a list of "locations" and "inputs".

Stage 2 — Audit: for each discovered input, Acunetix sends probing payloads and analyzes the response: - SQLi: inject a payload and observe DB errors, delays (time-based: SLEEP(5)), or boolean differences. - XSS: inject a marker script and check for unescaped reflection. - SSRF, XXE, LFI/RFI, command injection: corresponding payloads. - Misconfiguration: missing security headers, directory listing, backup files.

Time-based blind SQLi payload illustration:

'; IF(1=1) WAITFOR DELAY '0:0:5'--      (MSSQL)
' OR SLEEP(5)-- -                        (MySQL)
' || pg_sleep(5)--                       (PostgreSQL)

Acunetix measures the response time: if the response is slow by ~5s when injecting SLEEP(5) but fast with SLEEP(0) → injection confirmed (blind, time-based).

12.4.4. Reading an Acunetix Report

The report classifies findings by severity: High / Medium / Low / Informational. Each finding includes:

Report field Meaning
Vulnerability name The vulnerability's name (e.g., "Blind SQL Injection")
Severity Level (High/Medium/Low/Info)
Affected URL/parameter The affected endpoint + parameter
Request The HTTP request that Acunetix sent (PoC)
Response / Evidence Evidence (DB error, delay, reflection)
CVSS The score
CWE Weakness classification (e.g., CWE-89 SQLi)
Recommendation Remediation guidance
Classification OWASP, PCI DSS, ...

The standard report templates: Developer, Executive Summary, Compliance (PCI DSS, ISO 27001, HIPAA, OWASP Top 10).

12.4.5. False Positives and Verification

Automated DAST is prone to false positives (reported but not actually exploitable) and false negatives (missed). The verification process: 1. Take the PoC request from the report. 2. Reproduce it manually using Burp Repeater or curl. 3. Observe whether the exploitation signs are correct (e.g., whether the time-based delay is consistent, or just due to the network). 4. Mark it as a false positive in Acunetix so it is skipped in the next scan.

Example of validating a time-based SQLi with curl:

# Measure the response time between SLEEP(0) and SLEEP(5)
time curl -s "https://app.example.com/item?id=1' OR SLEEP(0)-- -" >/dev/null
time curl -s "https://app.example.com/item?id=1' OR SLEEP(5)-- -" >/dev/null
# If the 2nd run is consistently ~5s slower -> a real SQLi, not a false positive

Note: an "Informational" finding (e.g., the server version leaking in a header) can be a puzzle piece for recon — do not ignore it entirely. Conversely, not every "High" is exploitable in a real context; verification is needed.


12.5. Nmap — Analysis Down to the Packet Level

Nmap (Network Mapper) is a tool for host discovery, port scanning, version/OS detection, and running scripts (NSE). Understanding Nmap requires understanding the TCP 3-way handshake and the TCP flags, because most scans operate directly on these flags.

12.5.1. Foundation — the TCP Header and Flags

The TCP segment header (RFC 793/9293). Byte-by-byte diagram:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|          Source Port          |       Destination Port        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                        Sequence Number                        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Acknowledgment Number                      |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|  Data | Res |N|C|E|U|A|P|R|S|F|                               |
| Offset|     |S|W|C|R|C|S|S|Y|I|            Window             |
|       |     | |R|E|G|K|H|T|N|N|                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           Checksum            |         Urgent Pointer        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                    Options (if Data Offset > 5)               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Table of TCP header fields:

Field Size Meaning Example
Source Port 16 bits (2 bytes) Source port 49152
Destination Port 16 bits Destination port 443
Sequence Number 32 bits (4 bytes) Byte sequence number 0x1A2B3C4D
Acknowledgment Number 32 bits ACK of the next expected seq number 0x1A2B3C4E
Data Offset 4 bits Header length (in 32-bit words) 5 = 20 bytes
Reserved 3 bits Reserved (0) 0
Flags 9 bits NS,CWR,ECE,URG,ACK,PSH,RST,SYN,FIN see below
Window 16 bits Receive window size 64240
Checksum 16 bits Error check of header+data+pseudo-header 0x...
Urgent Pointer 16 bits Offset of urgent data (if URG) 0
Options 0–40 bytes MSS, SACK, Timestamp, Window scale MSS=1460

Control flags — each flag is 1 bit:

Flag Meaning when =1
SYN Request to establish a connection (synchronize seq)
ACK The Acknowledgment field is valid
FIN Finished sending data (graceful close)
RST Reset/reject the connection immediately
PSH Push data to the application immediately
URG There is urgent data

TCP 3-way handshake (connection establishment):

Client                         Server
  | --- SYN (seq=x) ----------> |     state: SYN_SENT -> server SYN_RECV
  | <-- SYN,ACK (seq=y,ack=x+1) |
  | --- ACK (ack=y+1) --------> |     state: ESTABLISHED on both sides

Nmap exploits this behavior: a server with an open port replies with SYN/ACK, a server with a closed port replies with RST.

12.5.2. -sS — SYN scan (half-open / stealth)

Mechanism: Nmap sends a SYN but does NOT complete the handshake.

Port OPEN:
  Nmap --- SYN ------------> Target
  Nmap <-- SYN/ACK -------- Target
  Nmap --- RST -----------> Target   (Nmap actively tears down, does not send ACK)
  => conclusion: open

Port CLOSED:
  Nmap --- SYN ------------> Target
  Nmap <-- RST ------------ Target
  => conclusion: closed

Port FILTERED (firewall drop):
  Nmap --- SYN ------------> Target
  (no response, retries a few times, still silent)
  => conclusion: filtered

Why "stealth": because the handshake is not completed (it does not reach ESTABLISHED), many older applications/logs do not record the connection (they only log after accept()). However, modern IDS/IPS detect it easily. A SYN scan requires raw socket privileges (root/CAP_NET_RAW) because Nmap crafts its own TCP packets, bypassing the OS connect().

sudo nmap -sS -p 1-1000 192.168.1.10

Sample output:

PORT     STATE    SERVICE
22/tcp   open     ssh
80/tcp   open     http
443/tcp  open     https
3306/tcp filtered mysql

12.5.3. -sT — TCP Connect scan

Mechanism: Nmap calls the OS connect() syscall, completes the full 3-way handshake, then closes (sends FIN or RST).

Nmap --- SYN -------> Target
Nmap <-- SYN/ACK ---- Target
Nmap --- ACK -------> Target    (fully ESTABLISHED)
Nmap --- RST/FIN ---> Target    (close)

When to use: when you do not have root privileges (no raw socket). Trade-off: it creates a full connection → the application logs it → less stealthy and slower.

nmap -sT -p 22,80,443 192.168.1.10   # no sudo needed

12.5.4. -sU — UDP scan

UDP has no handshake (connectionless). The inference mechanism:

Port CLOSED:
  Nmap --- UDP packet ----> Target
  Nmap <-- ICMP Port Unreachable (type 3, code 3) -- Target
  => closed

Port OPEN:
  Nmap --- UDP packet ----> Target
  - If the UDP service returns data => open
  - If there is NO response at all => open|filtered (ambiguous)

Port FILTERED:
  Nmap --- UDP ----> Target
  Nmap <-- ICMP type 3 code 1,2,9,10,13 (admin prohibited...) => filtered

Why UDP scans are slow: because there is no RST to definitively indicate "closed", Nmap relies on ICMP Port Unreachable; but RFC 1812 rate-limits ICMP emission, so Nmap must wait and retry → very slow. For better accuracy on common ports, Nmap sends service-specific payloads (a DNS query to 53, SNMP to 161).

sudo nmap -sU --top-ports 20 192.168.1.10   # scan the 20 most common UDP ports

12.5.5. -sN / -sF / -sX — Null, FIN, Xmas scan

These three scans exploit the RFC 793 rule: if a TCP packet arrives at a closed port WITHOUT the SYN/RST/ACK flags → the server must reply with RST; if the port is open → the server ignores it (no response).

Scan Flags set Packet description
-sN Null (no flags) All flags = 0
-sF FIN FIN Only FIN = 1
-sX Xmas FIN+PSH+URG "Lit up like a Christmas tree"
Port OPEN or FILTERED:
  Nmap --- (FIN/Null/Xmas) ---> Target
  (no response)  => open|filtered

Port CLOSED:
  Nmap --- (FIN/Null/Xmas) ---> Target
  Nmap <-- RST ---------------- Target  => closed

Why use it: it can get past stateless firewalls that only filter SYN packets. An important limitation: Windows (and many devices) do NOT comply with this standard RFC behavior — they always reply with RST regardless of whether the port is open/closed → every port shows "closed" → the scan is useless on Windows. It is only effective against RFC-compliant systems (many Unix-like systems).

sudo nmap -sX -p 1-100 192.168.1.10

12.5.6. -sn — Host Discovery (ping scan, no port scanning)

-sn (formerly -sP) only determines which hosts are "alive" without scanning ports. The default mechanism (when run with root privileges) sends a combination of probes:

Probe Packet sent Purpose
ICMP Echo Request ICMP type 8 Classic ping
ICMP Timestamp ICMP type 13 Fallback when Echo is blocked
TCP SYN to 443 SYN Infer a live host from the response
TCP ACK to 80 ACK Get past firewalls that filter SYN
ARP request (LAN) ARP who-has On the same subnet — the most reliable

On a LAN, Nmap uses ARP (layer 2) because a host is required to reply with an ARP reply if it exists — bypassing layer-3 firewalls.

sudo nmap -sn 192.168.1.0/24      # list live hosts in a /24 subnet

Output:

Nmap scan report for 192.168.1.1
Host is up (0.0012s latency).
MAC Address: AA:BB:CC:DD:EE:FF (Vendor)
Nmap scan report for 192.168.1.10
Host is up (0.0023s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 2.34 seconds

-Pn (no ping) skips host discovery and treats every host as alive — use this when the target blocks ICMP.

12.5.7. -sV — Version detection

After identifying open ports, -sV determines the service and version running on them. Mechanism: 1. Connect to the open port. 2. If the service sends a banner itself (e.g., SSH, SMTP) → read it and match it against nmap-service-probes. 3. If it is silent → Nmap sends a series of probes (protocol-specific byte sequences) and matches the response against the thousands of regex signatures in nmap-service-probes.

--version-intensity 0-9 adjusts the number of probes sent (0 = few/fast, 9 = full).

sudo nmap -sV -p 22,80,443 192.168.1.10

Output:

PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 8.9p1 Ubuntu 3ubuntu0.4 (Ubuntu Linux; protocol 2.0)
80/tcp  open  http     nginx 1.18.0 (Ubuntu)
443/tcp open  ssl/http nginx 1.18.0

An accurate version → look up the corresponding CVEs (the foundation for vulnerability scanning).

12.5.8. -O — OS detection

-O guesses the operating system via TCP/IP stack fingerprinting: it sends many specially-designed probes and analyzes the response characteristics that each OS implements differently:

Characteristic analyzed Meaning
Initial TTL The starting TTL (Linux 64, Windows 128, some 255)
TCP Window Size The default window size
TCP Options & order MSS, NOP, SACK, Timestamp, Window scale and their order
Don't Fragment bit Whether DF is set
ISN sampling How the Initial Sequence Number is generated
ICMP responses Responses to anomalous probes

Nmap matches the fingerprint against nmap-os-db. It needs ≥1 open port AND ≥1 closed port for accuracy.

sudo nmap -O 192.168.1.10

Output:

Running: Linux 5.X
OS CPE: cpe:/o:linux:linux_kernel:5
OS details: Linux 5.0 - 5.14
Network Distance: 2 hops

12.5.9. -p — Specifying ports, and -F

Syntax Meaning
-p 80 A single port
-p 22,80,443 A list
-p 1-1000 A range
-p- All of 1–65535
-p U:53,T:80 Separate UDP/TCP
-F Fast — the 100 most common ports
--top-ports 20 The 20 most common ports (per nmap-services)

12.5.10. -T — Timing templates

-T0 through -T5 adjust speed via several parameters (delay between probes, parallelism, timeout):

Template Name Characteristics Use case
-T0 Paranoid Extremely slow, sequential, delays up to 5 minutes Maximum IDS evasion
-T1 Sneaky Slow, 15s delay IDS evasion
-T2 Polite Reduced load, little parallelism Sensitive networks
-T3 Normal Default Balanced
-T4 Aggressive Fast, for stable networks Typical pentest
-T5 Insane Extremely fast, may drop packets Fast LAN, accepting inaccuracy

-T4 is a common choice on a good network. It can be fine-tuned in detail: --min-rate, --max-rate (packets/s), --max-retries, --host-timeout.

12.5.11. NSE — Nmap Scripting Engine

NSE runs Lua scripts to extend Nmap: vulnerability detection, brute forcing, information gathering. Scripts live in /usr/share/nmap/scripts/, organized by category:

Category Purpose Intrusiveness
safe Harmless, does not exploit Low
default (-sC) Run by default, useful & safe Low
discovery Gather more information Low
version Supports -sV Low
auth Authentication-related Medium
brute Brute force credentials High (generates traffic)
vuln Check for known vulnerabilities Medium-High
exploit Actually exploit High (dangerous)
dos Test for DoS Very high (may crash the service)
intrusive May cause load/harm High
# Run the default scripts + version
sudo nmap -sC -sV 192.168.1.10

# Scan for known vulnerabilities
sudo nmap --script vuln -p 80,443 192.168.1.10

# A specific script
sudo nmap --script http-title,http-headers -p 80 192.168.1.10
sudo nmap --script smb-vuln-ms17-010 -p 445 192.168.1.10   # detect EternalBlue
sudo nmap --script ssl-enum-ciphers -p 443 192.168.1.10    # enumerate TLS ciphers

Sample output of --script vuln:

PORT   STATE SERVICE
80/tcp open  http
| http-slowloris-check:
|   VULNERABLE:
|   Slowloris DoS attack
|     State: LIKELY VULNERABLE
|     IDs:  CVE:CVE-2007-6750

Passing script arguments (--script-args):

sudo nmap --script http-brute --script-args \
  http-brute.path=/login,userdb=users.txt,passdb=pass.txt -p 80 target

12.5.12. A Comprehensive Scan Command and Its Output

sudo nmap -sS -sV -O -p- -T4 --script default,vuln -oA fullscan 192.168.1.10
# -sS  : SYN scan
# -sV  : version detection
# -O   : OS detection
# -p-  : all 65535 ports
# -T4  : aggressive timing
# --script default,vuln : NSE
# -oA fullscan : output in 3 formats (.nmap, .gnmap, .xml) named fullscan

Output formats:

Flag Format Used for
-oN file Normal (like the screen) Human reading
-oG file Greppable Quick grep/awk processing
-oX file XML Parsing by script, importing into other tools
-oA base All 3 above Complete archival

Quick greppable analysis:

grep "open" fullscan.gnmap | awk '{print $2}'   # list IPs with open ports

12.5.13. Reading Port States

Nmap distinguishes 6 states:

State Meaning
open A service is listening and accepting
closed The host responds but there is no service (returns RST)
filtered Cannot be determined — a firewall blocks the probe
unfiltered Reachable but open/closed is unclear (ACK scan)
open\|filtered Cannot be distinguished (UDP, silent FIN/Null/Xmas)
closed\|filtered Rare (Idle scan)

This is a section NOT to be taken lightly — testing outside the authorized scope is unauthorized access to a computer system and may be subject to criminal prosecution.

  • Vietnam: the Penal Code 2015 (amended and supplemented in 2017), Article 289 (unauthorized access to computer/telecommunications networks), Article 287 (obstructing/disrupting network operations); the Cybersecurity Law 2018; the Law on Network Information Security 2015. (Readers should verify the current article numbers at the time of application — the regulations may have been amended.)
  • International references: the Computer Fraud and Abuse Act (CFAA — USA), the Computer Misuse Act (UK).

Port scanning or sending payloads to a system WITHOUT authorization = a violation, regardless of whether actual harm is caused.

12.6.2. Mandatory Documents Before Testing

Document Role
Scope of Work (SoW) Clearly defines the assets, IPs/domains, and types of testing permitted
Rules of Engagement (RoE) Time window, prohibited techniques (e.g., DoS), emergency contact
Authorization Letter ("get-out-of-jail") A signed authorization document from an authorized person
NDA Confidentiality of the data discovered

12.6.3. Principles for Safe Operation

  • Do NOT scan/exploit outside the list of IPs/domains in scope. In Burp: enable "Drop all out-of-scope traffic".
  • Avoid destructive techniques (--script dos, brute force causing lockouts) unless explicitly authorized and within a maintenance window.
  • Be careful with cloud assets: AWS/GCP/Azure require compliance with their own pen-test policies; some managed services are forbidden from being tested.
  • Log every action (with timestamps) as evidence of scope and to support investigation in case of an incident.
  • Sensitive data extracted during testing must be stored encrypted and securely deleted after completion, in accordance with the NDA.

12.7. Chapter Summary

This chapter went from distinguishing the concepts (scanning vs pentest), through the 5-phase OWASP process, to the three pillar tools with detail down to the packet/field/step level and runnable examples:

  • Burp Suite — deep manual control: the MITM architecture with a CA cert, Proxy, Target/Scope, Repeater (IDOR, SQLi), Intruder (4 attack types), Decoder, Comparer, Sequencer, Scanner; the end-to-end XSS workflow.
  • Acunetix — automated DAST: crawl + audit, scan configuration, reading reports, verifying false positives; complements rather than replaces Burp.
  • Nmap — network mapping down to the TCP flag level: -sS/-sT/-sU/-sN/-sF/-sX, -sn host discovery, -sV/-O fingerprinting, -p/-T tuning, NSE (--script vuln), reading states and exporting results.

The overarching principle: understand the mechanics down to the root, always manually verify automated results, and absolutely respect the legal scope.


My notes

Personal notes: points I previously misunderstood, areas I'm still exploring, or lessons from hands-on practice — updated over time.