From 177803af87f54a57105345dd16fc5aed9c7204fd Mon Sep 17 00:00:00 2001 From: terrorbyte Date: Fri, 8 Nov 2024 13:02:12 -0700 Subject: [PATCH 1/3] Add protocol based flag handling Closes #234 Allows for protocols to have explicit flags that will resolve when they get defined. For example, if your exploit defines "HTTP" as it's protocol, this change automatically applies the "user-agent" flag to the cli args and if it does not it will not appear. I of course wanted to support multi-protocol or sub-protocol situations, so this also adds the `cli.AddProtocolFlags` function that will allow for manually adding flags where applicable. Also adds a few checks for whether to print the Global User-Agent string based on that and a quick Warning check for if proxies are supported. --- cli/commandline.go | 33 +++++++++++++-- cli/protocols.go | 101 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 cli/protocols.go diff --git a/cli/commandline.go b/cli/commandline.go index 32dc1ec..eb093f5 100644 --- a/cli/commandline.go +++ b/cli/commandline.go @@ -8,6 +8,7 @@ import ( "io" "net" "os" + "slices" "strconv" "strings" @@ -271,8 +272,10 @@ func handleRhostsOptions(conf *config.Config, rhosts string, rports string, rhos return parseRhostsFile(conf, rhostsFile) } - // dump the selected user agent to debug - output.PrintfFrameworkDebug("Using the HTTP User-Agent: %s", protocol.GlobalUA) + if conf.Protocol == "HTTP" { + // dump the selected user agent to debug + output.PrintfFrameworkDebug("Using the HTTP User-Agent: %s", protocol.GlobalUA) + } return buildRhosts(conf, rhosts, rports) } @@ -387,8 +390,6 @@ func remoteHostFlags(conf *config.Config, rhosts *string, rhostsFile *string, rp flag.StringVar(rports, "rports", "", "A comma delimited list of the remote target's server ports") // generic all comms connection timeout flag.IntVar(&protocol.GlobalCommTimeout, "timeout", 10, "A default timeout for all socket communication") - // allow the user to use their own HTTP user-agent if they so wish - flag.StringVar(&protocol.GlobalUA, "user-agent", protocol.GlobalUA, "The User-Agent to use in HTTP requests") } // command line flags for defining the local host. @@ -542,6 +543,14 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) + if !slices.Contains(proxySupportedProtocols, conf.Protocol) { + output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") + } + if !protocolFlags(conf.Protocol) { + output.PrintfFrameworkError("internal flag setting for protocols failed") + + return false + } loggingFlags(&logFile, &frameworkLogLevel, &exploitLogLevel) remoteHostFlags(conf, &rhosts, &rhostsFile, &rports) localHostFlags(conf) @@ -607,6 +616,14 @@ func InformationDisclosureCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) + if !slices.Contains(proxySupportedProtocols, conf.Protocol) { + output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") + } + if !protocolFlags(conf.Protocol) { + output.PrintfFrameworkError("internal flag setting for protocols failed") + + return false + } loggingFlags(&logFile, &frameworkLogLevel, &exploitLogLevel) remoteHostFlags(conf, &rhosts, &rhostsFile, &rports) localHostFlags(conf) @@ -649,6 +666,14 @@ func WebShellCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) + if !slices.Contains(proxySupportedProtocols, conf.Protocol) { + output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") + } + if !protocolFlags(conf.Protocol) { + output.PrintfFrameworkError("internal flag setting for protocols failed") + + return false + } loggingFlags(&logFile, &frameworkLogLevel, &exploitLogLevel) remoteHostFlags(conf, &rhosts, &rhostsFile, &rports) localHostFlags(conf) diff --git a/cli/protocols.go b/cli/protocols.go new file mode 100644 index 0000000..0629d16 --- /dev/null +++ b/cli/protocols.go @@ -0,0 +1,101 @@ +package cli + +import ( + "flag" + + "github.com/vulncheck-oss/go-exploit/output" + "github.com/vulncheck-oss/go-exploit/protocol" +) + +// All arguments used by flag packages use this structure. +type flagArgs struct { + Variable any + Default any + Description string +} + +// The internalProtocols datastructure is a map based on protocols that then utilizes the interface +// versions of the flag arguments, which should make it generic enough for any of the flag package +// function types that we utilize. This also implies that the protocol variables that are set are +// utilized elsewhere in go-exploit and not freeform CreateStringFlag style flags. If you want to +// add more protocol flags this is where they go. +var internalProtocols = map[string]map[string]flagArgs{ + "HTTP": { + // allow the user to use their own HTTP user-agent if they so wish + "user-agent": flagArgs{ + Variable: protocol.GlobalUA, + Default: protocol.GlobalUA, + Description: "The User-Agent to use in HTTP requests", + }, + }, +} + +// Which protocols have explicit -proxy support. +var proxySupportedProtocols = []string{"HTTP"} + +// AddProtocolFlags uses the internal supported protocol variables and manually adds the protocol +// flags to the exploit. If your exploit uses multiple protocols and you would like to expose the +// protocol flags, it should be added with a `cli.AddProtocolFlags("HTTP"). +func AddProtocolFlags(protocol string) bool { + _, exists := internalProtocols[protocol] + if !exists { + output.PrintfFrameworkError("Protocol '%s' has no flags specified", protocol) + + return false + } + + return protocolFlags(protocol) +} + +// protocolFlags takes a protocol string and matches it to the internalProtocols map and then +// uses the type assertions to make them match the flag package functions. Be sure to check that +// the internalProtocols types for Variable and Default match the flag function signatures or this +// will bail out before the flag setting silently to basic type errors. +func protocolFlags(protocol string) bool { + flags, exists := internalProtocols[protocol] + if !exists { + // No flags for this protocol enabled, this is not fatal, it just means that no + // flags have set for the protocol + return true + } + for name, args := range flags { + switch v := args.Default.(type) { + case int: + a, ok := args.Variable.(int) + if !ok { + output.PrintFrameworkError("Internal protocol variable was not the expected type (int)") + + return false + } + flag.IntVar(&a, name, v, args.Description) + case uint: + a, ok := args.Variable.(uint) + if !ok { + output.PrintFrameworkError("Internal protocol variable was not the expected type (uint)") + + return false + } + flag.UintVar(&a, name, v, args.Description) + case string: + a, ok := args.Variable.(string) + if !ok { + output.PrintFrameworkError("Internal protocol variable was not the expected type (string)") + + return false + } + flag.StringVar(&a, name, v, args.Description) + case bool: + a, ok := args.Variable.(bool) + if !ok { + output.PrintFrameworkError("Internal protocol variable was not the expected type (bool)") + + return false + } + flag.BoolVar(&a, name, v, args.Description) + default: + // Type not found, how did this happen? + } + } + + return true +} From 72e5423923d791c9f867f8ce0b47dc6e9072251c Mon Sep 17 00:00:00 2001 From: terrorbyte Date: Fri, 8 Nov 2024 13:22:16 -0700 Subject: [PATCH 2/3] Remove incorrect proxy statements. Because @j-baines is smart and cool --- cli/commandline.go | 10 ---------- cli/protocols.go | 3 --- 2 files changed, 13 deletions(-) diff --git a/cli/commandline.go b/cli/commandline.go index eb093f5..0e95a6b 100644 --- a/cli/commandline.go +++ b/cli/commandline.go @@ -8,7 +8,6 @@ import ( "io" "net" "os" - "slices" "strconv" "strings" @@ -543,9 +542,6 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !slices.Contains(proxySupportedProtocols, conf.Protocol) { - output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") - } if !protocolFlags(conf.Protocol) { output.PrintfFrameworkError("internal flag setting for protocols failed") @@ -616,9 +612,6 @@ func InformationDisclosureCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !slices.Contains(proxySupportedProtocols, conf.Protocol) { - output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") - } if !protocolFlags(conf.Protocol) { output.PrintfFrameworkError("internal flag setting for protocols failed") @@ -666,9 +659,6 @@ func WebShellCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !slices.Contains(proxySupportedProtocols, conf.Protocol) { - output.PrintFrameworkWarn("-proxy flag may not work as expected with non-HTTP protocols") - } if !protocolFlags(conf.Protocol) { output.PrintfFrameworkError("internal flag setting for protocols failed") diff --git a/cli/protocols.go b/cli/protocols.go index 0629d16..f78a9c0 100644 --- a/cli/protocols.go +++ b/cli/protocols.go @@ -30,9 +30,6 @@ var internalProtocols = map[string]map[string]flagArgs{ }, } -// Which protocols have explicit -proxy support. -var proxySupportedProtocols = []string{"HTTP"} - // AddProtocolFlags uses the internal supported protocol variables and manually adds the protocol // flags to the exploit. If your exploit uses multiple protocols and you would like to expose the // protocol flags, it should be added with a `cli.AddProtocolFlags("HTTP"). From b995e50fcd7d69990b524e746b09ac4fa696668b Mon Sep 17 00:00:00 2001 From: terrorbyte Date: Wed, 29 Jan 2025 16:22:07 -0700 Subject: [PATCH 3/3] Move protocol based flags to protocols vs cli --- cli/commandline.go | 8 ++++---- cli/protocols.go => protocol/flags.go | 15 +++++++-------- 2 files changed, 11 insertions(+), 12 deletions(-) rename cli/protocols.go => protocol/flags.go (88%) diff --git a/cli/commandline.go b/cli/commandline.go index 0e95a6b..273dba0 100644 --- a/cli/commandline.go +++ b/cli/commandline.go @@ -542,8 +542,8 @@ func CodeExecutionCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !protocolFlags(conf.Protocol) { - output.PrintfFrameworkError("internal flag setting for protocols failed") + if !protocol.CreateProtocolFlags(conf.Protocol) { + output.PrintFrameworkError("internal flag setting for protocols failed") return false } @@ -612,7 +612,7 @@ func InformationDisclosureCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !protocolFlags(conf.Protocol) { + if !protocol.CreateProtocolFlags(conf.Protocol) { output.PrintfFrameworkError("internal flag setting for protocols failed") return false @@ -659,7 +659,7 @@ func WebShellCmdLineParse(conf *config.Config) bool { dbFlags(conf) proxyFlags(&proxy) - if !protocolFlags(conf.Protocol) { + if !protocol.CreateProtocolFlags(conf.Protocol) { output.PrintfFrameworkError("internal flag setting for protocols failed") return false diff --git a/cli/protocols.go b/protocol/flags.go similarity index 88% rename from cli/protocols.go rename to protocol/flags.go index f78a9c0..bb7667f 100644 --- a/cli/protocols.go +++ b/protocol/flags.go @@ -1,10 +1,9 @@ -package cli +package protocol import ( "flag" "github.com/vulncheck-oss/go-exploit/output" - "github.com/vulncheck-oss/go-exploit/protocol" ) // All arguments used by flag packages use this structure. @@ -23,8 +22,8 @@ var internalProtocols = map[string]map[string]flagArgs{ "HTTP": { // allow the user to use their own HTTP user-agent if they so wish "user-agent": flagArgs{ - Variable: protocol.GlobalUA, - Default: protocol.GlobalUA, + Variable: GlobalUA, + Default: GlobalUA, Description: "The User-Agent to use in HTTP requests", }, }, @@ -32,7 +31,7 @@ var internalProtocols = map[string]map[string]flagArgs{ // AddProtocolFlags uses the internal supported protocol variables and manually adds the protocol // flags to the exploit. If your exploit uses multiple protocols and you would like to expose the -// protocol flags, it should be added with a `cli.AddProtocolFlags("HTTP"). +// protocol flags, it should be added with a `protocol.AddProtocolFlags("HTTP"). func AddProtocolFlags(protocol string) bool { _, exists := internalProtocols[protocol] if !exists { @@ -41,14 +40,14 @@ func AddProtocolFlags(protocol string) bool { return false } - return protocolFlags(protocol) + return CreateProtocolFlags(protocol) } -// protocolFlags takes a protocol string and matches it to the internalProtocols map and then +// CreateProtocolFlags takes a protocol string and matches it to the internalProtocols map and then // uses the type assertions to make them match the flag package functions. Be sure to check that // the internalProtocols types for Variable and Default match the flag function signatures or this // will bail out before the flag setting silently to basic type errors. -func protocolFlags(protocol string) bool { +func CreateProtocolFlags(protocol string) bool { flags, exists := internalProtocols[protocol] if !exists { // No flags for this protocol enabled, this is not fatal, it just means that no