Skip to main content
Splunk Lantern

Amazon EKS Kubernetes pod scan detection

Kubernetes pods are a group of one or more containers with shared storage and a specification for how to run the containers. A pod's contents are always co-located and co-scheduled. You might want to look for unauthenticated requests against your Kubernetes' pods API when doing the following:

Prerequisites 

In order to execute this procedure in your environment, the following data, services, or apps are required:

Example

One of your concerns with using Kubernetes is unauthenticated requests. You want to know if your pods are being targeted, and, if so, to get details.

NOTE: To optimize the search shown below, you should specify an index and a time range.

  1. Ensure that you have configured your AWS CloudWatch EKS logs.
  2. Run the following search: 
sourcetype="aws:cloudwatchlogs:eks" "user.username"="system:anonymous" verb=list objectRef.resource=pods requestURI="/api/v1/pods" 
| rename source AS cluster_name sourceIPs{} AS src_ip
| stats count min(_time) AS firstTime max(_time) AS lastTime values(responseStatus.reason) values(responseStatus.code) values(userAgent) values(verb) values(requestURI) BY src_ip cluster_name user.username user.groups{} 
| convert timeformat="%m/%d/%Y %H:%M:%S" ctime(lastTime)
| convert timeformat="%m/%d/%Y %H:%M:%S" ctime(firstTime)

Search explanation

The table provides an explanation of what each part of this search achieves. You can adjust this query based on the specifics of your environment.

Splunk Search Explanation

sourcetype="aws:cloudwatchlogs:eks"

Search only AWS EKS Kubernetes data.

"user.username"="system:anonymous" 

Search for anonymous users.

verb=list 

Search for the API list resource request, which returns a collection of resources.

objectRef.resource=pods 

Search your Kubernetes pods data.

requestURI="/api/v1/pods"

Search for requests to this specific URI.

| rename source AS cluster_name sourceIPs{} AS src_ip

Rename the fields as shown for better readability and for Splunk processing capability.

| stats count min(_time) as firstTime max(_time) AS lastTime values(responseStatus.reason) values(responseStatus.code) values(userAgent) values(verb) values(requestURI) BY src_ip cluster_name user.username user.groups{} 

Count the number of times the values shown occurred for each unique source IP address, cluster, user name, and user group. 

| convert timeformat="%m/%d/%Y %H:%M:%S" ctime(lastTime)

| convert timeformat="%m/%d/%Y %H:%M:%S" ctime(firstTime)

Convert these times into readable strings.

Result

Not all unauthenticated requests are malicious, but frequency of requests, user agent, source IP addresses, and direct requests to the API provide context. Watch for IP addresses flagged as malicious by popular IP reputation lists, such as Team Cymru.

For additional information about this search, such as its applicability to common frameworks and standards, see this project on GitHub.

  • Was this article helpful?