Skip to content

Commit c1104b7

Browse files
Feature/autogenerate attack tactics visualization 95 (#613)
* Integrate GenerateCoverageMatrices function into generate-docs workflow - Added a call to the GenerateCoverageMatrices function within generate-docs.go. Signed-off-by: Anthony Mendonca <[email protected]> * Add GenerateCoverageMatrices function to produce HTML coverage matrices -Created generate-coverage-matrices.go in tools directory -Added logic to dynamically generate stylized HTML tables for each platform -Included in-line CSS for table styling and better readability Signed-off-by: Anthony Mendonca <[email protected]> * Output MITRE ATT&CK coverage as single Markdown file -Changed output from single HTML files per platform to single Markdown file. - Embedded raw HTML tables inside the markdown file to be rebuilt each time make docs is ran. Signed-off-by: Anthony Mendonca <[email protected]> * Autogenerate docs * Fixes font family issue Signed-off-by: Anthony Mendonca <[email protected]> * Adds updated mitre-attack-coverage-matrices.md file Signed-off-by: Anthony Mendonca <[email protected]> * Adjust styling and add links * Adds capitalization to platform name to UI Signed-off-by: Anthony Mendonca <[email protected]> * Adds scrollable div to aid with UX of Platform tables Signed-off-by: Anthony Mendonca <[email protected]> * Adds updated mitre-attack-coverage-matrices.md file Signed-off-by: Anthony Mendonca <[email protected]> --------- Signed-off-by: Anthony Mendonca <[email protected]> Co-authored-by: Christophe Tafani-Dereeper <[email protected]>
1 parent cc6aaad commit c1104b7

File tree

4 files changed

+268
-0
lines changed

4 files changed

+268
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
2+
<style>
3+
.table-container {
4+
overflow-x: auto; /* Enables horizontal scrolling */
5+
max-width: 80%; /* Ensures it doesn't go beyond the page */
6+
border: 1px solid #ddd;
7+
padding: 10px;
8+
margin-bottom: 20px;
9+
}
10+
table {
11+
width: 100%;
12+
border-collapse: collapse;
13+
margin: 20px 0;
14+
font-size: 16px;
15+
white-space: nowrap; /* Prevents text wrapping in cells */
16+
}
17+
th, td {
18+
border: 1px solid #ddd;
19+
padding: 8px;
20+
text-align: center;
21+
}
22+
.md-sidebar.md-sidebar--secondary { display: none; }
23+
.md-content { min-width: 100%; }
24+
</style>
25+
26+
# MITRE ATT&CK Coverage by Platform
27+
28+
This provides coverage matrices of MITRE ATT&CK tactics and techniques currently covered by Stratus Red Team for different cloud platforms.
29+
<h2 style="text-transform: uppercase;">azure</h2>
30+
<div class="table-container"><table>
31+
<thead><tr><th>Execution</th><th>Persistence</th><th>Exfiltration</th></tr></thead>
32+
<tbody>
33+
<tr><td><a href="../Azure/azure.execution.vm-custom-script-extension">Execute Command on Virtual Machine using Custom Script Extension</a></td><td><a href="../Azure/azure.persistence.create-bastion-shareable-link">Create Azure VM Bastion shareable link</a></td><td><a href="../Azure/azure.exfiltration.disk-export">Export Disk Through SAS URL</a></td></tr>
34+
<tr><td><a href="../Azure/azure.execution.vm-run-command">Execute Commands on Virtual Machine using Run Command</a></td><td></td><td></td></tr>
35+
</tbody>
36+
</table>
37+
</div>
38+
<h2 style="text-transform: uppercase;">EKS</h2>
39+
<div class="table-container"><table>
40+
<thead><tr><th>Persistence</th><th>Privilege Escalation</th><th>Lateral Movement</th></tr></thead>
41+
<tbody>
42+
<tr><td><a href="../EKS/eks.persistence.backdoor-aws-auth-configmap">Backdoor aws-auth EKS ConfigMap</a></td><td><a href="../EKS/eks.persistence.backdoor-aws-auth-configmap">Backdoor aws-auth EKS ConfigMap</a></td><td><a href="../EKS/eks.lateral-movement.create-access-entry">Create Admin EKS Access Entry</a></td></tr>
43+
</tbody>
44+
</table>
45+
</div>
46+
<h2 style="text-transform: uppercase;">entra-id</h2>
47+
<div class="table-container"><table>
48+
<thead><tr><th>Persistence</th><th>Privilege Escalation</th></tr></thead>
49+
<tbody>
50+
<tr><td><a href="../Entra ID/entra-id.persistence.backdoor-application-sp">Backdoor Entra ID application through service principal</a></td><td><a href="../Entra ID/entra-id.persistence.backdoor-application-sp">Backdoor Entra ID application through service principal</a></td></tr>
51+
<tr><td><a href="../Entra ID/entra-id.persistence.backdoor-application">Backdoor Entra ID application</a></td><td><a href="../Entra ID/entra-id.persistence.backdoor-application">Backdoor Entra ID application</a></td></tr>
52+
<tr><td><a href="../Entra ID/entra-id.persistence.guest-user">Create Guest User</a></td><td><a href="../Entra ID/entra-id.persistence.new-application">Create Application</a></td></tr>
53+
<tr><td><a href="../Entra ID/entra-id.persistence.hidden-au">Create Hidden Scoped Role Assignment Through HiddenMembership AU</a></td><td></td></tr>
54+
<tr><td><a href="../Entra ID/entra-id.persistence.new-application">Create Application</a></td><td></td></tr>
55+
<tr><td><a href="../Entra ID/entra-id.persistence.restricted-au">Create Sticky Backdoor User Through Restricted Management AU</a></td><td></td></tr>
56+
</tbody>
57+
</table>
58+
</div>
59+
<h2 style="text-transform: uppercase;">GCP</h2>
60+
<div class="table-container"><table>
61+
<thead><tr><th>Persistence</th><th>Privilege Escalation</th><th>Credential Access</th><th>Exfiltration</th></tr></thead>
62+
<tbody>
63+
<tr><td><a href="../GCP/gcp.persistence.backdoor-service-account-policy">Backdoor a GCP Service Account through its IAM Policy</a></td><td><a href="../GCP/gcp.persistence.create-admin-service-account">Create an Admin GCP Service Account</a></td><td><a href="../GCP/gcp.credential-access.secretmanager-retrieve-secrets">Retrieve a High Number of Secret Manager secrets</a></td><td><a href="../GCP/gcp.exfiltration.share-compute-disk">Exfiltrate Compute Disk by sharing it</a></td></tr>
64+
<tr><td><a href="../GCP/gcp.persistence.create-admin-service-account">Create an Admin GCP Service Account</a></td><td><a href="../GCP/gcp.persistence.create-service-account-key">Create a GCP Service Account Key</a></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-image">Exfiltrate Compute Image by sharing it</a></td></tr>
65+
<tr><td><a href="../GCP/gcp.persistence.create-service-account-key">Create a GCP Service Account Key</a></td><td><a href="../GCP/gcp.privilege-escalation.impersonate-service-accounts">Impersonate GCP Service Accounts</a></td><td></td><td><a href="../GCP/gcp.exfiltration.share-compute-snapshot">Exfiltrate Compute Disk by sharing a snapshot</a></td></tr>
66+
<tr><td><a href="../GCP/gcp.persistence.invite-external-user">Invite an External User to a GCP Project</a></td><td></td><td></td><td></td></tr>
67+
</tbody>
68+
</table>
69+
</div>
70+
<h2 style="text-transform: uppercase;">kubernetes</h2>
71+
<div class="table-container"><table>
72+
<thead><tr><th>Persistence</th><th>Privilege Escalation</th><th>Credential Access</th></tr></thead>
73+
<tbody>
74+
<tr><td><a href="../Kubernetes/k8s.persistence.create-admin-clusterrole">Create Admin ClusterRole</a></td><td><a href="../Kubernetes/k8s.persistence.create-admin-clusterrole">Create Admin ClusterRole</a></td><td><a href="../Kubernetes/k8s.credential-access.dump-secrets">Dump All Secrets</a></td></tr>
75+
<tr><td><a href="../Kubernetes/k8s.persistence.create-client-certificate">Create Client Certificate Credential</a></td><td><a href="../Kubernetes/k8s.privilege-escalation.hostpath-volume">Container breakout via hostPath volume mount</a></td><td><a href="../Kubernetes/k8s.credential-access.steal-serviceaccount-token">Steal Pod Service Account Token</a></td></tr>
76+
<tr><td><a href="../Kubernetes/k8s.persistence.create-token">Create Long-Lived Token</a></td><td><a href="../Kubernetes/k8s.privilege-escalation.nodes-proxy">Privilege escalation through node/proxy permissions</a></td><td></td></tr>
77+
<tr><td></td><td><a href="../Kubernetes/k8s.privilege-escalation.privileged-pod">Run a Privileged Pod</a></td><td></td></tr>
78+
</tbody>
79+
</table>
80+
</div>
81+
<h2 style="text-transform: uppercase;">AWS</h2>
82+
<div class="table-container"><table>
83+
<thead><tr><th>Initial Access</th><th>Execution</th><th>Persistence</th><th>Privilege Escalation</th><th>Defense Evasion</th><th>Credential Access</th><th>Discovery</th><th>Lateral Movement</th><th>Exfiltration</th><th>Impact</th></tr></thead>
84+
<tbody>
85+
<tr><td><a href="../AWS/aws.initial-access.console-login-without-mfa">Console Login without MFA</a></td><td><a href="../AWS/aws.execution.ec2-launch-unusual-instances">Launch Unusual EC2 instances</a></td><td><a href="../AWS/aws.persistence.iam-backdoor-role">Backdoor an IAM Role</a></td><td><a href="../AWS/aws.execution.ec2-user-data">Execute Commands on EC2 Instance via User Data</a></td><td><a href="../AWS/aws.defense-evasion.cloudtrail-delete">Delete CloudTrail Trail</a></td><td><a href="../AWS/aws.credential-access.ec2-get-password-data">Retrieve EC2 Password Data</a></td><td><a href="../AWS/aws.discovery.ec2-enumerate-from-instance">Execute Discovery Commands on an EC2 Instance</a></td><td><a href="../AWS/aws.lateral-movement.ec2-serial-console-send-ssh-public-key">Usage of EC2 Serial Console to push SSH public key</a></td><td><a href="../AWS/aws.exfiltration.ec2-security-group-open-port-22-ingress">Open Ingress Port 22 on a Security Group</a></td><td><a href="../AWS/aws.impact.bedrock-invoke-model">Invoke Bedrock Model</a></td></tr>
86+
<tr><td></td><td><a href="../AWS/aws.execution.ec2-user-data">Execute Commands on EC2 Instance via User Data</a></td><td><a href="../AWS/aws.persistence.iam-backdoor-user">Create an Access Key on an IAM User</a></td><td><a href="../AWS/aws.persistence.iam-backdoor-user">Create an Access Key on an IAM User</a></td><td><a href="../AWS/aws.defense-evasion.cloudtrail-event-selectors">Disable CloudTrail Logging Through Event Selectors</a></td><td><a href="../AWS/aws.credential-access.ec2-steal-instance-credentials">Steal EC2 Instance Credentials</a></td><td><a href="../AWS/aws.discovery.ec2-download-user-data">Download EC2 Instance User Data</a></td><td><a href="../AWS/aws.lateral-movement.ec2-instance-connect">Usage of EC2 Instance Connect on multiple instances</a></td><td><a href="../AWS/aws.exfiltration.ec2-share-ami">Exfiltrate an AMI by Sharing It</a></td><td><a href="../AWS/aws.impact.s3-ransomware-batch-deletion">S3 Ransomware through batch file deletion</a></td></tr>
87+
<tr><td></td><td><a href="../AWS/aws.execution.ssm-send-command">Usage of ssm:SendCommand on multiple instances</a></td><td><a href="../AWS/aws.persistence.iam-create-admin-user">Create an administrative IAM User</a></td><td><a href="../AWS/aws.persistence.iam-create-admin-user">Create an administrative IAM User</a></td><td><a href="../AWS/aws.defense-evasion.cloudtrail-lifecycle-rule">CloudTrail Logs Impairment Through S3 Lifecycle Rule</a></td><td><a href="../AWS/aws.credential-access.secretsmanager-batch-retrieve-secrets">Retrieve a High Number of Secrets Manager secrets (Batch)</a></td><td><a href="../AWS/aws.discovery.ses-enumerate">Enumerate SES</a></td><td></td><td><a href="../AWS/aws.exfiltration.ec2-share-ebs-snapshot">Exfiltrate EBS Snapshot by Sharing It</a></td><td><a href="../AWS/aws.impact.s3-ransomware-client-side-encryption">S3 Ransomware through client-side encryption</a></td></tr>
88+
<tr><td></td><td><a href="../AWS/aws.execution.ssm-start-session">Usage of ssm:StartSession on multiple instances</a></td><td><a href="../AWS/aws.persistence.iam-create-backdoor-role">Create a backdoored IAM Role</a></td><td><a href="../AWS/aws.persistence.iam-create-user-login-profile">Create a Login Profile on an IAM User</a></td><td><a href="../AWS/aws.defense-evasion.cloudtrail-stop">Stop CloudTrail Trail</a></td><td><a href="../AWS/aws.credential-access.secretsmanager-retrieve-secrets">Retrieve a High Number of Secrets Manager secrets</a></td><td></td><td></td><td><a href="../AWS/aws.exfiltration.rds-share-snapshot">Exfiltrate RDS Snapshot by Sharing</a></td><td><a href="../AWS/aws.impact.s3-ransomware-individual-deletion">S3 Ransomware through individual file deletion</a></td></tr>
89+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.iam-create-user-login-profile">Create a Login Profile on an IAM User</a></td><td><a href="../AWS/aws.persistence.lambda-layer-extension">Add a Malicious Lambda Extension</a></td><td><a href="../AWS/aws.defense-evasion.dns-delete-logs">Delete DNS query logs</a></td><td><a href="../AWS/aws.credential-access.ssm-retrieve-securestring-parameters">Retrieve And Decrypt SSM Parameters</a></td><td></td><td></td><td><a href="../AWS/aws.exfiltration.s3-backdoor-bucket-policy">Backdoor an S3 Bucket via its Bucket Policy</a></td><td></td></tr>
90+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.lambda-backdoor-function">Backdoor Lambda Function Through Resource-Based Policy</a></td><td><a href="../AWS/aws.persistence.rolesanywhere-create-trust-anchor">Create an IAM Roles Anywhere trust anchor</a></td><td><a href="../AWS/aws.defense-evasion.organizations-leave">Attempt to Leave the AWS Organization</a></td><td></td><td></td><td></td><td></td><td></td></tr>
91+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.lambda-layer-extension">Add a Malicious Lambda Extension</a></td><td><a href="../AWS/aws.privilege-escalation.iam-update-user-login-profile">Change IAM user password</a></td><td><a href="../AWS/aws.defense-evasion.vpc-remove-flow-logs">Remove VPC Flow Logs</a></td><td></td><td></td><td></td><td></td><td></td></tr>
92+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.lambda-overwrite-code">Overwrite Lambda Function Code</a></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
93+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.rolesanywhere-create-trust-anchor">Create an IAM Roles Anywhere trust anchor</a></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
94+
<tr><td></td><td></td><td><a href="../AWS/aws.persistence.sts-federation-token">Generate temporary AWS credentials using GetFederationToken</a></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
95+
</tbody>
96+
</table>
97+
</div>

mkdocs.yml

+1
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,5 @@ nav:
103103
- All Attack Techniques: attack-techniques/list.md
104104
- Philosophy: attack-techniques/philosophy.md
105105
- Supported Platforms: attack-techniques/supported-platforms.md
106+
- MITRE ATT&CK Coverage Matrices: attack-techniques/mitre-attack-coverage-matrices.md
106107
- ... | attack-techniques/*/*.md
+164
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/datadog/stratus-red-team/v2/pkg/stratus"
9+
)
10+
11+
// Define MITRE ATT&CK tactic order from MITRE website
12+
var mitreTacticOrder = []string{
13+
"Reconnaissance",
14+
"Resource Development",
15+
"Initial Access",
16+
"Execution",
17+
"Persistence",
18+
"Privilege Escalation",
19+
"Defense Evasion",
20+
"Credential Access",
21+
"Discovery",
22+
"Lateral Movement",
23+
"Collection",
24+
"Command and Control",
25+
"Exfiltration",
26+
"Impact",
27+
}
28+
29+
// GenerateCoverageMatrices generates a single static .md file containing MITRE ATT&CK coverage tables split by platform
30+
func GenerateCoverageMatrices(index map[stratus.Platform]map[string][]*stratus.AttackTechnique, docsDirectory string) error {
31+
outputFilePath := filepath.Join(docsDirectory, "attack-techniques", "mitre-attack-coverage-matrices.md")
32+
33+
if err := os.MkdirAll(filepath.Dir(outputFilePath), 0755); err != nil {
34+
return fmt.Errorf("failed to create docs directory: %w", err)
35+
}
36+
37+
if _, err := os.Stat(outputFilePath); err == nil {
38+
if err := os.Remove(outputFilePath); err != nil {
39+
return fmt.Errorf("failed to delete existing file: %w", err)
40+
}
41+
}
42+
43+
file, err := os.Create(outputFilePath)
44+
if err != nil {
45+
return fmt.Errorf("failed to create file: %w", err)
46+
}
47+
defer file.Close()
48+
49+
htmlContent := `
50+
<style>
51+
.table-container {
52+
overflow-x: auto; /* Enables horizontal scrolling */
53+
max-width: 80%; /* Ensures it doesn't go beyond the page */
54+
border: 1px solid #ddd;
55+
padding: 10px;
56+
margin-bottom: 20px;
57+
}
58+
table {
59+
width: 100%;
60+
border-collapse: collapse;
61+
margin: 20px 0;
62+
font-size: 16px;
63+
white-space: nowrap; /* Prevents text wrapping in cells */
64+
}
65+
th, td {
66+
border: 1px solid #ddd;
67+
padding: 8px;
68+
text-align: center;
69+
}
70+
.md-sidebar.md-sidebar--secondary { display: none; }
71+
.md-content { min-width: 100%; }
72+
</style>
73+
74+
# MITRE ATT&CK Coverage by Platform
75+
76+
This provides coverage matrices of MITRE ATT&CK tactics and techniques currently covered by Stratus Red Team for different cloud platforms.
77+
`
78+
79+
// Loop through each platform and generate tables
80+
for platform, tacticsMap := range index {
81+
htmlContent += fmt.Sprintf("<h2 style=\"text-transform: uppercase;\">%s</h2>\n", platform)
82+
htmlContent += `<div class="table-container">` // Add scrollable div
83+
84+
// Start the table
85+
htmlContent += "<table>\n"
86+
87+
// Sort tactics based on MITRE ATT&CK order
88+
sortedTactics := []string{}
89+
tacticSet := make(map[string]bool)
90+
91+
// Collect tactics present for specific platform
92+
for tactic := range tacticsMap {
93+
tacticSet[tactic] = true
94+
}
95+
96+
// Append tactics in the correct order
97+
for _, tactic := range mitreTacticOrder {
98+
if tacticSet[tactic] {
99+
sortedTactics = append(sortedTactics, tactic)
100+
}
101+
}
102+
103+
// Add table header with sorted tactics
104+
htmlContent += "<thead><tr>"
105+
for _, tactic := range sortedTactics {
106+
htmlContent += fmt.Sprintf("<th>%s</th>", tactic)
107+
}
108+
htmlContent += "</tr></thead>\n<tbody>\n"
109+
110+
// Create a list of rows
111+
rows := make([][]string, 0)
112+
maxRows := 0
113+
114+
// Map each tactic to its respective techniques (column by column)
115+
tacticToTechniques := make(map[string][]string)
116+
for _, tactic := range sortedTactics {
117+
techniques := tacticsMap[tactic]
118+
for _, technique := range techniques {
119+
platform, _ := technique.Platform.FormatName()
120+
cellText := fmt.Sprintf("<a href=\"%s\">%s</a>", fmt.Sprintf("../%s/%s", platform, technique.ID), technique.FriendlyName)
121+
tacticToTechniques[tactic] = append(tacticToTechniques[tactic], cellText)
122+
}
123+
if len(tacticToTechniques[tactic]) > maxRows {
124+
maxRows = len(tacticToTechniques[tactic])
125+
}
126+
}
127+
128+
// Fill rows with techniques for each tactic
129+
for i := 0; i < maxRows; i++ {
130+
row := make([]string, len(sortedTactics))
131+
for j, tactic := range sortedTactics {
132+
if i < len(tacticToTechniques[tactic]) {
133+
row[j] = tacticToTechniques[tactic][i]
134+
} else {
135+
row[j] = ""
136+
}
137+
}
138+
rows = append(rows, row)
139+
}
140+
141+
// Add rows to the HTML table
142+
for _, row := range rows {
143+
htmlContent += "<tr>"
144+
for _, cell := range row {
145+
if cell != "" {
146+
htmlContent += fmt.Sprintf("<td>%s</td>", cell)
147+
} else {
148+
htmlContent += "<td></td>"
149+
}
150+
}
151+
htmlContent += "</tr>\n"
152+
}
153+
154+
htmlContent += "</tbody>\n</table>\n</div>\n" // Close scrollable div
155+
}
156+
157+
// Write to Markdown file
158+
if _, err := file.WriteString(htmlContent); err != nil {
159+
return fmt.Errorf("failed to write to file: %w", err)
160+
}
161+
162+
fmt.Printf("Generated MITRE ATT&CK coverage markdown file: %s\n", outputFilePath)
163+
return nil
164+
}

v2/tools/generate-docs.go

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ func main() {
2828
os.Exit(1)
2929
}
3030

31+
if err := GenerateCoverageMatrices(index, docsDirectory); err != nil {
32+
fmt.Fprintln(os.Stderr, "Could not generate MITRE ATT&CK coverage file")
33+
fmt.Fprintf(os.Stderr, "%v\n", err)
34+
os.Exit(1)
35+
}
36+
3137
// Write a single index file with all techniques. File is enconded in YAML.
3238
yamlIndex := filepath.Join(docsDirectory, "index.yaml")
3339
if err := GenerateYAML(yamlIndex, index); err != nil {

0 commit comments

Comments
 (0)