KubeHound Cheat Sheet - Pen Testing & Red Teaming

Best Boutique Penetration Testing Companies - Top Rated Pen Test Companies

KubeHound Cheat Sheet for Azure Kubernetes Penetration Testing and Red Teaming

Scroll down to view example KubeHound queries created by Central InfoSec during Kubernetes penetration tests and queries collected from other sources.

Who knows, you may find a path to cluster-admin from an exposed endpoint...

KubeHound - Central InfoSec Penetration Testing Company

Example Graphs


Large Kubernetes Environment

KubeHound - Central InfoSec Penetration Testing Company

Exploiting an Endpoint Leads to Many Paths

KubeHound - Central InfoSec Penetration Testing Company

Selecting a Specific Pod

KubeHound - Central InfoSec Penetration Testing Company

Large Kubernetes Environment

KubeHound - Central InfoSec Penetration Testing Company

Hierarchical View

KubeHound - Central InfoSec Penetration Testing Company

Example Path 1

KubeHound - Central InfoSec Penetration Testing Company

Example Path 2

KubeHound - Central InfoSec Penetration Testing Company

Exposed Endpoint Leads to cluster-admin

KubeHound - Central InfoSec Penetration Testing Company

Terminology Overview


Graph Theory

  • Graph - A data type to represent complex, non-linear relationships between objects
  • Vertex - The fundamental unit of which graphs are formed (also known as "node")
  • Edge - A connection between vertices (also known as "relationship")
  • Path - A sequence of edges which joins a sequence of vertices
  • Traversal - The process of visiting (checking and/or updating) each vertex in a graph

KubeHound

  • Entity - An abstract representation of a Kubernetes component that form the vertices (nodes) of the attack graph. These do not necessarily have a one-to-mapping to Kubernetes objects, but represent a related construct in an attacker's mental model of the system. Each entity can be tied back to one (or more) Kubernetes object(s) from which it derived via vertex properties
  • Attack - All edges in the KubeHound graph represent a net "improvement" in an attacker's position or a lateral movement opportunity. Thus, if any two vertices in the graph are connected, we know immediately that an attacker can move between them. As such attack and edge are used interchangeably throughout the project
  • Critical Asset - An entity in KubeHound whose compromise would result in cluster admin (or equivalent) level access

Attacks

A majority of the attacks map to MITRE ATT&CK tactics and techniques
  • CE_MODULE_LOAD - Container escape: Load kernel module
  • CE_NSENTER - Container escape: nsenter
  • CE_PRIV_MOUNT - Container escape: Mount host filesystem
  • CE_SYS_PTRACE - Container escape: Attach to host process via SYS_PTRACE
  • CE_UMH_CORE_PATTERN - Container escape: through core_pattern usermode_helper
  • CONTAINER_ATTACH - Attach to running container
  • ENDPOINT_EXPLOIT - Exploit exposed endpoint
  • EXPLOIT_CONTAINERD_SOCK - Container escape: Through mounted container runtime socket
  • EXPLOIT_HOST_READ - Read file from sensitive host mount
  • EXPLOIT_HOST_TRAVERSE - Steal service account token through kubelet host mount
  • EXPLOIT_HOST_WRITE - Container escape: Write to sensitive host mount
  • IDENTITY_ASSUME - Act as identity
  • IDENTITY_IMPERSONATE - Impersonate user/group
  • PERMISSION_DISCOVER - Enumerate permissions
  • POD_ATTACH - Attach to running pod
  • POD_CREATE - Create privileged pod
  • POD_EXEC - Exec into running pod
  • POD_PATCH - Patch running pod
  • ROLE_BIND - Create role binding
  • SHARE_PS_NAMESPACE - Access container in shared process namespace
  • TOKEN_BRUTEFORCE - Brute-force secret name of service account token
  • TOKEN_LIST - Access service account token secrets
  • TOKEN_STEAL - Steal service account token from volume
  • CE_VAR_LOG_SYMLINK - Read file from sensitive host mount
  • VOLUME_ACCESS - Access host volume
  • VOLUME_DISCOVER - Enumerate mounted volumes

KubeHound DSL

KubeHound DSL (Domain-Specific Language) is an overlay on the Gremlin query language that simplifies queries for the most common use cases.

The KubeHound DSL can be used by starting a traversal with kh vs the traditional g. All gremlin queries will work exactly as normal, but a number of additional steps specific to KubeHound will be available.

First 100 vertices in the kubehound graph

kh.V().limit(100)

Count of containers

kh.containers().count()

Count of pods

kh.pods().count()

Count of nodes

kh.nodes().count()

Attacks from all containers

kh.containers().attacks()
kh.containers().attacks().limit(100)

Get the properties of the first container matching the name "central-infosec"

kh.containers().has("name", TextP.containing("central-infosec")).limit(1).valueMap()

Attacks from containers containing the name "central-infosec"

kh.containers().has("name", TextP.containing("central-infosec")).attacks()

Count of attacks from all containers

kh.containers().attacks().count()

Critical attack paths that allow an attacker to gain full privileges on the cluster (e.g., by gaining the cluster-admin ClusterRole)

kh.containers().criticalPaths()

Critical attack paths from containers containing the name "central-infosec"

kh.containers().has("name", TextP.containing("central-infosec")).criticalPaths()

Number of critical attack paths from containers

kh.containers().criticalPaths().count()

Attack paths from containers using a filter

kh.containers().criticalPathsFilter(10, "TOKEN_BRUTEFORCE", "TOKEN_LIST")

Critical attack paths that allow an attacker to gain full privileges on the cluster (e.g., by gaining the cluster-admin ClusterRole), deduplicating by container name

kh.containers().dedup().by("name").criticalPaths().count()

Attacks from containers running the cilium 1.11.18 image

kh.containers().has("image", "eu.gcr.io/internal/cilium:1.11.18").attacks()

Counts of containers by name

kh.containers().valueMap().groupCount().by("name")

Containers running as root by name

kh.containers().has("runAsUser", 0).groupCount().by("name")

Privileged containers by name

kh.containers().has("privileged", true).valueMap().groupCount().by("name")

Privileged containers running as root by name

kh.containers().has("privileged", true).has("runAsUser", 0).groupCount().by("name")

Attacks for privileged containers running as root by name

kh.containers().has("privileged", true).has("runAsUser", 0).attacks()

More than 10 paths / long path

kh.containers().repeat(both().simplePath()).until(loops().is(gte(10))).path().limit(1)

Vertices in the graph from the central-infosec.local cluster

kh.cluster("central-infosec.local")

Containers in the graph from the central-infosec.local cluster

kh.cluster("central-infosec.local").containers()

Attack paths that start with a container with an exposed endpoint. EndpointExposure.ClusterIP: The container does not externally expose any port, but the endpoint can still be accessed from within the cluster

kh.endpoints(EndpointExposure.ClusterIP).criticalPaths().count()

Attack paths that start with a container with an exposed endpoint. EndpointExposure.NodeIP: The container exposes an external port that can be accessed depending on firewall rules

kh.endpoints(EndpointExposure.NodeIP).criticalPaths().count()

Attack paths that start with a container with an exposed endpoint. EndpointExposure.External: The container exposes an endpoint outside the cluster. This type of endpoint can also be accessed with kh.services()

kh.endpoints(EndpointExposure.External).criticalPaths().count()
kh.services().criticalPaths().count()

Export the service DNS name and the associated port to scan as a starting point in the attack

kh.endpoints(EndpointExposure.External).criticalPaths().limit(local,1).dedup().valueMap("serviceDns","port").group().by("serviceDns").by("port")

Get the roles that an attacker would gain if they manage to successfully exploit an endpoint

kh.endpoints(EndpointExposure.External).criticalPaths().tail(local,1).dedup().values("role")

Lateral movement that an attacker can perform including which containers can be reached

kh.containers().has("pod",TextP.containing("central-infosec-pod")).repeat(outE().inV().simplePath())
.until(hasLabel("Container").or().loops().is(10).or().has("critical", true)).hasLabel("Container").path()

Containers

Containers in the graph

kh.containers()

Container names

kh.containers().values("name").dedup()

Containers in the graph with name filter

kh.containers("elasticsearch", "mongo", "central-infosec")

Containers in the graph with additional filters

kh.containers().has("namespace", "ns1").limit(10)

Get the number using the Ubuntu image

kh.containers().has("image",TextP.containing("ubuntu")).groupCount().by("image")
kh.containers().has("image",TextP.regex(".*ubuntu.*")).groupCount().by("image")

Counts of images with critical paths

kh.containers().hasCriticalPath().groupCount().by("image")

Count of each image

kh.containers().groupCount().by("image")

Count of images leading to critical assets

kh.containers().criticalPaths().limit(local,1).groupCount().by("image")

Count of images leading to attacks

kh.containers().attacks().limit(local,1).groupCount().by("image")

Pods

Pods in the graph

kh.pods()

Pod names

kh.pods().values("name").dedup()

Pods in the graph with name filter

kh.pods("app-pod", "sidecar-pod", "central-infosec-pod")

Pods in the graph with additional filters

kh.pods().has("namespace", "ns1").limit(10)

Nodes

Nodes in the graph

kh.nodes()

Node names

kh.nodes().values("name").dedup()

Nodes in the graph with name filter

kh.nodes("control-plane")

Nodes in the graph with additional filters

kh.nodes().has("name", "central-infosec").limit(10)
kh.nodes().has("team", "central-infosec").limit(10)

Escapes

Container escapes in the graph

kh.escapes()

Container escapes in the graph with node name filter

kh.escapes("control-plane")

Endpoints

Endpoints in the graph

kh.endpoints()

Endpoint names

kh.endpoints().values("name").dedup()

Endpoints in the graph with additional filters

kh.endpoints().has("port", 3000).limit(10)

Endpoints with K8s service exposure

kh.endpoints(EndpointExposure.External)

Services

Services in the graph

kh.services()

Service names

kh.services().values("name").dedup()

Services in the graph with name filter

kh.services("jmx", "redis")

Services in the graph with additional filters

kh.services().has("port", 9999).limit(10)

Volumes

Volumes in the graph

kh.volumes()

Volume names

kh.volumes().values("name").dedup()

Volumes in the graph with name filter

kh.volumes("db-data", "proc-mount")

Volumes in the graph with additional filters

kh.volumes().has("sourcePath", "/").has("app", "web-app", "cis")

HostMounts

Host mounted volumes in the graph

kh.hostMounts()

hostMount names

kh.hostMounts().values("name").dedup()

sourcePaths of the hostMounts

kh.hostMounts().values("sourcePath").dedup()

mountPaths of the hostMounts

kh.hostMounts().values("mountPath").dedup()

Host mount volumes in the graph with source path filter

kh.hostMounts("/", "/proc")

Host mount volumes in the graph with additional filters

kh.hostMounts().has("app", "web-app", "cis").limit(10)

Identities

Identities in the graph

kh.identities()

Identity names

kh.identities().values("name").dedup()

Identities in the graph with name filter

kh.identities("postgres-admin", "db-reader", "central-infosec")

Identities in the graph with additional filters

kh.identities().has("app", "web-app").limit(10)

Service Accounts

Service accounts in the graph

kh.sas()

Service account names

kh.sas().values("name").dedup()

Service accounts in the graph with name filter

kh.sas("postgres-admin", "db-reader", "central-infosec")

Service accounts in the graph with additional filters

kh.sas().has("app", "web-app").limit(10)

Users

Users in the graph

kh.users()

User names

kh.users().values("name").dedup()

Users in the graph with name filter

kh.users("postgres-admin", "db-reader", "central-infosec")

Users in the graph with additional filters

kh.users().has("app", "web-app").limit(10)

Groups

Groups in the graph

kh.groups()

Group names

kh.groups().values("name").dedup()

Groups in the graph with name filter

kh.groups("postgres-admin", "db-reader", "central-infosec")

Groups in the graph with additional filters

kh.groups().has("app", "web-app").limit(10)

Permissions

Permissions sets in the graph

kh.permissions()

Permission names

kh.permissions().values("name").dedup()

Permissions sets in the graph with role filter

kh.permissions("postgres-admin", "db-reader", "central-infosec")

Permissions sets in the graph with additional filters

kh.permissions().has("app", "web-app").limit(10)

Attacks

Attacks possible from a specific container in the graph

kh.containers("central-infosec-pwned-container").attacks()

Critical Assets

Critical assets in the graph

kh.V().critical()

Check whether a specific permission set is marked as critical

kh.permissions("system::kube-controller").critical()

Critical Paths

Attack paths from services to a critical asset

kh.services().criticalPaths()

Number of critical attack paths

kh.V().criticalPaths().count()

Attack paths (up to 5 hops) from a compromised credential to a critical asset

kh.groups("central-infosec").criticalPaths(5)

Critical PathsFilter

Attack paths (up to 10 hops) from services to a critical asset excluding the TOKEN_BRUTEFORCE and TOKEN_LIST attacks

kh.services().criticalPathsFilter(10, "TOKEN_BRUTEFORCE", "TOKEN_LIST")
kh.services().criticalPathsFilter(10, "TOKEN_BRUTEFORCE", "TOKEN_LIST").count()

HasCriticalPath

Services with an attack path to a critical asset

kh.services().hasCriticalPath()

Number of services with an attack path to a critical asset

kh.services().hasCriticalPath().count()

MinHopsToCritical

Shortest exploitable path between an external service and a critical asset

kh.services().minHopsToCritical()

Shortest exploitable path from a compromised central-infosec credential to a critical asset (up to 10)

kh.groups("central-infosec").minHopsToCritical(10)

CriticalPathsFreq

Most common critical paths from services

kh.services().criticalPathsFreq()

Most common critical paths from a compromised central-infosec credential of up to 10 hops

kh.groups("central-infosec").criticalPathsFreq(10)

Gremlin Queries

Basic Queries

You can query KubeHound data stored in the JanusGraph database by using the Gremlin query

Show edges

g.E()
g.E().limit(50)

Show vertices

g.V()
g.V().limit(50)

Get the count of pods

g.V().hasLabel("Pod").count()

Get the properties of the first pod

g.V().hasLabel("Pod").limit(1).valueMap()

Get the properties of the first pod with the name "central-infosec-pod"

g.V().hasLabel("Pod").has("name", "central-infosec-pod").limit(1).valueMap()

View the pods with the name "central-infosec-pod"

g.V().hasLabel("Pod").has("name", "central-infosec-pod")

View the pods with names that contain "central-infosec"

g.V().hasLabel("Pod").has("name", TextP.containing("central-infosec"))

View compromised pods

g.V().hasLabel("Pod").has("compromised", 1)

View items with names containing the string "central-infosec"

g.V().has("name", TextP.containing("central-infosec"))

View attack paths from items with names containing the string "central-infosec"

g.V().has("name", TextP.containing("central-infosec")).attacks()

Find paths from vertices labeled "Container" to vertices labeled "Node" via outgoing edges

g.V().hasLabel("Container").outE().inV().hasLabel("Node").path()

Group the edges in the graph by their labels and counts the number of edges for each label

g.E().groupCount().by(label)

Filter vertices labeled "Volume" that have a property "type" with the value "HostPath". Then groups these vertices by the value of their "sourcePath" property and counts the occurrences of each group

g.V().hasLabel("Volume").has("type", "HostPath").groupCount().by("sourcePath")

Filter vertices labeled "Volume" that have a property "type" with the value "HostPath" with a "sourcePath" of "/etc/passwd"

g.V().hasLabel("Volume").has("type", "HostPath").has("sourcePath", "/etc/passwd")

Filter vertices labeled "Volume" that have a property "type" with the value "HostPath" with a "sourcePath" of "/etc/passwd" and show incoming edges

g.V().hasLabel("Volume").has("type", "HostPath").has("sourcePath", "/etc/passwd").inE()

Select edges with labels "EXPLOIT_HOST_READ" or "EXPLOIT_HOST_WRITE". Then traverses to the outgoing vertices and groups them by the value of their "sourcePath" property, counting the occurrences of each group

g.E().hasLabel("EXPLOIT_HOST_READ", "EXPLOIT_HOST_WRITE").outV().groupCount().by("sourcePath")

Leveraging the "EndpointExposureType" enum value to filter only on services

g.V().hasLabel("Endpoint").has("exposure", 3).groupCount().by("serviceEndpoint")

Leveraging the "EndpointExposureType" enum value to filter only on services with the serviceEndpoint of "admin"

g.V().hasLabel("Endpoint").has("exposure", 3).has("serviceEndpoint", "admin")

Basic Attack Paths

Endpoint to Node Path

This query starts from vertices labeled as "Endpoint" and traverses outgoing edges in a loop until it reaches a vertex labeled as "Node." An attacker might leverage this path to move from an endpoint to a critical node in the system. For example, if an endpoint has direct access to a node and there are security misconfigurations or vulnerabilities in the communication between the endpoint and the node, an attacker could exploit these weaknesses to compromise the node.

g.V().hasLabel("Endpoint").repeat(out().simplePath()).until(hasLabel("Node")).path()

Container to Node Path

This query starts from vertices labeled as "Container" and traverses outgoing edges in a loop. It continues until it either reaches a vertex labeled as "Node" or completes five loops. An attacker might use this path to move from a container to a critical node in the system. If there are vulnerabilities or misconfigurations in the containers or the communication between containers and nodes, an attacker could exploit these issues to compromise a node.

g.V().hasLabel("Container").repeat(out().simplePath()).until(hasLabel("Node").or().loops().is(5)).hasLabel("Node").path()

Critical Identity Path

This query starts from vertices labeled as "Identity" and traverses outgoing edges in a loop. It continues until it either reaches a vertex with the property "critical" set to true or completes six loops. An attacker might exploit this path to identify critical identities in the system. If an identity with critical privileges or access is reachable from a starting identity, an attacker could compromise the system by impersonating or escalating privileges through these critical identities.

g.V().hasLabel("Identity").repeat(out().simplePath()).until(has("critical", true).or().loops().is(6)).has("critical", true).path().limit(5)

Attack paths from compromised assets

Containers

g.V().hasLabel("Container").has("name", "nsenter-pod").repeat(out().simplePath())
.until(has("critical", true).or().loops().is(10)).has("critical", true).path()

g.V().hasLabel("Container").has("image", TextP.containing("malicious-image")).repeat(out().simplePath())
.until(has("critical", true).or().loops().is(10)).has("critical", true).path()

More than 5 paths from an endpoint / long path

g.V().hasLabel("Endpoint").repeat(out().simplePath()).until(loops().is(gte(5))).path().limit(1)

More than 5 paths from a container / long path

g.V().hasLabel("Container").repeat(out().simplePath()).until(loops().is(gte(5))).path().limit(1)

Credentials

g.V().hasLabel("Identity").has("name", "compromised-sa").repeat(out().simplePath()).until(has("critical", true).or().loops().is(10)).has("critical", true).path()

Endpoints

g.V().hasLabel("Endpoint").repeat(out().simplePath()).until(has("critical", true).or().loops().is(6)).has("critical", true).path().limit(5)
g.V().hasLabel("Endpoint").has("portName", "jmx").repeat(out().simplePath()).until(has("critical", true).or().loops().is(6)).has("critical", true).path().limit(5)

Risk assessment

g.V().hasLabel("Endpoint").has("exposure", gte(3)).repeat(out().simplePath())
.until(has("critical", true).or().loops().is(7)).has("critical", true).path().count(local).min()

Base case

g.V().hasLabel("Endpoint").has("exposure", gte(3)).count()

Has a critical path

g.V().hasLabel("Endpoint").has("exposure", gte(3)).where(repeat(out().simplePath())
.until(has("critical", true).or().loops().is(10)).has("critical", true).limit(1)).count()

More than five paths

g.V().hasLabel("Endpoint").has("exposure", gte(3)).repeat(out().simplePath()).until(loops().is(gte(5))).path()

More than three paths

g.V().hasLabel("Endpoint").has("name", TextP.containing("central-infosec")).repeat(out().simplePath()).until(loops().is(gte(3))).path()

CVE impact assessment

You can also use KubeHound to determine if workloads in your cluster may be vulnerable to a specific vulnerability.

First, evaluate if a known vulnerable image is running in the cluster

g.V().hasLabel("Container").has("image", TextP.containing("elasticsearch")).groupCount().by("image")

Then, check any exposed services that could be affected and have a path to a critical asset. This helps prioritizing patching and remediation

g.V().hasLabel("Container").has("image", "dockerhub.com/elasticsearch:7.1.4").where(inE("ENDPOINT_EXPLOIT")
.outV().has("exposure", gte(3))).where(repeat(out().simplePath()).until(has("critical", true).or().loops().is(10)).has("critical", true).limit(1))

Assessing the value of implementing new security controls

To verify concrete impact, this can be achieved by comparing the difference in the key risk metrics above, before and after the control change. To simulate the impact of introducing a control (e.g to evaluate ROI), add conditions to path queries. For example if we wanted to evaluate the impact of adding a gatekeeper rule that would deny the use of hostPID we can use the following

Calculate the base case

g.V().hasLabel("Endpoint").has("exposure", gte(3)).repeat(out().simplePath()).until(has("critical", true).or().loops().is(6)).has("critical", true).path().count()

The "CE" stands for "container escape"

Calculate the impact of preventing CE_NSENTER attack

g.V().hasLabel("Endpoint").has("exposure", gte(3)).repeat(outE().not(hasLabel("CE_NSENTER")).inV().simplePath())
.emit().until(has("critical", true).or().loops().is(6)).has("critical", true).path().count()

Count the number of instances of unique attack paths using

g.V().hasLabel("Container").repeat(outE().inV().simplePath()).emit()
.until(has("critical", true).or().loops().is(6)).has("critical", true)
.path().by(label).groupCount().order(local).by(select(values), desc)

Threat modelling

g.V().hasLabel("Container", "Identity")
.repeat(out().simplePath())
.until(has("name", "cluster-admin").or().loops().is(5))
.has("name", "cluster-admin").hasLabel("Role").path().as("p").by(label).dedup().select("p").path()
g.V().hasLabel("Container", "Identity")
.repeat(out().simplePath())
.until(has("critical", true).or().loops().is(5))
.has("critical", true).path().as("p").by(label).dedup().select("p").path()

Metrics

Unique labels

g.V().label().dedup()

Counts of multiple labels

g.V().hasLabel("Pod", "Node", "Service", "Volume", "Container", "Identity", "PermissionSet", "Endpoint").groupCount().by(label)

Count of all vertices

g.V().count()

Count of edges

g.E().count()

Count of pods

kh.pods().count()
g.V().hasLabel("Pod").count()

Count of nodes

g.V().hasLabel("Node").count()

Count of services

kh.services().count()
g.V().hasLabel("Service").count()

Count of volumes

g.V().hasLabel("Volume").count()

Count of containers

g.V().hasLabel("Container").count()



Pen Test Your Kubernetes

Central InfoSec security professionals have decades of experience and can uncover critical misconfigurations in your Kubernetes environment.




Best Pen Test Companies

Central InfoSec was rated the "best boutique penetration testing company" and the "best penetration testing firm" multiple years in a row by two independent third-party organizations that review many contributing factors.



Professional Security Services Offered by Central InfoSec

Central InfoSec offers a variety of professional security services including:

  • Red Teaming
    • Attack simulation to test, measure, and improve your detection and response
  • Penetration Testing
    • Real-world security tests using advanced hacking methods to identify your weaknesses
  • Kubernetes Security Audit
    • Identification of potential vulnerabilities and misconfigurations in your Kubernetes environment
  • Cloud Security Assessments (Azure & AWS)
    • Identification of potential vulnerabilities in your cloud
  • Application & API Testing
    • Testing of security controls and products to identify your gaps and weaknesses
  • vCISO Services
    • Virtual CISO (vCISO) services allowing immediate access to strategic security guidance
  • Cyber Risk Management
    • Cyber solutions to help address security threats and to help you reach your security initiatives
  • Phishing Assessment
    • Effective security awareness training through social engineering and phishing emails
  • Managed Phishing
    • Routine phishing campaigns to track and measure the security awareness of your employees
  • Password Audit
    • Detection of weak passwords to help you improve your password policies
  • C2 & Pivot Testing
    • Command and control (C2) communications, pivoting, and data exfiltration testing
  • Purple Team Tabletop
    • Targeted training exercises to measure people, processes, and technologies
  • Security Training
    • Fully customizable cyber security training and employee awareness support


Best Boutique Penetration Testing Company

Central InfoSec named Best Boutique Penetration Testing Company by the Global 100 Awards.

Central InfoSec Best Boutique Penetration Testing Company

Best Penetration Testing Firm

Central InfoSec named Best Penetration Testing Firm by Corporate Vision's Corporate Excellence Awards.

Central InfoSec Best Penetration Testing & Security Consulting Firm

"Central InfoSec helps organizations by discovering network and web application vulnerabilities before the hackers do!"


Central InfoSec is an award-winning cyber security company that offers professional security services including Red Teaming, Penetration Testing, and Security Training.

The Central InfoSec team consists of skilled security professionals bringing a total of 20+ years of red teaming, penetration testing, web application, and exploitation experience. Central InfoSec team members have achieved industry leading professional certifications including CRTO, OSCP, OSWP, GXPN, GPEN, GCPN, GWAPT, GMOB, AWS-CSS, AWS-CCP, PenTest+, CEH, CISSP, and more.

The Central InfoSec team goes one step further and develops open-source tools including Burp Suite extensions, Cobalt Strike aggressor scripts, scripts tying into tools (including GoPhish, PhishMe, Slack, Lair), other custom-built security tools, and Capture The Flag (CTF) events!

Central InfoSec performs a variety of penetration tests including external-networks, internal-networks, web applications, and APIs. The company quickly informs clients of critical vulnerabilities by creating ad-hoc reports and hosting ad-hoc debriefs as necessary.

Best Penetration Testing & Security Consulting Firm

Central InfoSec Best Penetration Testing & Security Consulting Firm

Central InfoSec Red Teaming
& Penetration Testing

Central InfoSec can quickly uncover critical vulnerabilities that have been missed for years. No automated scanning tool can replace high-quality security professionals. Utilizing Central InfoSec’s custom-built tools and manual analysis, Central InfoSec’s security experts have found numerous vulnerabilities within web applications including multiple 0-days allowing direct access to web servers hosting the applications. Once critical vulnerabilities are discovered, Central InfoSec’s experts work directly with application developers to address security flaws. With many success stories, Central InfoSec is constantly contributing to the community by sharing its knowledge through blogs, open-source projects, tool development, conferences, presentations, and local security meetups.

Every organization, at a minimum, should receive both network pen testing and web application pen testing, and cost should never be the reason that quality testing is not performed. Therefore, the company focuses on offering quality and affordable professional security services while increasing security awareness at organizations. The Central InfoSec team educates clients through security assessments and tailored security training while also helping with permanent resource staffing. We want to help organizations understand the core foundation to security, help businesses acquire the appropriate staff that they need, and help strengthen security postures through offensive security testing.

Central InfoSec Best Boutique Penetration Testing Firm - Top Rated Red Team Companies

Best Boutique Pen Test Company

Central InfoSec strengthens the security posture of businesses by reducing cyber risk through red teaming and pen testing.

Best Boutique Pen Test Company

Let’s Work Together

If you’d like to see why Global 100 selected Central InfoSec as the Best Boutique Pen Test Company, let's have a chat to see how you could benefit from Central InfoSec security services. It’s simple and easy. We’ll even include a free customized quote. Let’s get started: Contact Us

Central InfoSec offers a variety of other professional security services to help you test, measure, and improve your overall security posture. Security services offered include red teaming, pen testing, vulnerability assessments, web app testing, managed phishing, and other tailored security services to help you reduce risk to your organization.

Central InfoSec Core Values

Quality

Performance

Honesty

Integrity

Innovation

Reliability

Contact Central InfoSec Today!

Don't wait for a data breach to invest into your cybersecurity.

Central InfoSec Red Teaming and Penetration Testing can uncover your network and application vulnerabilities before the cyber criminals do!