Skip to content
Pentesting and ethical hacking

The phases of a penetration test, walked through on a fictional company

Penetration testing phases on a fictional fintech: scoping, recon, scanning, exploitation, post-exploitation and reporting, mapped to NIST and PTES.

LearnCyber editorial team, reviewed by Hackrowd Technology’s penetration testers · · 8 min read

A penetration test runs in six practical phases: scoping and rules of engagement, reconnaissance, scanning and enumeration, exploitation, post-exploitation, and reporting. Most of the value, and most of the risk, sits in the first and last phases, not in the exciting middle.

To make that concrete, we will follow one engagement from start to finish against Acme Fintech, a fictional payments start-up at acme-fintech.test. Everything below ran in a lab built for this post: private 10.x addresses, a .test domain that cannot exist on the public internet, and seeded vulnerabilities. Only test systems you own or have written permission to test.

Which methodology do penetration testers follow?

Two public references describe the phases, and it helps to see how they line up.

NIST SP 800-115, Technical Guide to Information Security Testing and Assessment, describes penetration testing in four phases: Planning, Discovery, Attack and Reporting, with the Attack phase looping back into Discovery as new access reveals new systems. It dates from 2008, but its structure still holds.

The Penetration Testing Execution Standard (PTES) splits the work into seven sections: Pre-engagement Interactions, Intelligence Gathering, Threat Modelling, Vulnerability Analysis, Exploitation, Post Exploitation and Reporting.

Practical phase (this post) NIST SP 800-115 PTES
1. Scoping and rules of engagement Planning Pre-engagement Interactions
2. Reconnaissance Discovery Intelligence Gathering, Threat Modelling
3. Scanning and enumeration Discovery Vulnerability Analysis
4. Exploitation Attack Exploitation
5. Post-exploitation Attack (and back to Discovery) Post Exploitation
6. Reporting Reporting Reporting

Neither framework is a checklist you tick in order. Real tests loop: something you find in phase 4 sends you back to phase 2 with a new question.

Phase 1: Scoping and rules of engagement

Acme Fintech’s CTO wants “a pentest before our Series A”. That is not a scope. The scoping call turns it into something testable and legally safe.

What we agreed with Acme (fictional):

  • In scope: app.acme-fintech.test (customer web app), api.acme-fintech.test (REST API used by the mobile app), and the lab’s stand-in ‘external’ range 10.10.20.0/28.
  • Out of scope: the card processor’s systems (a third party Acme does not own), staff personal devices, and denial-of-service testing.
  • Test accounts: two customer accounts (tester-a, tester-b) and one support-staff account, created by Acme for the test.
  • Window: weekdays 09:00–18:00 WAT, with a named contact on each side and an emergency phone number.
  • Data handling: if we reach real customer data, we stop, take the minimum evidence (a record count and one redacted sample), and call the contact.
  • Source IPs: our testing addresses are listed so Acme’s monitoring team can tell us apart from a real attacker.

All of that goes into a signed rules of engagement document alongside the contract. The signature matters: it is the difference between a penetration test and an offence. If the client cannot confirm they own an asset, it comes out of scope until they can.

Beginner lesson: most junior testers get into trouble here, not in exploitation. Re-read the scope before every session and keep it open in a second window.

Phase 2: Reconnaissance

Reconnaissance means learning about the target before touching it hard. It is split into passive work (public sources, no direct contact) and light active work (DNS lookups and fetching the homepage like any visitor would).

In a real engagement, passive sources include certificate transparency logs, public code repositories, job adverts that name the tech stack, and DNS records. In our lab, Acme’s internal DNS answers for the .test zone:

dig +short app.acme-fintech.test
dig +short api.acme-fintech.test
dig +short TXT acme-fintech.test
10.10.20.5
10.10.20.6
“v=spf1 include:_spf.mailhost.example.com -all”

Then a polite look at what the web servers say about themselves:

curl -sI https://app.acme-fintech.test
HTTP/2 200
server: nginx/1.24.0
content-type: text/html; charset=utf-8
x-powered-by: Express
set-cookie: sid=s%3A9f2c...; Path=/; HttpOnly; Secure

Two notes go straight into our working file: the app is Node.js behind nginx, and it leaks x-powered-by: Express. Not a vulnerability on its own, but it tells us what kind of bugs to look for.

PTES puts threat modelling here, and it is worth five minutes even on a small test. For a fintech the obvious question is: what would a criminal want? Answer: other customers' money and data. So the API’s authorisation checks become our top priority.

Phase 3: Scanning and enumeration

Now we map what is listening and what it runs. A full TCP port scan of the in-scope range, with service detection:

sudo nmap -sS -sV -p- --min-rate 1000 -oA acme-full 10.10.20.0/28
Nmap scan report for app.acme-fintech.test (10.10.20.5)
PORT    STATE SERVICE  VERSION
22/tcp  open  ssh      OpenSSH 9.6p1 Ubuntu 3ubuntu13 (Ubuntu Linux; protocol 2.0)
443/tcp open  ssl/http nginx 1.24.0

Nmap scan report for api.acme-fintech.test (10.10.20.6)
PORT     STATE SERVICE  VERSION
443/tcp  open  ssl/http nginx 1.24.0
9000/tcp open  http     Node.js Express framework

Nmap done: 16 IP addresses (2 hosts up) scanned in 41.87 seconds

-oA saves output in all three Nmap formats, which you will want as evidence later. The Nmap reference guide explains every flag used here. Port 9000 on the API host is interesting: it looks like the Node app answering directly, bypassing nginx.

Next, content discovery on the web app with a wordlist:

ffuf -u https://app.acme-fintech.test/FUZZ \
     -w /usr/share/seclists/Discovery/Web-Content/common.txt \
     -mc 200,301,302,403 -rate 50
admin                   [Status: 302, Size: 28, Words: 4, Lines: 1]
api-docs                [Status: 200, Size: 3104, Words: 211, Lines: 77]
login                   [Status: 200, Size: 4410, Words: 512, Lines: 98]
.env                    [Status: 403, Size: 153, Words: 3, Lines: 8]

We kept the request rate low (-rate 50) because the rules of engagement exclude anything that looks like denial of service. api-docs is public Swagger documentation, which hands us a full list of API endpoints, including GET /v1/accounts/{accountId}/statements.

A vulnerability scanner might run here too. Treat scanner output as leads, not findings: every item needs manual confirmation before it reaches the report.

Phase 4: Exploitation

Exploitation means proving that a weakness is real and showing its impact, with the smallest action that does so.

Log in as tester-a, whose account ID is 100481, and request our own statements:

curl -s -H “Authorization: Bearer $TOKEN_A” \
  https://api.acme-fintech.test/v1/accounts/100481/statements | jq ‘.[0]’
{
  “accountId”: 100481,
  “owner”: “tester-a”,
  “period”: “2026-09”,
  “closingBalance”: “15000.00”
}

Now change one number, to tester-b's account (which Acme also created for us), still using tester-a’s token:

curl -s -H “Authorization: Bearer $TOKEN_A” \
  https://api.acme-fintech.test/v1/accounts/100482/statements | jq ‘.[0]’
{
  “accountId”: 100482,
  “owner”: “tester-b”,
  “period”: “2026-09”,
  “closingBalance”: “8200.00”
}

The API checks that we are logged in but not that the account belongs to us. This is broken object level authorisation, number one on the OWASP API Security Top 10 (2023). Note what we did not do: we did not loop through thousands of IDs pulling real customers' statements. Two test accounts prove the flaw; harvesting real data proves nothing extra and breaks the data-handling rule.

If you want to practise this exact class of bug legally, PortSwigger’s free Web Security Academy access-control labs are excellent.

Phase 5: Post-exploitation

Post-exploitation asks: now that we have a foothold, how far could a real attacker go, and what does that mean for the business?

Back in phase 3 we saw Express listening directly on port 9000. Requesting .env, which nginx blocks on the public port (a quick check of https://api.acme-fintech.test/.env returned 403), directly from Express on port 9000:

curl -s http://10.10.20.6:9000/.env | sed -E ‘s/=.*/=[redacted]/’
NODE_ENV=[redacted]
DB_HOST=[redacted]
DB_USER=[redacted]
DB_PASSWORD=[redacted]
JWT_SECRET=[redacted]

We redacted the values on our side as we captured them, so secrets never land in our notes in clear text. The finding is severe on its own: with the JWT signing secret, an attacker could forge a token for any user, including support staff.

The rules of engagement now decide what happens next. Acme’s say we may demonstrate impact but must not touch production data. So we:

  1. Confirm the JWT secret is valid by forging a token for our own test account only, and checking it is accepted.
  2. Stop. We do not log into the database, even though we have the credentials.
  3. Call Acme’s named contact the same day, because exposed production secrets need rotating now, not in two weeks when the report lands.

This is where NIST’s Attack phase loops back to Discovery: the new access would open new targets (the database host), and the scope tells us whether we may follow it. Here, we may not.

Cleanup is part of this phase too: remove any test files or accounts you created, and list everything you changed in the report.

Phase 6: Reporting

The report is the product. Acme is not paying for the moment the IDOR worked; it is paying for a document that lets developers fix the problem and lets the CTO explain the risk to investors.

A good finding has a consistent shape:

Field Example for the BOLA finding
Title Customers can read other customers' statements (broken object level authorisation)
Severity Rated with CVSS v4.0 plus a business-context note
Affected asset GET /v1/accounts/{accountId}/statements on api.acme-fintech.test
Description What is wrong, in plain English first, technical detail second
Evidence The two requests above, with timestamps and redacted tokens
Impact Any logged-in customer could read any other customer’s statements
Remediation Check on every request that the account ID belongs to the authenticated user; add automated tests for it
Retest status Open, pending fix

Write an executive summary a non-technical director can read in two minutes, then the detailed findings for engineers. Our separate guide, How to write a penetration testing report, includes a full sample built on this same fictional company.

Most engagements end with a retest: once Acme fixes the issues, we repeat the exact requests and update each finding’s status.

How long does each phase take?

It depends on scope, but as a rough shape for a small web and API test: scoping happens before the test window opens, recon and scanning take a meaningful share of the first days, exploitation and post-exploitation take the middle, and reporting takes longer than beginners expect. Budget real time for writing; a rushed report undoes a careful test.

What beginners get wrong about the phases

  • Skipping recon. Jumping straight to exploits means missing things like a public api-docs page.
  • Trusting the scanner. Unconfirmed scanner output in a report damages your credibility fast.
  • Proving too much. Impact is shown with the minimum action. Dumping a database is not better evidence than two test accounts.
  • Keeping secrets in notes. Redact as you capture.
  • Leaving the report until the end. Write findings up while the evidence is fresh.

If you are wondering which tools to learn for each phase, see Penetration testing tools: a beginner’s toolkit, and for the career route itself, How to become a penetration tester from scratch.

Questions

What are the 5 phases of penetration testing?

Many courses list five: reconnaissance, scanning, gaining access, maintaining access and covering tracks. That model describes an attacker. A professional test adds scoping at the start and reporting at the end, and replaces "covering tracks" with documented cleanup.

Is vulnerability scanning the same as penetration testing?

No. Scanning finds possible weaknesses; a penetration test confirms them manually and shows what an attacker could do with them.

What is the most important phase?

Scoping, because it makes the test legal and safe, and reporting, because it is what the client uses.

Do I need written permission even for a quick scan?

Yes. Get written authorisation from someone who owns the system before any testing.