Skip to content

Commit

Permalink
dontgo403 refactorization + raw-request function added
Browse files Browse the repository at this point in the history
  • Loading branch information
devploit committed Mar 21, 2023

Verified

This commit was signed with the committer’s verified signature.
luehm Alex Luehm
1 parent 9b6f590 commit 7734013
Showing 6 changed files with 156 additions and 49 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -12,5 +12,8 @@
# Built Visual Studio Code Extensions
*.vsix

# Test requests files
request.txt

# Built binary
dontgo403
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -29,16 +29,18 @@ Usage:
dontgo403 [flags]

Flags:
-b, --bypassIp string Try bypass tests with a specific IP address (or hostname). i.e.: 'X-Forwarded-For: 192.168.0.1' instead of 'X-Forwarded-For: 127.0.0.1'
-d, --delay int Set a delay (in ms) between each request. Default: 0ms
-f, --folder string Define payloads folder (if it's not in the same path as binary)
-H, --header strings Add a custom header to the requests (can be specified multiple times)
-h, --help help for dontgo403
-t, --httpMethod string HTTP method to use (default 'GET')
-m, --max_goroutines int Set the max number of goroutines working at same time. Default: 50 (default 50)
-p, --proxy string Proxy URL. For example: http://127.0.0.1:8080
-u, --uri string Target URL
-a, --useragent string Set the User-Agent string (default 'dontgo403')
-b, --bypassIp string Try bypass tests with a specific IP address (or hostname). i.e.: 'X-Forwarded-For: 192.168.0.1' instead of 'X-Forwarded-For: 127.0.0.1'
-d, --delay int Set a delay (in ms) between each request. Default: 0ms
-f, --folder string Define payloads folder (if it's not in the same path as binary)
-H, --header strings Add a custom header to the requests (can be specified multiple times)
-h, --help help for dontgo403
--http Set HTTP schema for request-file requests (default HTTPS)
-t, --httpMethod string HTTP method to use (default 'GET')
-m, --max_goroutines int Set the max number of goroutines working at same time. Default: 50 (default 50)
-p, --proxy string Proxy URL. For example: http://127.0.0.1:8080
-r, --request-file string Path to request file to load flags from
-u, --uri string Target URL
-a, --useragent string Set the User-Agent string (default 'dontgo403')
```
121 changes: 97 additions & 24 deletions cmd/api.go
Original file line number Diff line number Diff line change
@@ -3,67 +3,77 @@ package cmd
import (
"bufio"
"crypto/tls"
"io/ioutil"
"log"
"net"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strings"
"time"
)

// Reads a file given its filename and returns a list containing each of its lines.
func parseFile(filename string) (lines []string, err error) {

// parseFile reads a file given its filename and returns a list containing each of its lines.
func parseFile(filename string) ([]string, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
}
defer file.Close()

lines := []string{}
scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)

for scanner.Scan() {
lines = append(lines, scanner.Text())
}

err = file.Close()
if err != nil {
if err := scanner.Err(); err != nil {
return nil, err
}

return lines, nil
}

// header represents an HTTP header.
type header struct {
key string
value string
}

// Makes a GET request using headers `headers` proxy `proxy`.
// request makes an HTTP request using headers `headers` and proxy `proxy`.
//
// Uses a custom method if specified.
func request(method, uri string, headers []header, proxy *url.URL) (statusCode int, response []byte, err error) {

if method == "" { // check if it is nil
// If `method` is empty, it defaults to "GET".
func request(method, uri string, headers []header, proxy *url.URL) (int, []byte, error) {
if method == "" {
method = "GET"
}

var _proxy *url.URL
if len(proxy.Host) != 0 {
_proxy = proxy
} else {
_proxy = nil
if len(proxy.Host) == 0 {
proxy = nil
}

client := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(_proxy),
TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, DialContext: (&net.Dialer{Timeout: 6 * time.Second}).DialContext}}
client := &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxy),
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
},
DialContext: (&net.Dialer{
Timeout: 6 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
},
}

req, err := http.NewRequest(method, uri, nil)
if err != nil {
return 0, nil, err
} else {
req.Close = true
}
req.Close = true

for _, header := range headers {
req.Header.Add(header.key, header.value)
@@ -73,14 +83,77 @@ func request(method, uri string, headers []header, proxy *url.URL) (statusCode i
if err != nil {
return 0, nil, err
}
defer res.Body.Close()

resp, err := httputil.DumpResponse(res, true)
if err != nil {
return 0, nil, err
}

res.Body.Close()

return res.StatusCode, resp, nil
}

// makeRequests reads the lines from the file at `filename` and makes HTTP requests to each URL using the given headers and proxy.
func makeRequests(filename string, headers []header, proxy *url.URL) error {
lines, err := parseFile(filename)
if err != nil {
return err
}

responses := make(chan []byte, len(lines))

// Start worker routines to make requests concurrently
for _, line := range lines {
go func(line string) {
statusCode, resp, err := request("", line, headers, proxy)
if err != nil {
log.Printf("Error making request to %s: %s", line, err)
} else {
log.Printf("%s returned status code %d", line, statusCode)
responses <- resp
}
}(line)
}

// Wait for all responses to be received
for i := 0; i < len(lines); i++ {
resp := <-responses
log.Printf("Received response: %s", resp)
}

return nil
}

func loadFlagsFromRequestFile(requestFile string, schema bool) {
// Read the content of the request file
content, err := ioutil.ReadFile(requestFile)
if err != nil {
log.Fatalf("Error reading request file: %v", err)
}
http_schema := "https://"

if schema != false {
http_schema = "http://"
}

// Split the request into lines
requestLines := strings.Split(string(content), "\n")
firstLine := requestLines[0]
headers := requestLines[1:]
host := strings.Split(requestLines[1], " ")

// Extract the HTTP method and URL from the first line of the request
parts := strings.Split(firstLine, " ")
uri := http_schema + host[1] + parts[1]

// Extract headers from the request and assign them to the req_headers slice
req_headers := []string{}
for _, h := range headers {
if len(h) > 0 {
req_headers = append(req_headers, h)
}
}

// Assign the extracted values to the corresponding flag variables
requester(uri, proxy, useragent, req_headers, bypassIp, folder, httpMethod)
}
40 changes: 30 additions & 10 deletions cmd/requester.go
Original file line number Diff line number Diff line change
@@ -6,6 +6,7 @@ import (
"strconv"
"strings"
"time"
"unicode"

"github.com/cheynewallace/tabby"
"github.com/fatih/color"
@@ -18,6 +19,7 @@ type Result struct {
contentLength int
}

// printResponse prints the results of HTTP requests in a tabular format with colored output based on the status codes.
func printResponse(results []Result) {
t := tabby.New()

@@ -36,16 +38,16 @@ func printResponse(results []Result) {
t.AddLine(code, color.BlueString(strconv.Itoa(result.contentLength)+" bytes"), result.line)
}
t.Print()

}

// requestMethods makes HTTP requests using a list of methods from a file and prints the results.
func requestMethods(uri string, headers []header, proxy *url.URL, folder string) {
color.Cyan("\n[####] HTTP METHODS [####]")

var lines []string
lines, err := parseFile(folder + "/httpmethods")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading /httpmethods file: %v", err)
}

w := goccm.New(max_goroutines)
@@ -69,13 +71,14 @@ func requestMethods(uri string, headers []header, proxy *url.URL, folder string)
printResponse(results)
}

// requestHeaders makes HTTP requests using a list of headers from a file and prints the results. It can also bypass IP address restrictions by specifying a bypass IP address.
func requestHeaders(uri string, headers []header, proxy *url.URL, bypassIp string, folder string, method string) {
color.Cyan("\n[####] VERB TAMPERING [####]")

var lines []string
lines, err := parseFile(folder + "/headers")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading /headers file: %v", err)
}

var ips []string
@@ -84,13 +87,13 @@ func requestHeaders(uri string, headers []header, proxy *url.URL, bypassIp strin
} else {
ips, err = parseFile(folder + "/ips")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading /ips file: %v", err)
}
}

simpleheaders, err := parseFile(folder + "/simpleheaders")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading /simpleheaders file: %v", err)
}

w := goccm.New(max_goroutines)
@@ -136,13 +139,14 @@ func requestHeaders(uri string, headers []header, proxy *url.URL, bypassIp strin
printResponse(results)
}

// requestEndPaths makes HTTP requests using a list of custom end paths from a file and prints the results.
func requestEndPaths(uri string, headers []header, proxy *url.URL, folder string, method string) {
color.Cyan("\n[####] CUSTOM PATHS [####]")

var lines []string
lines, err := parseFile(folder + "/endpaths")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading custom paths file: %v", err)
}

w := goccm.New(max_goroutines)
@@ -166,11 +170,12 @@ func requestEndPaths(uri string, headers []header, proxy *url.URL, folder string
printResponse(results)
}

// requestMidPaths makes HTTP requests using a list of custom mid paths from a file and prints the results.
func requestMidPaths(uri string, headers []header, proxy *url.URL, folder string, method string) {
var lines []string
lines, err := parseFile(folder + "/midpaths")
if err != nil {
log.Fatal(err)
log.Fatalf("Error reading custom paths file: %v", err)
}

x := strings.Split(uri, "/")
@@ -213,6 +218,7 @@ func requestMidPaths(uri string, headers []header, proxy *url.URL, folder string
printResponse(results)
}

// requestCapital makes HTTP requests by capitalizing each letter in the last part of the URI and prints the results.
func requestCapital(uri string, headers []header, proxy *url.URL, method string) {
color.Cyan("\n[####] CAPITALIZATION [####]")

@@ -234,8 +240,14 @@ func requestCapital(uri string, headers []header, proxy *url.URL, method string)
for _, z := range uripath {
time.Sleep(time.Duration(delay) * time.Millisecond)
w.Wait()
go func(z string) {
newpath := strings.ReplaceAll(uripath, string(z), strings.ToUpper(string(z)))
go func(z rune) {
newpath := strings.Map(func(r rune) rune {
if r == z {
return unicode.ToUpper(r)
} else {
return r
}
}, uripath)

var fullpath string
if uri[len(uri)-1:] == "/" {
@@ -251,27 +263,33 @@ func requestCapital(uri string, headers []header, proxy *url.URL, method string)

results = append(results, Result{fullpath, statusCode, len(response)})
w.Done()
}(string(z))
}(z)
}
w.WaitAllDone()
printResponse(results)
}

// requester is the main function that runs all the tests.
func requester(uri string, proxy string, userAgent string, req_headers []string, bypassIp string, folder string, method string) {
// Set up proxy if provided.
if len(proxy) != 0 {
if !strings.Contains(proxy, "http") {
proxy = "http://" + proxy
}
color.Magenta("\n[*] USING PROXY: %s\n", proxy)
}
userProxy, _ := url.Parse(proxy)

// Check if URI has trailing slash, if not add it.
x := strings.Split(uri, "/")
if len(x) < 4 {
uri += "/"
}
// Set User-Agent header.
if len(userAgent) == 0 {
userAgent = "dontgo403"
}
// Set default request method to GET.
if len(method) == 0 {
method = "GET"
}
@@ -280,13 +298,15 @@ func requester(uri string, proxy string, userAgent string, req_headers []string,
{"User-Agent", userAgent},
}

// Parse custom headers from CLI arguments and add them to the headers slice.
if len(req_headers[0]) != 0 {
for _, _header := range req_headers {
header_split := strings.Split(_header, ":")
headers = append(headers, header{header_split[0], header_split[1]})
}
}

// Call each function that will send HTTP requests with different variations of headers and URLs.
requestMethods(uri, headers, userProxy, folder)
requestHeaders(uri, headers, userProxy, bypassIp, folder, method)
requestEndPaths(uri, headers, userProxy, folder, method)
Loading

0 comments on commit 7734013

Please sign in to comment.