-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
573 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
digraph all { | ||
color=blue fontname=Arial rankdir=LR | ||
node [fontname=Arial fontsize=11 shape=box style=rounded] | ||
edge [fontname=Arial fontsize=11] | ||
subgraph cluster_Internet { | ||
graph [color=red fontname=Arial fontsize=11 label=Internet style=dashed] | ||
Researcher | ||
} | ||
subgraph "cluster_ACI Control Plane" { | ||
graph [color=red fontname=Arial fontsize=11 label="ACI Control Plane" style=dashed] | ||
"ACI API" | ||
} | ||
subgraph cluster_Azure { | ||
graph [color=red fontname=Arial fontsize=11 label=Azure style=dashed] | ||
"Kube-API" | ||
} | ||
Researcher -> "ACI API" [dir=forward] | ||
"ACI API" -> "Kube-API" [dir=forward] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions
19
examples/aciExploit/Attacker looks for runtime information-dfd
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
digraph "Attacker looks for runtime information" { | ||
color=blue fontname=Arial rankdir=LR | ||
node [fontname=Arial fontsize=11 shape=box style=rounded] | ||
edge [fontname=Arial fontsize=11] | ||
subgraph cluster_Internet { | ||
graph [color=red fontname=Arial fontsize=11 label=Internet style=dashed] | ||
Researcher | ||
} | ||
subgraph "cluster_ACI Control Plane" { | ||
graph [color=red fontname=Arial fontsize=11 label="ACI Control Plane" style=dashed] | ||
"ACI API" | ||
} | ||
subgraph cluster_Azure { | ||
graph [color=red fontname=Arial fontsize=11 label=Azure style=dashed] | ||
"Kube-API" | ||
} | ||
Researcher -> "ACI API" [label="(1) Deploy WhoC container"] | ||
"ACI API" -> "Kube-API" [label="(2) Deploy WhoC container"] | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions
5
examples/aciExploit/flow-Attacker looks for runtime information-1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
digraph { | ||
graph [bgcolor=transparent fontsize=11 fontstyle=Arial] | ||
node [fontsize=11 fontstyle=Arial shape=plaintext] | ||
struct [label="TLS|HTTP|{Deploy WhoC container}" shape=record] | ||
} |
Binary file added
BIN
+2.48 KB
examples/aciExploit/flow-Attacker looks for runtime information-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions
5
examples/aciExploit/flow-Attacker looks for runtime information-2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
digraph { | ||
graph [bgcolor=transparent fontsize=11 fontstyle=Arial] | ||
node [fontsize=11 fontstyle=Arial shape=plaintext] | ||
struct [label="Unknown|{Deploy WhoC container}" shape=record] | ||
} |
Binary file added
BIN
+2.31 KB
examples/aciExploit/flow-Attacker looks for runtime information-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
#!/bin/sh | ||
for f in example_*.py; do python3 $f; done |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from fluentm.entities import Actor, Process, DataFlow, HTTP, MTLS, TLS, DHCP, Unknown | ||
|
||
import fluentm.renderer as renderer | ||
|
||
# An example using scenes to describe how the Azure ACI exploit took place | ||
|
||
scenes = { | ||
# User starts from terminal, with Azure credentials | ||
"Attacker looks for runtime information": [ | ||
DataFlow( | ||
Actor("Researcher").inBoundary("Internet"), | ||
Process("ACI API").inBoundary("Azure").inBoundary("ACI Control Plane"), | ||
TLS(HTTP("Deploy WhoC container")), | ||
), | ||
DataFlow( | ||
Process("ACI API"), | ||
Process("Kube-API").inBoundary("k8s control plane").inBoundary("Azure"), | ||
Unknown("Deploy WhoC container"), | ||
), | ||
] | ||
} | ||
|
||
if __name__ == "__main__": | ||
renderer.report(scenes, outputDir="aciExploit", dfdLabels=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from fluentm.entities import Actor, Boundary, Process, DataFlow, TLS, HTTP, Internal, GIT, SSH | ||
from fluentm.renderer import report | ||
|
||
# Example of a more code-oriented approach, using variables which will play | ||
# nicely with IDEs. It can be a faster way to write these. | ||
|
||
# Setup scenes here: | ||
scenes = {} | ||
|
||
newK8sClusterBoundary = Boundary("New Kubernetes Cluster").inBoundary("New AWS Account") | ||
|
||
## Developer requests a new cluster | ||
# Participants | ||
developer = Actor("Developer") | ||
clusterOrchestrator = Process("Cluster Orchestrator").inBoundary( | ||
Boundary("Control Cluster") | ||
) | ||
iam = Process("IAM").inBoundary("AWS") | ||
eks = Process("EKS").inBoundary("AWS") | ||
k8sApi = Process("k8s API").inBoundary(Boundary("New Kubernetes Cluster")) | ||
# Flows | ||
scenes["Developer requests a new cluster"] = [ | ||
DataFlow(developer, clusterOrchestrator, TLS(HTTP("Create cluster request"))), | ||
DataFlow(clusterOrchestrator, clusterOrchestrator, Internal("Validates user")), | ||
DataFlow( | ||
clusterOrchestrator, | ||
iam, | ||
TLS(HTTP("Create new account")), | ||
response=TLS(HTTP("Account Details")), | ||
), | ||
DataFlow( | ||
clusterOrchestrator, | ||
eks, | ||
TLS(HTTP("Create new cluster")), | ||
response=TLS(HTTP("Cluster Details")), | ||
), | ||
DataFlow( | ||
clusterOrchestrator, k8sApi, TLS(HTTP("Add default admission controller")) | ||
), | ||
] | ||
|
||
## Developer creates a pod | ||
# New participants (not seen above) | ||
developer = Actor("Developer") | ||
admissionController = Process("Admission Controller").inBoundary("Cluster Orchestrator") | ||
policyRepo = Process("Policy Repo").inBoundary(Boundary("Version Control")) | ||
opa = Process("OPA") | ||
# DataFlows | ||
scenes["Developer creates a pod"] = [ | ||
DataFlow(developer, k8sApi, TLS(HTTP("Create POD"))), | ||
DataFlow(k8sApi, admissionController, TLS(HTTP("Validate pod creation"))), | ||
DataFlow(admissionController, opa, TLS(HTTP("Validate pod creation"))), | ||
DataFlow( | ||
opa, | ||
policyRepo, | ||
SSH(GIT("Get latest policy")), | ||
response=SSH(GIT("Latest policy REGO")), | ||
), | ||
DataFlow(opa, k8sApi, TLS(HTTP("Validation Decision"))), | ||
DataFlow(k8sApi, developer, TLS(HTTP("Approve/Denied"))), | ||
] | ||
|
||
if __name__ == "__main__": | ||
r = report(scenes, outputDir="OPA_orchestration", dfdLabels=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
from fluentm.entities import Actor, Boundary, Process, DataFlow, TLS, SIGV4, Data | ||
|
||
import fluentm.renderer as renderer | ||
|
||
# 1. Create an IAM OIDC provider for your cluster | ||
# 2. Create an IAM role and attach an IAM policy to it with the permissions that your service accounts need | ||
# 2.a. recommend creating separate roles for each unique collection of permissions | ||
# 3. Associate an IAM role with a service account | ||
|
||
scenes = { | ||
"Create an IAM OIDC provider for cluster": [ | ||
DataFlow( | ||
Actor("User"), | ||
Process("EKS").inBoundary("AWS SVCs"), | ||
TLS(SIGV4("Create OIDC endpoint")) | ||
.addProtocolData(Data("Server x509")) | ||
.addProtocolData(Data("Client x509")), | ||
response="OIDC provider URL", | ||
), | ||
DataFlow( | ||
Actor("User"), | ||
Process("IAM").inBoundary("AWS SVCs"), | ||
TLS(SIGV4("Add OIDC provider,\n OIDC provider URL")), | ||
), | ||
], | ||
"Create an IAM policy & role to allow CPI addon to manage VPC": [ | ||
DataFlow( | ||
Actor("User"), | ||
Process("IAM"), | ||
TLS(SIGV4("Create Policy")), | ||
response=TLS("Policy ARN"), | ||
), | ||
DataFlow( | ||
Actor("User"), | ||
Process("IAM"), | ||
TLS( | ||
SIGV4( | ||
"Create Role,\nTrusted Entity: Web Identity,\nIdentity Provider: OIDC URL,\nAttach Policy: Policy ARN" | ||
) | ||
), | ||
response=TLS("Role ARN"), | ||
), | ||
], | ||
"Associate IAM role to a cluster service account": [ | ||
DataFlow( | ||
Actor("User"), | ||
Process("Kube API").inBoundary( | ||
Boundary("Kubernetes Control Plane").inBoundary( | ||
Boundary("Single Tenant VPC") | ||
) | ||
), | ||
TLS(SIGV4("Annotate service account $acct with Role ARN")), | ||
) | ||
], | ||
"Deploy Addon": [ | ||
DataFlow( | ||
Actor("User"), | ||
Process("EKS"), | ||
TLS(SIGV4("Create add-on CNI,\nCluster: $clusterID")), | ||
), | ||
DataFlow( | ||
Process("EKS"), | ||
Process("Kube API"), | ||
TLS("Deployment Spec: CNI addon\nRole: Role ARN"), | ||
), | ||
DataFlow( | ||
Process("Kube API"), | ||
Process("eks-pod-identity-webhook").inBoundary( | ||
Boundary("Kubernetes Control Plane") | ||
), | ||
TLS("Pod Spec"), | ||
response=TLS("Mutated Pod Spec,\nAdd projected token to spec"), | ||
), | ||
DataFlow( | ||
Process("Kube API"), | ||
Process("Kubelet").inBoundary( | ||
Boundary("Kubernetes Data Plane").inBoundary( | ||
Boundary("Customer Account") | ||
) | ||
), | ||
TLS("Launch Pod,\nPod Spec"), | ||
), | ||
DataFlow( | ||
Process("Kubelet"), | ||
Process("CNI Pod").inBoundary(Boundary("Kubernetes Data Plane")), | ||
TLS("Launch Pod,\nsvcacct $acct,\nRole ARN,\nJWT STS Token"), | ||
), | ||
], | ||
"CNI configures VPC": [ | ||
DataFlow( | ||
Process("CNI Pod"), | ||
Process("VPC").inBoundary(Boundary("AWS SVCs")), | ||
TLS("Update VPC configuration,\nSTS token,\nOperates as Role ARN"), | ||
), | ||
], | ||
} | ||
|
||
if __name__ == "__main__": | ||
renderer.report(scenes, outputDir="aws-eks-add-on-permissions", dfdLabels=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
from fluentm.entities import ( | ||
Boundary, | ||
Process, | ||
DataFlow, | ||
Exec, | ||
HTTP, | ||
SIGV4, | ||
TLS, | ||
SIGV4, | ||
Stdout, | ||
Internal, | ||
) | ||
from fluentm.renderer import report | ||
|
||
scenes = { | ||
# Example using variables, which is fine for small things but gets hard with longer flows | ||
"kubectl gets pre-signed URL": [ | ||
DataFlow( | ||
Process("kubectl").inBoundary("User Machine"), | ||
Process("aws-cli").inBoundary("User Machine"), | ||
Exec("Exec aws-cli get-token"), | ||
), | ||
DataFlow( | ||
Process("aws-cli"), | ||
Process("aws-cli"), | ||
Internal("Sign URL using AWS IAM credentials"), | ||
), | ||
DataFlow(Process("aws-cli"), Process("kubectl"), Stdout("STS pre-signed URL")), | ||
], | ||
"API traffic": [ | ||
DataFlow( | ||
Process("kubectl"), | ||
Process("Kubernetes API").inBoundary( | ||
Boundary("EKS Cluster").inBoundary("AWS Cloud") | ||
), | ||
TLS(HTTP("pre-signed URL as Bearer Token HTTP Header")), | ||
), | ||
DataFlow( | ||
Process("Kubernetes API"), | ||
Process("aws-iam-authenticator").inBoundary("EKS Cluster"), | ||
TLS(HTTP("TokenReview request with pre-signed URL")), | ||
), | ||
DataFlow( | ||
Process("aws-iam-authenticator"), | ||
Process("AWS STS").inBoundary("AWS Cloud"), | ||
TLS(HTTP(SIGV4("sts:GetCallerIdentity request"))), | ||
response=TLS(HTTP("sts:GetCallerIdentity response")), | ||
), | ||
DataFlow( | ||
Process("aws-iam-authenticator"), | ||
Process("Kubernetes API").inBoundary("EKS Cluster"), | ||
TLS(HTTP("TokenReview response with username")), | ||
), | ||
DataFlow( | ||
Process("aws-iam-authenticator"), | ||
Process("Kubernetes API").inBoundary("EKS Cluster"), | ||
TLS(HTTP(("Async Watch mapped aws-auth ConfigMap "))), | ||
# response=TLS(HTTP("Config Map username mappings")), | ||
), | ||
], | ||
} | ||
|
||
if __name__ == "__main__": | ||
report(scenes, outputDir="aws-iam-authenticator", dfdLabels=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from fluentm.entities import Actor, Boundary, Process, DataFlow, TLS, HTTP, SQL | ||
from fluentm.renderer import report | ||
|
||
scenes = { | ||
"Customer Login": [ | ||
DataFlow( | ||
Actor("Customer"), | ||
Process("Nginx").inBoundary(Boundary("Front End")), | ||
TLS(HTTP("GET /Login credentials")), | ||
), | ||
DataFlow( | ||
Process("Nginx"), | ||
Process("User Database").inBoundary(Boundary("Back End")), | ||
SQL("SELECT user password"), | ||
), | ||
DataFlow(Process("User Database"), Process("Nginx"), SQL("password")), | ||
DataFlow(Process("Nginx"), Actor("Customer"), TLS(HTTP("Login Cookie"))), | ||
], | ||
"Customer Lists Books": [ | ||
DataFlow( | ||
Actor("Customer"), Process("Nginx"), TLS(HTTP("GET /list, Login Cookie")) | ||
), | ||
DataFlow( | ||
Process("Nginx"), | ||
Process("Stock Database").inBoundary(Boundary("Back End")), | ||
SQL("SELECT stock"), | ||
), | ||
DataFlow( | ||
Process("Stock Database"), | ||
Process("Nginx"), | ||
SQL("Stock Items, Pagination token"), | ||
), | ||
DataFlow(Process("Nginx"), Actor("Customer"), TLS(HTTP("Page listings"))), | ||
], | ||
"Customer Views Details": [ | ||
DataFlow( | ||
Actor("Customer"), Process("Nginx"), TLS(HTTP("GET /item, Login Cookie")) | ||
), | ||
DataFlow(Process("Nginx"), Process("User Database"), HTTP("Log viewed ID")), | ||
DataFlow(Process("Nginx"), Process("Stock Database"), SQL("SELECT ID")), | ||
DataFlow( | ||
Process("Stock Database"), | ||
Process("Nginx"), | ||
SQL("Stock details, CDN image links"), | ||
), | ||
DataFlow(Process("Nginx"), Actor("Customer"), HTTP("Page html")), | ||
DataFlow( | ||
Actor("Customer"), | ||
Process("CDN").inBoundary(Boundary("External CDN")), | ||
HTTP("GET images"), | ||
), | ||
], | ||
} | ||
|
||
if __name__ == "__main__": | ||
r = report(scenes, outputDir="bookstore", dfdLabels=True) |
Oops, something went wrong.