diff --git a/cmd/bruter/concurrency.go b/cmd/bruter/concurrency.go new file mode 100644 index 0000000..ae30b9d --- /dev/null +++ b/cmd/bruter/concurrency.go @@ -0,0 +1,19 @@ +package main + +import ( + "sync" +) + +func RunConcurrently(tasks ...func()) { + var wg sync.WaitGroup + wg.Add(len(tasks)) + + for _, task := range tasks { + go func(t func()) { + defer wg.Done() + t() + }(task) + } + + wg.Wait() +} diff --git a/cmd/bruter/main.go b/cmd/bruter/main.go index 25f9639..6acc2e7 100644 --- a/cmd/bruter/main.go +++ b/cmd/bruter/main.go @@ -71,7 +71,6 @@ func main() { app.UseCache = false app.Domain = *Domain app.ShodanAPIKey = *Apikey - repo := handlers.NewRepo(&app) handlers.NewHandlers(repo) render.NewTemplates(&app) diff --git a/cmd/bruter/routes.go b/cmd/bruter/routes.go index 7808f68..f500dd8 100644 --- a/cmd/bruter/routes.go +++ b/cmd/bruter/routes.go @@ -11,6 +11,7 @@ import ( "github.com/CyberRoute/bruter/pkg/ssl" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" + "html/template" "net/http" ) @@ -34,28 +35,68 @@ func routes(app *config.AppConfig) http.Handler { TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client := &http.Client{Transport: customTransport} - shodan := shodan.NewClient(client, ipv4, app.ShodanAPIKey) - hostinfo, err := shodan.HostInfo(app) - checkError(err) - headers, err := shodan.Head("http://" + app.Domain) - checkError(err) - mx_records, err := network.FindMX(app.Domain) - checkError(err) - mysql, err := grabber.GrabMysqlBanner(app.Domain, hostinfo.Ports) - checkError(err) - ssh, err := grabber.GrabSSHBanner(app.Domain, hostinfo.Ports) - checkError(err) - ftp, err := grabber.GrabFTPBanner(app.Domain, hostinfo.Ports) - checkError(err) + sh := shodan.NewClient(client, ipv4, app.ShodanAPIKey) - smtp, err := grabber.GrabSMTPBanner(app.Domain, hostinfo.Ports) - checkError(err) - pop, err := grabber.GrabPOPBanner(app.Domain, hostinfo.Ports) - checkError(err) - irc, err := grabber.GrabIRCBanner(app.Domain, hostinfo.Ports) - checkError(err) - sslinfo, err := ssl.FetchCrtData(app.Domain) - checkError(err) + var ( + hostinfo shodan.Response + headers map[string]interface{} + mx_records map[string]uint16 + whoisinfo template.HTML + mysql string + ssh string + ftp string + smtp string + pop string + irc string + sslinfo []map[string]interface{} + ) + + RunConcurrently( + func() { + hostinfo, err = sh.HostInfo(app) + checkError(err) + }, + func() { + headers, err = sh.Head("https://" + app.Domain) + checkError(err) + }, + func() { + mx_records, err = network.FindMX(app.Domain) + checkError(err) + }, + func() { + whoisinfo, err = network.WhoisLookup(app.Domain) + checkError(err) + }, + func() { + mysql, err = grabber.GrabMysqlBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + ssh, err = grabber.GrabSSHBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + ftp, err = grabber.GrabFTPBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + smtp, err = grabber.GrabSMTPBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + pop, err = grabber.GrabPOPBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + irc, err = grabber.GrabIRCBanner(app.Domain, hostinfo.Ports) + checkError(err) + }, + func() { + sslinfo, err = ssl.FetchCrtData(app.Domain) + checkError(err) + }, + ) homeargs := models.HomeArgs{ Ipv4: ipv4, Ipv6: ipv6, @@ -69,11 +110,18 @@ func routes(app *config.AppConfig) http.Handler { Pop: pop, Irc: irc, } + sslargs := models.HomeArgs{ SSLInfo: sslinfo, } + + whoisargs := models.HomeArgs{ + WhoisInfo: whoisinfo, + } + mux.Get("/", handlers.Repo.Home(homeargs)) mux.Get("/ssl", handlers.Repo.SSLInfo(sslargs)) + mux.Get("/whois", handlers.Repo.WhoisInfo(whoisargs)) mux.Get("/consumer", handlers.Repo.Consumer) fileServer := http.FileServer(http.Dir("./static/")) mux.Handle("/static/*", http.StripPrefix("/static", fileServer)) diff --git a/go.mod b/go.mod index e1e4770..15979d5 100644 --- a/go.mod +++ b/go.mod @@ -6,15 +6,13 @@ require ( github.com/alexedwards/scs/v2 v2.5.1 github.com/evilsocket/islazy v1.11.0 github.com/go-chi/chi/v5 v5.0.8 + github.com/likexian/whois v1.15.1 github.com/rs/zerolog v1.29.0 - github.com/stretchr/testify v1.8.4 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - golang.org/x/sys v0.6.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + golang.org/x/net v0.14.0 // indirect + golang.org/x/sys v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index f489570..54cec30 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,14 @@ github.com/alexedwards/scs/v2 v2.5.1 h1:EhAz3Kb3OSQzD8T+Ub23fKsiuvE0GzbF5Lgn0uTwM3Y= github.com/alexedwards/scs/v2 v2.5.1/go.mod h1:ToaROZxyKukJKT/xLcVQAChi5k6+Pn1Gvmdl7h3RRj8= github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -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/evilsocket/islazy v1.11.0 h1:B5w6uuS6ki6iDG+aH/RFeoMb8ijQh/pGabewqp2UeJ0= github.com/evilsocket/islazy v1.11.0/go.mod h1:muYH4x5MB5YRdkxnrOtrXLIBX6LySj1uFIqys94LKdo= github.com/go-chi/chi/v5 v5.0.8 h1:lD+NLqFcAi1ovnVZpsnObHGW4xb4J8lNmoYVfECH1Y0= github.com/go-chi/chi/v5 v5.0.8/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/likexian/gokit v0.25.13 h1:p2Uw3+6fGG53CwdU2Dz0T6bOycdb2+bAFAa3ymwWVkM= +github.com/likexian/whois v1.15.1 h1:6vTMI8n9s1eJdmcO4R9h1x99aQWIZZX1CD3am68gApU= +github.com/likexian/whois v1.15.1/go.mod h1:/nxmQ6YXvLz+qTxC/QFtEJNAt0zLuRxJrKiWpBJX8X0= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= @@ -16,19 +17,13 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 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/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.29.0 h1:Zes4hju04hjbvkVkOhdl2HpZa+0PmVwigmo8XoORE5w= github.com/rs/zerolog v1.29.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= +golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/handlers/handlers.go b/pkg/handlers/handlers.go index c1171f8..bb09fd4 100644 --- a/pkg/handlers/handlers.go +++ b/pkg/handlers/handlers.go @@ -3,15 +3,15 @@ package handlers import ( "encoding/json" "fmt" - "io" - "net/http" - "os" - "strings" - "github.com/CyberRoute/bruter/pkg/config" "github.com/CyberRoute/bruter/pkg/models" + "github.com/CyberRoute/bruter/pkg/network" "github.com/CyberRoute/bruter/pkg/render" "github.com/CyberRoute/bruter/pkg/ssl" + "io" + "net/http" + "os" + "strings" ) // Repo used by the handlers @@ -68,11 +68,21 @@ func (m *Repository) Home(args models.HomeArgs) http.HandlerFunc { func (m *Repository) SSLInfo(args models.HomeArgs) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - sslinfo, err := ssl.FetchCrtData(m.App.Domain) + var templateData models.TemplateData + sslInfo, err := ssl.FetchCrtData(m.App.Domain) m.checkError(err) - render.RenderTemplate(w, "ssl.page.html", &models.TemplateData{ - SSLInfo: sslinfo, - }) + templateData.SSLInfo = sslInfo + render.RenderTemplate(w, "ssl.page.html", &templateData) + } +} + +func (m *Repository) WhoisInfo(args models.HomeArgs) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var templateData models.TemplateData + whoisInfo, err := network.WhoisLookup(m.App.Domain) + m.checkError(err) + templateData.WhoisInfo = whoisInfo + render.RenderTemplate(w, "whois.page.html", &templateData) } } diff --git a/pkg/models/home.go b/pkg/models/home.go index d5a0aab..d984722 100644 --- a/pkg/models/home.go +++ b/pkg/models/home.go @@ -1,20 +1,23 @@ package models import ( + "html/template" + "github.com/CyberRoute/bruter/pkg/shodan" ) type HomeArgs struct { - Ipv4 string - Ipv6 string - Host shodan.Response - Headers map[string]interface{} - Mx map[string]uint16 - SSLInfo []map[string]interface{} - Ftp string - Ssh string - Mysql string - Smtp string - Pop string - Irc string + Ipv4 string + Ipv6 string + Host shodan.Response + Headers map[string]interface{} + Mx map[string]uint16 + SSLInfo []map[string]interface{} + WhoisInfo template.HTML + Ftp string + Ssh string + Mysql string + Smtp string + Pop string + Irc string } diff --git a/pkg/models/templatedata.go b/pkg/models/templatedata.go index 6108f40..95dd350 100644 --- a/pkg/models/templatedata.go +++ b/pkg/models/templatedata.go @@ -1,5 +1,9 @@ package models +import ( + "html/template" +) + // Template data holds data sent from handlers to templates type TemplateData struct { StringMap map[string]string @@ -9,6 +13,7 @@ type TemplateData struct { HeadersMap map[string]interface{} FtpBannerGrabberMap map[string]interface{} SSLInfo []map[string]interface{} + WhoisInfo template.HTML CSRFToken string Flash string Warning string diff --git a/pkg/network/net-tools.go b/pkg/network/net-tools.go index e26c7cb..0bb668f 100644 --- a/pkg/network/net-tools.go +++ b/pkg/network/net-tools.go @@ -2,7 +2,10 @@ package network import ( "fmt" + "github.com/likexian/whois" + "html/template" "net" + "strings" ) func ResolveByName(domain string) (string, error) { @@ -35,3 +38,19 @@ func FindMX(domain string) (map[string]uint16, error) { } return mx_records, nil } + +func WhoisLookup(domain string) (template.HTML, error) { + result, err := whois.Whois(domain) + if err != nil { + return "", fmt.Errorf("failed to perform WHOIS lookup: %v", err) + } + lines := strings.Split(result, "\n") + for i, line := range lines { + parts := strings.SplitN(line, ":", 2) + if len(parts) == 2 { + lines[i] = parts[0] + ":" + parts[1] + } + } + result = strings.Join(lines, "
") + return template.HTML(result), nil +} diff --git a/templates/base.layout.html b/templates/base.layout.html index 0c566e9..3d8cce1 100644 --- a/templates/base.layout.html +++ b/templates/base.layout.html @@ -35,7 +35,10 @@ diff --git a/templates/whois.page.html b/templates/whois.page.html new file mode 100644 index 0000000..3347e8a --- /dev/null +++ b/templates/whois.page.html @@ -0,0 +1,20 @@ +{{template "base" .}} + +{{define "content"}} +
+
+
+
+
+
+
WHOIS Information
+
+
+

{{.WhoisInfo}}

+
+
+
+
+
+
+{{end}}