Move all pages into template-able functions, add black/grey/white box explanation appendix

This commit is contained in:
maride 2025-11-17 14:42:15 +01:00
parent 078f4486c6
commit 11fe5e95ef
3 changed files with 205 additions and 143 deletions

View File

@ -124,17 +124,7 @@
#let placeholder(value) = {
highlight(
fill: rgb(0xff, 0xa2, 0x9c, 0xff),
// Check which kind of placeholder is requested
if type(value) == str [
#if value.len() == 0 [
#lorem(30)
] else [
#value
]
] else [
#value
]
value
)
context(

184
main.typ
View File

@ -1,13 +1,11 @@
#import "@preview/diagraph:0.3.6": render
#import "pages.typ"
#import "helper.typ"
// Project-specific values
// Project-specific variables
#helper.panicOnPlaceholder.update(false)
#let place = helper.placeholder("Düsseldorf")
#let author = helper.placeholder("Martin \"maride\" Dessauer")
#let targetFull = helper.placeholder("FooBar Dummy Lab")
#let targetHandy = helper.placeholder("Dummy Lab")
#let targetInSentence = helper.placeholder("the Dummy Lab")
// ---
@ -16,8 +14,11 @@
v(1em)
par(text(it.body, fill: color.linear-rgb(4.5%, 14.5%, 14.5%, 255)))
}
#set heading(numbering: "1.1")
#set par(justify: true)
#pages.cover(targetFull, author)
// ----- Cover & Legal disclaimer(s) -----
#pages.cover(targetFull, place, author)
#pages.legal(author)
#set page(
@ -29,137 +30,82 @@
#text(fill: silver, [Penetration Test Report #targetFull])
#h(1fr)
#context(
text(fill: silver,
counter(page).display("1 of 1", both: true)
)
text(fill: silver, counter(page).display("1 of 1", both: true))
)
]
)
// ----- Table of contents -----
#pages.toc()
#set heading(numbering: "1.1")
#set par(justify: true)
= Management Summary
== Motivation
This penetration test was conducted to proactively identify, assess, and validate the severity of security vulnerabilities within the defined scope of #targetInSentence, specifically those exploitable by #helper.placeholder("external attackers in real-world scenarios"). Adversarial techniques to bypass controls, gain unauthorized access, and compromise critical assets were performed for this test scenario to determine the actual impact on confidentiality, integrity, and availability.
== Test Object
#helper.placeholder(lorem(30))
== Test Methodology
The aim of the test was to uncover vulnerabilities and weaknesses of all kinds. These were carried out in accordance with the OWASP Web Security Testing Guide, version 4#footnote("https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing"), and, where applicable, the MITRE ATT&CK Framework#footnote("https://attack.mitre.org"). Recommendations for system hardening were made based on the current version of the CIS Benchmarks#footnote("https://www.cisecurity.org/") and the appropriate variant in each case.
The penetration test was performed as a #helper.placeholder("black box test, without any access to source code or other information other than the scope").
== Findings
The penetration test revealed #context(helper.riskCategoryStats.values().map(v => v.final()).sum()) findings, which can be divided into the following risk categories:
#table(
columns: (16.66%, 16.66%, 16.66%, 16.66%, 16.66%, 16.66%),
align: center,
[Critical], [High], [Medium], [Low], [None], [Other],
table.cell(context(helper.riskCategoryStats.Critical.final()), fill: red, align: center),
table.cell(context(helper.riskCategoryStats.High.final()), fill: orange, align: center),
table.cell(context(helper.riskCategoryStats.Medium.final()), fill: yellow, align: center),
table.cell(context(helper.riskCategoryStats.Low.final()), fill: lime, align: center),
table.cell(context(helper.riskCategoryStats.None.final()), fill: white, align: center),
table.cell(context(helper.riskCategoryStats.Other.final()), fill: gray, align: center),
)
== Recommendations & Next Steps
Based on the results of this penetration test, #targetInSentence may be exposed to a production environment.
#pagebreak()
== Test Scope and Setup
The test was conducted from #helper.placeholder("01.01.1970") to #helper.placeholder("01.01.1970").
#helper.placeholder([
Connection to #targetHandy was made through a dedicated VPN connection via vpnhost.maride.inv. The inner IP address of the test device was 10.0.0.42.
])
The following scope was set for the penetration test:
#let inscope = table.cell("In scope", fill: lime, align: center)
#let outscope = table.cell("Out of scope", fill: gray, align: center)
#table(
columns: (25%, 50%, 25%,),
align: center,
[*Type*], [*Value*], [*State*],
[Address], [#helper.placeholder("10.23.42.1")], inscope,
[Address], [#helper.placeholder("2001:db8::2342")], inscope,
[Domain], [#helper.placeholder("*.maride.inv")], inscope,
[URL], [#helper.placeholder("secret.maride.inv/flag.txt")], outscope,
[URL], [#helper.placeholder("important.maride.inv/rickroll")], outscope,
// ----- Management Summary -----
#pages.managementSummary(
target: targetFull,
targetInSentence: targetInSentence,
testFocus: helper.placeholder("external attackers in real-world scenarios"),
testObject: helper.placeholder(lorem(30)),
testScenario: helper.placeholder("black box test"),
recommendation: helper.placeholder([Based on the results of this penetration test, #targetInSentence may be exposed to a production environment.])
)
#pagebreak()
From the perspective of the machine used for the penetration test, the network layout was seen as shown in the graph below - simplified by leaving out hops that are not relevant for the penetration test, like third-party network operators and ISPs.
#figure(
render("
digraph G {
rankdir=LR;
node [shape=rectangle];
subgraph stage1 {
style=filled;
color=red;
label=\"Connection\";
User -> Firewall [label=\"OpenVPN\"];
}
subgraph targetnet1 {
style=filled;
color=red;
label=\"Target Network\";
Firewall -> Target1;
Firewall -> Target2;
Firewall -> Target3;
Firewall -> Target4;
}
subgraph targetnet2 {
style=filled;
color=red;
label=\"Target Network\";
Target2 -> Target5;
Target2 -> Target6;
Target2 -> Target7;
}
subgraph targetnet3 {
style=filled;
color=red;
label=\"Target Network\";
Target4 -> Target8;
}
// ----- Test Scope & Setup -----
#pages.scopeAndSetup(
target: targetFull,
start: helper.placeholder("01.01.1970"),
end: helper.placeholder("31.12.1970"),
setup: helper.placeholder([Connection to #targetFull was made through a dedicated VPN connection. The inner IP address of the test device was 10.0.0.42.]),
nodes: "
subgraph stage1 {
label=\"Connection\";
User -> Firewall [label=\"OpenVPN\"];
}
"),
caption: [
Schematic graph showing the test objective network
]
subgraph targetnet1 {
label=\"Target Network\";
Firewall -> Target1;
Firewall -> Target2;
Firewall -> Target3;
Firewall -> Target4;
}
subgraph targetnet2 {
label=\"Target Network\";
Target2 -> Target5;
Target2 -> Target6;
Target2 -> Target7;
}
subgraph targetnet3 {
label=\"Target Network\";
Target4 -> Target8;
}
",
scope: (
( type: "Address", content: helper.placeholder("10.23.42.1"), inScope: true ),
( type: "Address", content: helper.placeholder("10.23.42.1"), inScope: true ),
( type: "Address", content: helper.placeholder("2001:db8::2342"), inScope: true ),
( type: "Domain", content: helper.placeholder("*.maride.inv"), inScope: true ),
( type: "URL", content: helper.placeholder("secret.maride.inv/flag.txt"), inScope: false),
( type: "URL", content: helper.placeholder("important.maride.inv/rickroll"), inScope: false)
)
)
#pagebreak()
// ----- Findings -----
#include "findings.typ"
#pagebreak()
// ----- Appendix -----
= Appendix
#context(
[
#if helper.hasCVSSTable.get() {
pages.cvssAppendix()
pagebreak()
pages.ciaAppendix()
}
#((
pages.boxAppendix(),
pages.ciaAppendix(),
if helper.hasCVSSTable.get() { pages.cvssAppendix() }
).join(pagebreak()))
]
)

152
pages.typ
View File

@ -1,6 +1,8 @@
#import "@preview/diagraph:0.3.6": render
#import "helper.typ"
#let cover(title, author) = {
#let cover(title, place, author) = {
// Define page
set page(
paper: "a4",
@ -22,20 +24,10 @@
v(0pt)
text(size: 16pt, [
Düsseldorf, #datetime.today().display("[day].[month].[year]") • #author
#place, #datetime.today().display("[day].[month].[year]") • #author
])
}
#let toc() = {
outline(
title: "Table of contents",
indent: 10pt,
depth: 2
)
pagebreak()
}
#let legal(author) = {
// Define page
set page(
@ -72,6 +64,114 @@
])
}
#let toc() = {
outline(
title: "Table of contents",
indent: 10pt,
depth: 2
)
}
#let managementSummary(target: str, targetInSentence: str, testFocus: str, testObject: str, testScenario: str, recommendation: str) = {
[
= Management Summary
== Motivation
This penetration test was conducted to proactively identify, assess, and validate the severity of security vulnerabilities within the defined scope of #targetInSentence, specifically those exploitable by #testFocus. Adversarial techniques to bypass controls, gain unauthorized access, and compromise critical assets were performed for this test scenario to determine the actual impact on confidentiality, integrity, and availability.
== Test Object
#testObject
== Test Methodology
The aim of the test was to uncover vulnerabilities and weaknesses of all kinds. These were carried out in accordance with the OWASP Web Security Testing Guide, version 4#footnote("https://owasp.org/www-project-web-security-testing-guide/stable/4-Web_Application_Security_Testing"), and, where applicable, the MITRE ATT&CK Framework#footnote("https://attack.mitre.org"). Recommendations for system hardening were made based on the current version of the CIS Benchmarks#footnote("https://www.cisecurity.org/") and the appropriate variant in each case.
The penetration test was performed as a #testScenario.
== Findings
The penetration test revealed #context([
#let num = helper.riskCategoryStats.values().map(v => v.final()).sum()
#if num == 1 {
[ #num finding ]
} else {
[ #num findings ]
}
]) which can be categorized by risk:
#table(
columns: (16.66%, 16.66%, 16.66%, 16.66%, 16.66%, 16.66%),
align: center,
[Critical], [High], [Medium], [Low], [None], [Other],
table.cell(context(helper.riskCategoryStats.Critical.final()), fill: red, align: center),
table.cell(context(helper.riskCategoryStats.High.final()), fill: orange, align: center),
table.cell(context(helper.riskCategoryStats.Medium.final()), fill: yellow, align: center),
table.cell(context(helper.riskCategoryStats.Low.final()), fill: lime, align: center),
table.cell(context(helper.riskCategoryStats.None.final()), fill: white, align: center),
table.cell(context(helper.riskCategoryStats.Other.final()), fill: gray, align: center),
)
== Recommendations & Next Steps
#recommendation
]
}
#let scopeAndSetup(target: str, start: str, end: str, setup: str, nodes: str, scope: array) = {
[
== Test Scope and Setup
#if start != "" {
if end != "" {
[ The test was conducted from #start to #end. ]
} else {
[ The test was conducted on #start. ]
}
}
#setup
The following scope was set for the penetration test:
#table(
columns: (25%, 50%, 25%),
align: center,
[*Type*], [*Value*], [*State*],
..for (i, value) in scope.enumerate() {
(
table.cell(value.type),
table.cell(value.content),
if value.inScope {
table.cell("In scope", fill: lime, align: center)
} else {
table.cell("Out of scope", fill: gray, align: center)
}
)
}
)
#if nodes != "" {
[ From the perspective of the machine used for the penetration test, the network layout was seen as shown in the graph below - simplified by leaving out hops that are not relevant for the penetration test, like third-party network operators and ISPs. ]
figure(
render("
digraph G {
rankdir=LR;
node [shape=rectangle];
" + nodes + "
}
"),
caption: [
Schematic graph showing the test objective network
]
)
}
]
}
#let ciaAppendix() = {
[
== CIA Triad
@ -141,4 +241,30 @@
- *Unchanged (U)*: Lowest severity. Vulnerability only affects resources within the same security authority (e.g., a web app affecting its own files).
- *Changed (C)*: Highest severity. Vulnerability crosses security boundaries, impacting components under different authorities (e.g., a compromised web server accessing a database).
]
}
}
#let boxAppendix() = {
[
== Appendix: Penetration Testing Box Scenarios
Penetration testing engagements are classified by the level of information provided to the testing team. This classification directly impacts the methodology, scope, and findings. The three standard scenarios are *Black Box*, *Grey Box*, and *White Box*. While Black Box and White Box refer to quite clear and precise situations, Grey box is a bit vague, in-between of both. Due to this, these terms should always be interpreted in the current situation and not be seen as precise and clear terminology. Nonetheless, the selection of the box scenario directly determines the scope of findings and realism of threat simulation. Black box tests external risks, grey box evaluates insider-adjacent threats, and white box provides the deepest technical analysis.
=== Black Box Testing
The testing team has no prior knowledge of the target system (e.g., internal architecture, source code, credentials, or network topology). Testing simulates an external attacker with only publicly available information. The purpose is to evaluate realistic attack surfaces, unpatched vulnerabilities exposed to the internet, and the effectiveness of perimeter defenses.
For example: a penetration test against a companys public-facing e-commerce website (`www.maride.inv`). Testers are provided only the domain name and must identify vulnerabilities using only publicly available and gathered information. No access to internal systems or credentials is granted.
=== Grey Box Testing
The testing team is provided limited, realistic information (e.g., user credentials, network diagrams, or documentation). This simulates a threat actor with compromised credentials or insider access. The purpose is to bridge the gap between external and internal testing; uncover vulnerabilities exploitable by authenticated users or partial insider knowledge.
For example: testing a corporate web application where testers are given a low-privileged user account (e.g., "standard employee" credentials). Testers identify issues like privilege escalation, insecure data handling, or business logic flaws that an internal user could exploit.
=== White Box Testing
The testing team has complete, detailed access to the target system (e.g., source code, infrastructure diagrams, credentials, and system configurations). This simulates a highly motivated insider threat with deep system knowledge. The purpose is to perform exhaustive code-level analysis, identify root causes of vulnerabilities, and validate secure development practices.
For example: reviewing the source code of a custom mobile banking application. Testers are provided full access to the code repository, database schemas, and API documentation to identify flaws like hardcoded secrets, cryptographic misconfigurations, or insecure API endpoints.
]
}