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 @@
{{.WhoisInfo}}
+