Integrate Disgo for user interface (#193)
This commit is contained in:
committed by
GitHub
parent
ceb210f281
commit
b6ebd468c6
+40
-42
@@ -7,12 +7,14 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/fatih/color"
|
|
||||||
"github.com/gernest/wow"
|
"github.com/gernest/wow"
|
||||||
"github.com/gernest/wow/spin"
|
"github.com/gernest/wow/spin"
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
cmrdr "github.com/ullaakut/cameradar"
|
cmrdr "github.com/ullaakut/cameradar"
|
||||||
|
"github.com/ullaakut/disgo/logger"
|
||||||
|
log "github.com/ullaakut/disgo/logger"
|
||||||
|
"github.com/ullaakut/disgo/symbol"
|
||||||
curl "github.com/ullaakut/go-curl"
|
curl "github.com/ullaakut/go-curl"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -66,10 +68,14 @@ func parseArguments() error {
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var options options
|
var options options
|
||||||
|
logger, err := log.New(os.Stdout, log.WithErrorOutput(os.Stderr))
|
||||||
err := parseArguments()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErr(err)
|
fmt.Fprintf(os.Stderr, "Unable to create logger: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = parseArguments()
|
||||||
|
if err != nil {
|
||||||
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
options.Credentials = viper.GetString("custom-credentials")
|
options.Credentials = viper.GetString("custom-credentials")
|
||||||
@@ -85,14 +91,14 @@ func main() {
|
|||||||
if len(options.Targets) == 1 {
|
if len(options.Targets) == 1 {
|
||||||
options.Targets, err = cmrdr.ParseTargetsFile(options.Targets[0])
|
options.Targets, err = cmrdr.ParseTargetsFile(options.Targets[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
err = curl.GlobalInit(curl.GLOBAL_ALL)
|
err = curl.GlobalInit(curl.GLOBAL_ALL)
|
||||||
handle := curl.EasyInit()
|
handle := curl.EasyInit()
|
||||||
if err != nil || handle == nil {
|
if err != nil || handle == nil {
|
||||||
printErr(errors.New("libcurl initialization failed"))
|
printErr(logger, errors.New("libcurl initialization failed"))
|
||||||
}
|
}
|
||||||
|
|
||||||
c := &cmrdr.Curl{CURL: handle}
|
c := &cmrdr.Curl{CURL: handle}
|
||||||
@@ -105,33 +111,33 @@ func main() {
|
|||||||
|
|
||||||
credentials, err := cmrdr.LoadCredentials(options.Credentials)
|
credentials, err := cmrdr.LoadCredentials(options.Credentials)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
color.Red("Invalid credentials dictionary: %s", err.Error())
|
printErr(logger, fmt.Errorf("Invalid credentials dictionary %q: %v", options.Credentials, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err := cmrdr.LoadRoutes(options.Routes)
|
routes, err := cmrdr.LoadRoutes(options.Routes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
color.Red("Invalid routes dictionary: %s", err.Error())
|
printErr(logger, fmt.Errorf("Invalid routes dictionary %q: %v", options.Routes, err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSpinner(w, "Scanning the network...", options.EnableLogs)
|
updateSpinner(w, "Scanning the network...", options.EnableLogs)
|
||||||
streams, err := cmrdr.Discover(options.Targets, options.Ports, options.Speed)
|
streams, err := cmrdr.Discover(options.Targets, options.Ports, options.Speed)
|
||||||
if err != nil && len(streams) > 0 {
|
if err != nil && len(streams) > 0 {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Most cameras will be accessed successfully with these two attacks
|
// Most cameras will be accessed successfully with these two attacks
|
||||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their routes...", options.EnableLogs)
|
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their routes...", options.EnableLogs)
|
||||||
streams, err = cmrdr.AttackRoute(c, streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
streams, err = cmrdr.AttackRoute(c, streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||||
if err != nil && len(streams) > 0 {
|
if err != nil && len(streams) > 0 {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their credentials...", options.EnableLogs)
|
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their credentials...", options.EnableLogs)
|
||||||
streams, err = cmrdr.AttackCredentials(c, streams, credentials, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
streams, err = cmrdr.AttackCredentials(c, streams, credentials, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||||
if err != nil && len(streams) > 0 {
|
if err != nil && len(streams) > 0 {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// But some cameras run GST RTSP Server which prioritizes 401 over 404 contrary to most cameras.
|
// But some cameras run GST RTSP Server which prioritizes 401 over 404 contrary to most cameras.
|
||||||
@@ -141,7 +147,7 @@ func main() {
|
|||||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Final attack...", options.EnableLogs)
|
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Final attack...", options.EnableLogs)
|
||||||
streams, err = cmrdr.AttackRoute(c, streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
streams, err = cmrdr.AttackRoute(c, streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||||
if err != nil && len(streams) > 0 {
|
if err != nil && len(streams) > 0 {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
@@ -151,70 +157,62 @@ func main() {
|
|||||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Validating their availability...", options.EnableLogs)
|
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Validating their availability...", options.EnableLogs)
|
||||||
streams, err = cmrdr.ValidateStreams(c, streams, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
streams, err = cmrdr.ValidateStreams(c, streams, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||||
if err != nil && len(streams) > 0 {
|
if err != nil && len(streams) > 0 {
|
||||||
printErr(err)
|
printErr(logger, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
clearOutput(w, options.EnableLogs)
|
clearOutput(w, options.EnableLogs)
|
||||||
|
|
||||||
prettyPrint(streams)
|
prettyPrint(logger, streams)
|
||||||
}
|
}
|
||||||
|
|
||||||
func prettyPrint(streams []cmrdr.Stream) {
|
func prettyPrint(logger *logger.Logger, streams []cmrdr.Stream) {
|
||||||
yellow := color.New(color.FgYellow, color.Bold, color.Underline).SprintFunc()
|
|
||||||
blue := color.New(color.FgBlue, color.Underline).SprintFunc()
|
|
||||||
green := color.New(color.FgGreen, color.Bold).SprintFunc()
|
|
||||||
red := color.New(color.FgRed, color.Bold).SprintFunc()
|
|
||||||
white := color.New(color.Italic).SprintFunc()
|
|
||||||
|
|
||||||
success := 0
|
success := 0
|
||||||
|
|
||||||
if len(streams) > 0 {
|
if len(streams) > 0 {
|
||||||
for _, stream := range streams {
|
for _, stream := range streams {
|
||||||
if stream.CredentialsFound && stream.RouteFound && stream.Available {
|
if stream.CredentialsFound && stream.RouteFound && stream.Available {
|
||||||
fmt.Printf("%s\tDevice RTSP URL:\t%s\n", green("\xE2\x96\xB6"), blue(cmrdr.GetCameraRTSPURL(stream)))
|
logger.Infof("%s\tDevice RTSP URL:\t%s\n", log.Success(symbol.RightTriangle), log.Link(cmrdr.GetCameraRTSPURL(stream)))
|
||||||
success++
|
success++
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s\tAdmin panel URL:\t%s %s\n", red("\xE2\x96\xB6"), yellow(cmrdr.GetCameraAdminPanelURL(stream)), white("You can use this URL to try attacking the camera's admin panel instead."))
|
logger.Infof("%s\tAdmin panel URL:\t%s You can use this URL to try attacking the camera's admin panel instead.\n", log.Failure(symbol.Cross), log.Link(cmrdr.GetCameraAdminPanelURL(stream)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\tDevice model:\t\t%s\n\n", stream.Device)
|
logger.Infof("\tDevice model:\t\t%s\n\n", stream.Device)
|
||||||
|
|
||||||
if stream.Available {
|
if stream.Available {
|
||||||
fmt.Printf("\tAvailable:\t\t%s\n", green("yes"))
|
logger.Infof("\tAvailable:\t\t%s\n", log.Success(symbol.Check))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\tAvailable:\t\t%s\n", red("no"))
|
logger.Infof("\tAvailable:\t\t%s\n", log.Failure(symbol.Cross))
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("\tIP address:\t\t%s\n", stream.Address)
|
logger.Infof("\tIP address:\t\t%s\n", stream.Address)
|
||||||
fmt.Printf("\tRTSP port:\t\t%d\n", stream.Port)
|
logger.Infof("\tRTSP port:\t\t%d\n", stream.Port)
|
||||||
if stream.CredentialsFound {
|
if stream.CredentialsFound {
|
||||||
fmt.Printf("\tUsername:\t\t%s\n", green(stream.Username))
|
logger.Infof("\tUsername:\t\t%s\n", log.Success(stream.Username))
|
||||||
fmt.Printf("\tPassword:\t\t%s\n", green(stream.Password))
|
logger.Infof("\tPassword:\t\t%s\n", log.Success(stream.Password))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\tUsername:\t\t%s\n", red("not found"))
|
logger.Infof("\tUsername:\t\t%s\n", log.Failure("not found"))
|
||||||
fmt.Printf("\tPassword:\t\t%s\n", red("not found"))
|
logger.Infof("\tPassword:\t\t%s\n", log.Failure("not found"))
|
||||||
}
|
}
|
||||||
if stream.RouteFound {
|
if stream.RouteFound {
|
||||||
fmt.Printf("\tRTSP route:\t\t%s\n\n\n", green("/"+stream.Route))
|
logger.Infof("\tRTSP route:\t\t%s\n\n\n", log.Success("/"+stream.Route))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("\tRTSP route:\t\t%s\n\n\n", red("not found"))
|
logger.Infof("\tRTSP route:\t\t%s\n\n\n", log.Failure("not found"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if success > 1 {
|
if success > 1 {
|
||||||
fmt.Printf("%s Successful attack: %s devices were accessed", green("\xE2\x9C\x94"), green(len(streams)))
|
logger.Infof("%s Successful attack: %s devices were accessed", log.Success(symbol.Check), log.Success(len(streams)))
|
||||||
} else if success == 1 {
|
} else if success == 1 {
|
||||||
fmt.Printf("%s Successful attack: %s device was accessed", green("\xE2\x9C\x94"), green(len(streams)))
|
logger.Infof("%s Successful attack: %s device was accessed", log.Success(symbol.Check), log.Success(len(streams)))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s Streams were found but none were accessed. They are most likely configured with secure credentials and routes. You can try adding entries to the dictionary or generating your own in order to attempt a bruteforce attack on the cameras.\n", red("\xE2\x9C\x96"))
|
logger.Infof("%s Streams were found but none were accessed. They are most likely configured with secure credentials and routes. You can try adding entries to the dictionary or generating your own in order to attempt a bruteforce attack on the cameras.\n", log.Failure("\xE2\x9C\x96"))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("%s No streams were found. Please make sure that your target is on an accessible network.\n", red("\xE2\x9C\x96"))
|
logger.Infof("%s No streams were found. Please make sure that your target is on an accessible network.\n", log.Failure(symbol.Cross))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printErr(err error) {
|
func printErr(logger *logger.Logger, err error) {
|
||||||
red := color.New(color.FgRed, color.Bold).SprintFunc()
|
logger.Errorln(log.Failure(symbol.Cross), err)
|
||||||
fmt.Printf("%s %v\n", red("\xE2\x9C\x96"), err)
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ require (
|
|||||||
github.com/mattn/go-isatty v0.0.6 // indirect
|
github.com/mattn/go-isatty v0.0.6 // indirect
|
||||||
github.com/pkg/errors v0.8.1
|
github.com/pkg/errors v0.8.1
|
||||||
github.com/spf13/viper v1.3.1 // indirect
|
github.com/spf13/viper v1.3.1 // indirect
|
||||||
|
github.com/ullaakut/disgo v0.0.0-20190310161027-e17c43d71b3d // indirect
|
||||||
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70
|
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70
|
||||||
github.com/ullaakut/nmap v0.0.0-20190306183004-e38898a9bead
|
github.com/ullaakut/nmap v0.0.0-20190306183004-e38898a9bead
|
||||||
gopkg.in/go-playground/validator.v9 v9.27.0
|
gopkg.in/go-playground/validator.v9 v9.27.0
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ github.com/spf13/viper v1.3.1 h1:5+8j8FTpnFV4nEImW/ofkzEt8VoOiLXxdYIDsB73T38=
|
|||||||
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.1/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||||
|
github.com/ullaakut/disgo v0.0.0-20190310161027-e17c43d71b3d h1:tObr2ILgSQwrhpQRiVUKHtXF+0V5gYnnd/zBQGAmfuQ=
|
||||||
|
github.com/ullaakut/disgo v0.0.0-20190310161027-e17c43d71b3d/go.mod h1:UOgLVyqihzJ7yihrHjYZikivT+AHb9NhT3r1OyPCJqg=
|
||||||
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70 h1:3q4hgRu9NT894aYmnoMFl5wPvdNhpHYmdi2+Njyxq5U=
|
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70 h1:3q4hgRu9NT894aYmnoMFl5wPvdNhpHYmdi2+Njyxq5U=
|
||||||
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70/go.mod h1:FTfXm4jC9Ff1yqc3/HMXCyr+SGO03vJyijJCQlNyF10=
|
github.com/ullaakut/go-curl v0.0.0-20190310175419-50acab4cef70/go.mod h1:FTfXm4jC9Ff1yqc3/HMXCyr+SGO03vJyijJCQlNyF10=
|
||||||
github.com/ullaakut/nmap v0.0.0-20190306183004-e38898a9bead h1:Pw5wKSAfxi8GcYJSc3GdcwtPG5tyg7zg9E3hAHbLPO0=
|
github.com/ullaakut/nmap v0.0.0-20190306183004-e38898a9bead h1:Pw5wKSAfxi8GcYJSc3GdcwtPG5tyg7zg9E3hAHbLPO0=
|
||||||
|
|||||||
Reference in New Issue
Block a user