net/go.book
All Parts Marketing

Penetration Testing Workflows

"A fire drill isn't useful because you hope for a fire — it's useful because it proves the exits actually work. A penetration test is a fire drill for your network, run by someone trying, on purpose and with permission, to find the exit that doesn't."


What a Penetration Test Actually Is

A penetration test ("pentest") is an authorized, scoped simulation of a real attack against a system, with the explicit goal of finding and demonstrating exploitable weaknesses before a real adversary does. The key words are authorized and scoped — everything that follows in this chapter assumes both are in place before any technical work starts.

Unlike a vulnerability assessment (Chapter 5.6), which is broad and largely automated, a penetration test is narrower and manual: a smaller set of targets, explored deeply, often chaining multiple minor findings into one demonstrated, significant impact — the difference between "this port is open" and "an open port led to a shell on the internal network."


The Phases

Most pentesting methodologies (PTES (Penetration Testing Execution Standard), OWASP Testing Guide, and others) converge on a similar shape:

It's worth internalizing that reporting is not an afterthought — for most clients, the report is the entire value of the engagement. A brilliant exploit chain that never gets written up clearly, with reproducible steps and a fix recommendation, delivers close to zero value.


Rules of Engagement

Before any technical work begins, a professional engagement is bounded by a written agreement covering:

  • Scope — exactly which systems, IP ranges, or applications are in bounds (and explicitly, which are not).
  • Timing — the testing window, and whether production hours are off-limits for anything risky (like a DoS-adjacent test).
  • Permitted techniques — whether social engineering, physical access attempts, or actual denial-of-service testing are authorized, since not every engagement wants all of them.
  • Emergency stop conditions — who to call immediately if a test causes unexpected impact.
  • Data handling — how discovered sensitive data is stored, reported, and eventually destroyed.

No authorization, no test
Every technique described anywhere in this book — scanning, sniffing, exploitation basics — is only appropriate to run under this kind of explicit authorization: your own lab, a licensed practice platform, a CTF, or a signed rules-of-engagement document. Without it, the exact same actions are unauthorized computer access, a crime in essentially every jurisdiction, regardless of intent.


Black Box, White Box, and Grey Box

Engagements are often categorized by how much information the tester starts with:

  • Black box — the tester starts with nothing beyond a target name or IP range, mimicking an external attacker with no inside knowledge.
  • White box — the tester is given full information: source code, architecture diagrams, credentials — useful for a deep, efficient review rather than simulating a realistic attacker.
  • Grey box — a middle ground, often the most realistic and cost-effective: some information (like a low-privilege account) is provided, mirroring what a real attacker could plausibly obtain early on.

A Minimal Engagement Tracker

Real engagements use dedicated case-management tooling, but the underlying structure is simple enough to model directly — useful for keeping even a small, single-tester engagement organized:

package main

import "fmt"

type Finding struct {
	Title    string
	Severity string // "critical", "high", "medium", "low", "info"
	Status   string // "open", "verified", "reported", "remediated"
}

type Engagement struct {
	Client   string
	Scope    []string
	Findings []Finding
}

func (e *Engagement) summary() {
	fmt.Printf("Engagement: %s\n", e.Client)
	fmt.Printf("Scope: %v\n", e.Scope)
	counts := map[string]int{}
	for _, f := range e.Findings {
		counts[f.Severity]++
	}
	fmt.Printf("Findings by severity: %v\n", counts)
}

func main() {
	eng := Engagement{
		Client: "internal-lab",
		Scope:  []string{"10.0.4.0/24"},
		Findings: []Finding{
			{"Unauthenticated admin panel", "critical", "verified"},
			{"Outdated TLS version accepted", "medium", "reported"},
		},
	}
	eng.summary()
}

This is intentionally minimal, but it captures the shape every real report is built from: a defined scope, a list of findings each with a severity and a status, and a summary a client can act on.


Frequently Asked Questions

If I have good intentions, is it still illegal to test a system without permission? Yes, and intent barely matters legally — unauthorized access statutes in essentially every jurisdiction care about whether you had permission, not whether you meant well or planned to report what you found responsibly. The Warning above isn't a formality; a scan or exploitation attempt run without a signed rules-of-engagement document is the same crime whether it's done by a curious hobbyist or a malicious attacker.

Why does black box testing exist if white box finds more vulnerabilities faster? Because "find the most vulnerabilities" isn't always the actual goal — sometimes the client specifically wants to know what a real external attacker with zero inside knowledge could achieve, and handing over source code and architecture diagrams would answer a different question than the one they're asking. Grey box exists precisely because it splits the difference: realistic enough to mirror a plausible attacker, efficient enough not to waste the engagement's limited time on pure discovery.

What should I do if an exploitation attempt during a test causes an unexpected outage? Stop immediately and follow the emergency stop conditions agreed upon before testing began — that's exactly why they're a mandatory line item in the rules of engagement, not an optional nicety. Continuing to poke at a system that's already misbehaving, hoping to finish the finding, is how a contained accident during an authorized test turns into a real incident with real consequences.

I found a critical vulnerability with a great exploit chain — isn't that the deliverable? Not on its own. As the chapter stresses, reporting is the actual value most clients are paying for, and an exploit chain that never gets written up with reproducible steps, evidence, and a concrete fix delivers close to nothing to a client who now has to decide what to patch first. A "verified" finding with no clear writeup is barely more useful to the client than a "reported but unconfirmed" one — the report is what turns the work into action.


Why This Matters Even If You Never Do This Job

Most readers of this book will build software, not run pentests professionally — but understanding this workflow reshapes how you read a pentest report handed to you about your own system: you'll know why scope matters, why "verified" is different from "reported but unconfirmed," and why a well-written finding always includes clear reproduction steps and a concrete fix, not just a scary severity label.