This document provides recipes for containerizing and deploying common C2 frameworks like Cobalt Strike and Merlin on Kubernetes. It discusses using Docker to containerize the C2 payloads, creating Kubernetes deployments, services, and ingress resources to expose the containers. It also covers using Nginx Ingress and Istio service mesh with Envoy sidecars to provide redirection and traffic manipulation capabilities for C2 infrastructure on Kubernetes.
2. Who we are
◎Larry Suto - Larry is an independent
security consultant based out of Oakland,
CA. He spends a lot of time researching
using cloud infrastructure for all types of
security testing. He spends some time on
Windows security as well.
Twitter: @larrysuto
2
3. Who we are
◎Jeff Holden – Works at the largest college
system in the united states. CISO by day,
hacker by night. Currently living in an RV
with 3 dogs, 1 wife, and 1 kid.
◎@jeffh
4. Goals
◎Working in AWS, GCE, Azure
◎Automated
○ Set domains, access keys, etc
◎Portable
◎Scriptable
10. What is this Kops thing?
• Takes care of the infrastructure grunt work
• Creates Network
• Creates Base VMs
• Creates load balancer
• Creates Access list
• Supports
• AWS
• GCE
12. External DNS
◎Support all major cloud services
◎ Pod adds and updates DNS entries to
cloud providers DNS
○ Need to use cloud provider specific tool to create
hosted zone
○ Can automate domain registration
12
15. Background
◎Placing Apache mod_rewrite in front of C2 infrastructure has been common
place for many years now
◎Many advances have been made in redirection technology recently driven
by the move to container-based cloud systems such as Kubernetes
◎Adoption of Docker by the red team is common but we have seen little in
the way of container management systems and service mesh technology
which provide sophisticated mechanisms for ingress and egress
manipulation
◎Service mesh technology holds a lot of promise for sophisticated c2
redirection and traffic manipulation and can leverage multiple clouds with
many simultaneous ingress points
◎With Kubernetes its quite straight forward to introduce new redirection
point dynamically
16. Recipes for Containerizing C2
◎Candidates
○ Cobalt Strike
○ Merlin (http/2)
○ Many others (Empire, Faction, silver, Covenant,..)
28. ConfigMaps in nginx-controller
◎The ConfigMap API resource stores configuration data
as key-value pairs. The data provides the
configurations for system components for the nginx-
controller.
◎https://kubernetes.github.io/ingress-nginx/user-
guide/nginx-configuration/configmap/
◎use-http2
○ Enables or disables HTTP/2 support in secure connections.
33. Convert mod_rewrite to nginx-ingress
◎https://winginx.com/en/htaccess
RewriteCond %{HTTP_USER_AGENT} "wget|curl|HTTrack|crawl|google|bot|b-o-t|spider|baidu" [NC,OR]
RewriteCond %{HTTP_USER_AGENT} =""
RewriteRule ^.*$ http://COMPANYDOMAIN.com/404.html/? [L,R=302]
location / {
if ($http_user_agent ~* ""wget|curl|HTTrack|crawl|google|bot|b-o-t|spider|baidu""){
rewrite ^(.*)$ http://www.google.com/404.html/? redirect;
}
}
Location block can be dropped into an Ingress definition using the configuration
snippet we just described
nginx rewrite
mod_rewrite
34. Create External Back End
kind: Service
apiVersion: v1
metadata:
name: google
namespace: default
spec:
type: ExternalName
externalName: www.google.com
39. Validate the Addition of the Annotations
kubectl exec nginx-ingress-controller-873061567-4n3k2 –n
kube-system cat /etc/nginx/nginx.conf
40. Istio Service Mesh
Mixer Istio-AuthPilot
Envoy Envoy
SvcA SvcB
Envoy
Istio-Ingress
(Gateway)
Service A (C2) Service B
http, https,
http/2 http, https,
http/2
http, https,
http/2
41. Envoy Proxy
◎Envoy supports an HTTP level filter stack within the connection
manager.
◎Filters can be written that operate on HTTP level messages
without knowledge of the underlying physical protocol
(HTTP/1.1, HTTP/2, etc.) or multiplexing capabilities.
◎Three Types:
○ Decoder: Decoder filters are invoked when the connection manager is decoding
parts of the request stream (headers, body, and trailers).
○ Encoder: Encoder filters are invoked when the connection manager is about to
encode parts of the response stream (headers, body, and trailers).
○ Decoder/Encoder:
◎Istio can manage Envoy configuration
◎Envoy supports custom LUA scripts for HTTP filtering
42. Installing Istio
◎kubectl create namespace istio-system
◎Install CRD with kubectl apply
◎helm install install/kubernetes/helm/istio --name istio --namespace istio-system
--values install/kubernetes/helm/istio/values-istio-demo.yaml
◎Inject the Istio/Envoy sidecar manually or using injection webhook
○ istioctl kube-inject -f samples/sleep/sleep.yaml | kubectl apply -f -
○ kubectl label namespace default istio-injection=enabled –overwrite
◉ Injection occurs when the pod restarts
43. Istio Ingress
◎kubectl get svc istio-ingressgateway -n istio-system
◎Handles http or tcp ingress
◎Overcomes weaknesses of Kubernetes Ingress
○ Kubernetes Ingress mostly focused on http/https
◎Generally auto-provisions a load balancer
43
47. Exposing Services via Istio-ingeress gateway
◎To expose a service using ingressgateway you have to create at
least 2 objects
○ Gateway
○ Virtual Service
48. Istio Gateway
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: teamserver-gateway
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 80
name: http-system
protocol: HTTP
hosts:
- "*"
- port:
number: 50050 # exposes teamserver admin port
name: tcp-admin
protocol: TCP
hosts:
- "*"
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: PASSTHROUGH
hosts:
- "*"
Gateway describes a load
balancer operating at the edge
of the mesh receiving incoming
or outgoing HTTP/TCP
connections.
49. Virtual Services
◎A Virtual Service defines a set of traffic routing rules to
apply when a host is addressed. A routing rule defines
matching criteria for traffic of a specific protocol.
◎If the traffic is matched, then it is sent to a named
destination service (or subset/version of it) defined in the
registry.
◎Supports many protocols : http, https, http/2
52. StringMatch for HTTP Headers
Field Type Description
exact string (oneof ) exact string match
prefix string (oneof ) prefix-based match
regex string (oneof ) ECMAscript style regex-based match
Case sensitive
53. Istio ingressgateway Tips
◎A selector is used by istio to select the ingressgateway.
This is important when there are multiple
ingressgateways
◎istio uses port naming in some routing logic
◎Port names are of the form protocol-suffix with grpc,
http, http2, https, mongo, redis, tcp, tls or udp as the
protocol.
54. Routing to External Destinations
◎Envoy passthrough to external services
○ On by default
○ global.outboundTrafficPolicy.mode option set to ALLOW_ANY
○ kubectl get configmap istio -n istio-system -o yaml | grep -o "mode:
ALLOW_ANY"
55. Notes on Ingress Capabilities
◎A mesh can have any number of gateways, and multiple different implementations of the
gateway can coexist
◎The Kubernetes Ingress API cannot express the routing needs of Istio. Kubernetes Ingress
looks for a common intersection between different HTTP proxies. It only supports the most
basic of HTTP routing.
◎Kubernetes Ingress itself does not support the TCP protocol. Kubernetes Ingress cannot be
set up to configure an NGINX Ingress Controller for TCP load balancing – requires a special
configmap
◎Istio Gateway has overcome the above shortcomings of Ingress by separating the L4-L6
configuration from the L7 configuration
◎Gateway is only used to configure L4-L6 functions
○ exposed ports, TLS configuration
◎A VirtualService is bound a Gateway in order to control inbound TCP and HTTP traffic
56. Drone
◎Drone is a modern CI/CD platform built with
containers as first class citizens. Pipelines are
configured using a yaml file that you check-in to your
git repository.
◎Can be deployed as a Docker container to a VM or a
Kubernetes cluster
◎Integrates with git repository and can deploy pipelines
to a Kubernetes cluster
58. Monitoring C2 with Prometheus
◎Open source metrics based monitoring system
◎Can be used to instrument application
◎Applications without instrumentation support can be monitored
using exporters and other legacy methods
○ extract whitebox monitoring data from application logs for collection
in a timeseries database
○ Google mtail
○ Grok Exporter
○ JMX (Cobalt Strike teamserver is a Java application so theoretically it
could be supported)
◎C2 authors and developers can instrument code to provide fine
grained monitoring support
59. Google mtail
◎Can be used to create timeseries data from standard logs
○ https://github.com/google/mtail/blob/master/docs/Programming-
Guide.md
◎Prometheus exporter is available
◎Cobalt Strike teamserver logs are in the Cobalt Strike working
directory:
○ Ie /opt/cobaltstrike/logs
○ Weblogs and beacon session logs are available
◎Use mtail to create counters by matching events in log with
regular expressions
60. Grok Exporter
◎https://github.com/fstab/grok_exporter
◎Can be used to convert arbitrary logs into
Prometheus compatible time series data
◎An example would be the Cobalt Strike
beacon log checkin entry
○ This interval can be collected as a metric to
monitor beacon health
◎Grok Exporter uses same language as
64. Envoy LUA Filters
◎Inspection of headers, body, and trailers while streaming in either the
request flow, response flow, or both.
◎Modification of headers and trailers.
◎Blocking and buffering the full request/response body for inspection.
◎Performing an outbound async HTTP call to an upstream host. Such a
call can be performed while buffering body data so that when the call
completes upstream headers can be modified.
◎Performing a direct response and skipping further filter iteration. For
example, a script could make an upstream HTTP call for authentication,
and then directly respond with a 403 response code.
64
65. ISTIO Envoy and LUA Filters
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: csc2-lua
spec:
workloadLabels:
app: csc2
filters:
- listenerMatch:
portNumber: 8080
listenerType: SIDECAR_INBOUND # will match with the
inbound listener for csc2:8080
listenerProtocol: HTTP
filterName: csc2.lua
filterType: HTTP
filterConfig:
inlineCode: |
... lua code ...
66. Example LUA Filter
66
-- Called on the request path.
function envoy_on_request(request_handle)
-- Wait for the entire request body and add a request header with the body size.
request_handle:headers():add("request_body_size", request_handle:body():length())
end
-- Called on the response path.
function envoy_on_response(response_handle)
-- Wait for the entire response body and a response header with the the body size.
response_handle:headers():add("response_body_size",
response_handle:body():length())
-- Remove a response header named 'foo'
response_handle:headers():remove("foo")
end