From 331eba1e559640600ab0e3e349f7e48b1969cffa Mon Sep 17 00:00:00 2001 From: Jaikishan Tulswani <30144126+jaikishantulswani@users.noreply.github.com> Date: Sat, 27 Jul 2024 09:21:01 +0530 Subject: [PATCH 1/4] Update root.go added flags for status code and unique flags --- cmd/root.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index 27d725b..22b7092 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -31,9 +31,11 @@ var ( uri string userAgent string verbose bool + statusCodes []string // New flag for filtering status codes + uniqueOutput bool // New flag for unique output ) -// rootCmd +// rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "nomore403", Short: "Tool to bypass 40X response codes.", @@ -99,8 +101,12 @@ func init() { rootCmd.PersistentFlags().StringSliceVarP(&technique, "technique", "k", []string{"verbs", "verbs-case", "headers", "endpaths", "midpaths", "http-versions", "path-case"}, "Specify one or more attack techniques to use (e.g., headers,path-case).") rootCmd.PersistentFlags().IntVarP(&timeout, "timeout", "", 6000, "Specify a max timeout time in ms.") rootCmd.PersistentFlags().StringVarP(&uri, "uri", "u", "", "Specify the target URL for the request.") - rootCmd.PersistentFlags().StringVarP(&userAgent, "user-agent", "a", "", "pecify a custom User-Agent string for requests (default: 'nomore403').") + rootCmd.PersistentFlags().StringVarP(&userAgent, "user-agent", "a", "", "Specify a custom User-Agent string for requests (default: 'nomore403').") rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Enable verbose output for detailed request/response logging.") + + // New flags + rootCmd.PersistentFlags().StringSliceVarP(&statusCodes, "status", "", []string{}, "Filter output by comma-separated status codes (e.g., 200,301,403)") + rootCmd.PersistentFlags().BoolVarP(&uniqueOutput, "unique", "", false, "Show unique output based on status code and response length") } // initConfig reads in config file and ENV variables if set. @@ -125,7 +131,7 @@ func initConfig() { if err := viper.ReadInConfig(); err == nil { _, err := fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) if err != nil { - log.Fatalf("{#err}") + log.Fatalf("Error writing to stderr: %v", err) } } } From a355d34f75adf3cb691da5343389e72eb3e5a39f Mon Sep 17 00:00:00 2001 From: Jaikishan Tulswani <30144126+jaikishantulswani@users.noreply.github.com> Date: Sat, 27 Jul 2024 09:21:46 +0530 Subject: [PATCH 2/4] Update requester.go changes in requester functionality --- cmd/requester.go | 157 ++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 63 deletions(-) diff --git a/cmd/requester.go b/cmd/requester.go index ecb1cd8..dc84848 100644 --- a/cmd/requester.go +++ b/cmd/requester.go @@ -1,30 +1,31 @@ package cmd import ( - "bufio" - "fmt" - "log" - "math/rand" - "net/url" - "os" - "os/exec" - "strconv" - "strings" - "sync" - "time" - "unicode" - - "github.com/fatih/color" - "github.com/zenthangplus/goccm" + "bufio" + "fmt" + "log" + "math/rand" + "net/url" + "os" + "os/exec" + "strconv" + "strings" + "sync" + "time" + "unicode" + + "github.com/fatih/color" + "github.com/zenthangplus/goccm" ) type Result struct { - line string - statusCode int - contentLength int - defaultReq bool + line string + statusCode int + contentLength int + defaultReq bool } + type RequestOptions struct { uri string headers []header @@ -46,34 +47,60 @@ var _verbose bool var defaultSc int var defaultCl int var printMutex = &sync.Mutex{} +var uniqueResults = make(map[string]bool) +// printResponse prints the results of HTTP requests in a tabular format with colored output based on the status codes. // printResponse prints the results of HTTP requests in a tabular format with colored output based on the status codes. func printResponse(result Result) { - printMutex.Lock() - defer printMutex.Unlock() - - resultContentLength := strconv.Itoa(result.contentLength) + " bytes" - - var code string - switch result.statusCode { - case 200, 201, 202, 203, 204, 205, 206: - code = color.GreenString(strconv.Itoa(result.statusCode)) - case 300, 301, 302, 303, 304, 307, 308: - code = color.YellowString(strconv.Itoa(result.statusCode)) - case 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 429: - code = color.RedString(strconv.Itoa(result.statusCode)) - case 500, 501, 502, 503, 504, 505, 511: - code = color.MagentaString(strconv.Itoa(result.statusCode)) - } - if !_verbose { - if ((defaultSc == result.statusCode) && (defaultCl == result.contentLength) || result.contentLength == 0 || result.statusCode == 404 || result.statusCode == 400) && !result.defaultReq { - return - } else { - fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line) - } - } else { - fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line) - } + printMutex.Lock() + defer printMutex.Unlock() + + // Check if status code filtering is enabled + if len(statusCodes) > 0 { + statusMatch := false + for _, code := range statusCodes { + if strconv.Itoa(result.statusCode) == code { + statusMatch = true + break + } + } + if !statusMatch { + return + } + } + + // Check for unique output if enabled + if uniqueOutput { + key := fmt.Sprintf("%d-%d", result.statusCode, result.contentLength) + if uniqueResults[key] { + return + } + uniqueResults[key] = true + } + + resultContentLength := strconv.Itoa(result.contentLength) + " bytes" + + var code string + switch result.statusCode { + case 200, 201, 202, 203, 204, 205, 206: + code = color.GreenString(strconv.Itoa(result.statusCode)) + case 300, 301, 302, 303, 304, 307, 308: + code = color.YellowString(strconv.Itoa(result.statusCode)) + case 400, 401, 402, 403, 404, 405, 406, 407, 408, 413, 429: + code = color.RedString(strconv.Itoa(result.statusCode)) + case 500, 501, 502, 503, 504, 505, 511: + code = color.MagentaString(strconv.Itoa(result.statusCode)) + } + + if !_verbose { + if ((defaultSc == result.statusCode) && (defaultCl == result.contentLength) || result.contentLength == 0 || result.statusCode == 404 || result.statusCode == 400) && !result.defaultReq { + return + } else { + fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line) + } + } else { + fmt.Printf("%s \t%20s %s\n", code, color.BlueString(resultContentLength), result.line) + } } func showInfo(options RequestOptions) { @@ -541,6 +568,7 @@ func randomLine(filePath string) (string, error) { // requester is the main function that runs all the tests. func requester(uri string, proxy string, userAgent string, reqHeaders []string, bypassIP string, folder string, method string, verbose bool, techniques []string, banner bool, rateLimit bool, timeout int, redirect bool, randomAgent bool) { + // Set up proxy if provided. if len(proxy) != 0 { if !strings.Contains(proxy, "http") { @@ -589,25 +617,28 @@ func requester(uri string, proxy string, userAgent string, reqHeaders []string, _verbose = verbose - options := RequestOptions{ - uri: uri, - headers: headers, - method: method, - proxy: userProxy, - userAgent: userAgent, - redirect: redirect, - folder: folder, - bypassIP: bypassIP, - timeout: timeout, - rateLimit: rateLimit, - verbose: verbose, - techniques: techniques, - reqHeaders: reqHeaders, - banner: banner, - } - - // Call each function that will send HTTP requests with different variations of headers and URLs. - showInfo(options) + options := RequestOptions{ + uri: uri, + headers: headers, + method: method, + proxy: userProxy, + userAgent: userAgent, + redirect: redirect, + folder: folder, + bypassIP: bypassIP, + timeout: timeout, + rateLimit: rateLimit, + verbose: verbose, + techniques: techniques, + reqHeaders: reqHeaders, + banner: banner, + } + + // Reset uniqueResults map before starting new requests + uniqueResults = make(map[string]bool) + + // Call each function that will send HTTP requests with different variations of headers and URLs. + showInfo(options) for _, tech := range techniques { switch tech { From 7f3c722f631d60273b311cc432982a9a8a393209 Mon Sep 17 00:00:00 2001 From: Jaikishan Tulswani <30144126+jaikishantulswani@users.noreply.github.com> Date: Sat, 27 Jul 2024 09:22:56 +0530 Subject: [PATCH 3/4] Update README.md --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42e417f..afe222e 100644 --- a/README.md +++ b/README.md @@ -108,7 +108,7 @@ Verbose: false ./nomore403 -u https://domain.com/admin -m 10 -d 200 ``` -## Options +## Options Modded ```bash ./nomore403 -h @@ -134,6 +134,8 @@ Flags: --request-file string Load request configuration and flags from a specified file. -k, --technique strings Specify one or more attack techniques to use (e.g., headers,path-case). (default [verbs,verbs-case,headers,endpaths,midpaths,http-versions,path-case]) --timeout int Specify a max timeout time in ms (default 6000) + ## --status strings Filter output by comma-separated status codes (e.g., 200,301,403) + ## --unique Show unique output based on status code and response length -u, --uri string Specify the target URL for the request. -a, --user-agent string pecify a custom User-Agent string for requests (default: 'nomore403'). -v, --verbose Enable verbose output for detailed request/response logging. From 1003bcd45ea6ecd80558d353f2c757c59cd34015 Mon Sep 17 00:00:00 2001 From: Jaikishan Tulswani <30144126+jaikishantulswani@users.noreply.github.com> Date: Sat, 27 Jul 2024 09:23:32 +0530 Subject: [PATCH 4/4] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index afe222e..d88f2e1 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,8 @@ Flags: --request-file string Load request configuration and flags from a specified file. -k, --technique strings Specify one or more attack techniques to use (e.g., headers,path-case). (default [verbs,verbs-case,headers,endpaths,midpaths,http-versions,path-case]) --timeout int Specify a max timeout time in ms (default 6000) - ## --status strings Filter output by comma-separated status codes (e.g., 200,301,403) - ## --unique Show unique output based on status code and response length + --status strings Filter output by comma-separated status codes (e.g., 200,301,403) + --unique Show unique output based on status code and response length -u, --uri string Specify the target URL for the request. -a, --user-agent string pecify a custom User-Agent string for requests (default: 'nomore403'). -v, --verbose Enable verbose output for detailed request/response logging.