Documentation ¶
Overview ¶
Package exploit is the entrypoint for exploits developed with the go-exploit framework.
The exploit package invokes command line parsing, handles c2, and calls into the three stages of exploitation (as defined by go-exploit). In order to use this framework, implementing exploits should follow this general template:
package main import ( "github.com/vulncheck-oss/go-exploit" "github.com/vulncheck-oss/go-exploit/c2" "github.com/vulncheck-oss/go-exploit/config" "github.com/vulncheck-oss/go-exploit/output" ) type MyExploit struct{} func generatePayload(conf *config.Config) (string, bool) { generated := "" switch conf.C2Type { case c2.SimpleShellServer: // generated = reverse.Bash.TCPRedirection(conf.Lhost, conf.Lport) // Example default: output.PrintError("Invalid payload") return generated, false } return generated, true } 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 { generated, ok := generatePayload(conf) if !ok { return false } 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) }
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RunProgram ¶
Effectively the package main function. Parses configuration, starts command and control, controls which targets are scanned, initiates call down into the exploits implementation and is ultimately responsible for waiting for all c2 and attack threads to finish.
This function also runs `flag.Parse()` so any defined flags will be parsed when RunProgram is called.
This function should be called by the implementing exploit, likely in the main function.
func StoreVersion ¶ added in v1.21.0
Prints the version to the log file using status VERSION and a parsable version string (version=). Additionally, updates the database if it's in use. Typically should be called from the exploit.
Types ¶
type Exploit ¶
type Exploit interface { ValidateTarget(conf *config.Config) bool CheckVersion(conf *config.Config) VersionCheckType RunExploit(conf *config.Config) bool }
Exploit is the implementing interface for go-exploit exploits. The functions are called in order: ValidateTarget, CheckVersion, RunExploit.
ValidateTarget ¶
ValidateTarget is for determining if the target is the type of software the implemented exploit would like to exploit. This is to avoid throwing an exploit at target would never be vulnerable. For example, if an exploit is targeting Confluence, then ValidateTarget might look like the following
func (sploit ConfluenceExploit) ValidateTarget(conf *config.Config) bool { url := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, "/") resp, _, ok := protocol.HTTPSendAndRecv("GET", url, "") if !ok { return false } if resp.StatusCode != 200 { output.PrintfError("Received an unexpected HTTP status code: %d", resp.StatusCode) return false } _, ok = resp.Header["X-Confluence-Request-Time"] return ok }
Above you can see ValidateTarget returns true *only* if it finds the X-Confluence-Request-Time HTTP header. The exploit will not continue on if false is returned. If true is returned then it will move on to the next stage (CheckVersion).
CheckVersion ¶
CheckVersion is for determning if the target is an affected version or not. Again, to avoid throwing an exploit at a target that is not vulnerable. CheckVersion is intended to be a non-intrusive version check. That generally means doing things like:
- Extracting the version number from a login page
- Examining the HTTP Last-Modified header
- Looking for new functionality introduce in the patch
For example, to check for CVE-2022-30525, you could do something like this.
func (sploit ZyxelExploit) CheckVersion(conf *config.Config) exploit.VersionCheckType { url := protocol.GenerateURL(conf.Rhost, conf.Rport, conf.SSL, "/") resp, bodyString, ok := protocol.HTTPSendAndRecv("GET", url, "") if !ok { return exploit.Unknown } if resp.StatusCode != 200 { output.PrintfError("Received an unexpected HTTP status code: %d", resp.StatusCode) return exploit.Unknown } if !strings.Contains(bodyString, "zyFunction.js") { output.PrintError("The HTTP response did not contain an expected JavaScript include") return exploit.Unknown } re := regexp.MustCompile(`src="/ext-js/app/common/zyFunction.js\?v=([0-9]+)"></script>`) res := re.FindAllStringSubmatch(bodyString, -1) if len(res) == 0 { output.PrintError("Could not extract the build date from the target") return exploit.Unknown } output.PrintfStatus("The device has a self-reported firmware publication date of %s", res[0][1]) date64, _ := strconv.ParseInt(res[0][1], 10, 64) if date64 < 220415000000 { return exploit.Vulnerable } return exploit.NotVulnerable }
Regardless, the goal is to avoid throwing the exploit until you are somewhat sure that it should land. This cannot always be accomplished so the return of exploit.NotImplemented is always on offer, and the attacker can skip this step via configuration if they please.
RunExploit ¶
RunExploit should contain the logic for exploiting the target. There is almost no requirement on this function other than the attacker do their thing. The on thing the implementation should do is return false if believe their attack has failed.
type VersionCheckType ¶
type VersionCheckType int
The return type for CheckVersion().
const ( // The target is not vulnerable. NotVulnerable VersionCheckType = 0 // The target is vulnerable. Vulnerable VersionCheckType = 1 // Based on incomplete information, the target might be vulnerable. PossiblyVulnerable VersionCheckType = 2 // Something went wrong during CheckVersion(). Unknown VersionCheckType = 3 // CheckVersion() is not implemented. NotImplemented VersionCheckType = 4 )
Directories ¶
Path | Synopsis |
---|---|
httpservefile
httpservefile c2 spawns an HTTP or HTTPS server and hosts arbitrary user-provided files.
|
httpservefile c2 spawns an HTTP or HTTPS server and hosts arbitrary user-provided files. |
httpserveshell
httpservershell is (literally) a combination of HTTPServeFile and (SSLShell || SimpleShellServer).
|
httpservershell is (literally) a combination of HTTPServeFile and (SSLShell || SimpleShellServer). |
sslshell
sslshell is a simple c2 that listens for incoming ssl/tls connections in order to establish a reverse shell.
|
sslshell is a simple c2 that listens for incoming ssl/tls connections in order to establish a reverse shell. |
SQLite Caching and Cross-Exploit Database
|
SQLite Caching and Cross-Exploit Database |
ldapjndi
This is an implementation of an evil JNDI LDAP server.
|
This is an implementation of an evil JNDI LDAP server. |
Package output handles structured logging for the framework and exploits.
|
Package output handles structured logging for the framework and exploits. |
Payload related functions and actions
|
Payload related functions and actions |
bindshell
Bind shell payloads & listeners.
|
Bind shell payloads & listeners. |
dropper
File dropper download and execute payloads.
|
File dropper download and execute payloads. |
fileplant
file planting based payloads.
|
file planting based payloads. |
reverse
Reverse shell and command payloads.
|
Reverse shell and command payloads. |
ajp
Package ajp is a very basic (and incomplete) implementation of the AJPv13 protocol.
|
Package ajp is a very basic (and incomplete) implementation of the AJPv13 protocol. |
mikrotik
`msg.go` contains the logic for building, reading, accessing, and serializing RouterOS M2 messages.
|
`msg.go` contains the logic for building, reading, accessing, and serializing RouterOS M2 messages. |
rocketmq
Package rocketmq is a very basic (and incomplete) implementation of RocketMQ remoting protocol
|
Package rocketmq is a very basic (and incomplete) implementation of RocketMQ remoting protocol |