Fix timeout and unresponsive cameras being detected as successful & add error message
Update unit tests Fix deadlock in libcurl for tests to stop failing randomly
This commit is contained in:
committed by
Brendan Le Glaunec
parent
216d30fd45
commit
89647ae457
@@ -145,7 +145,7 @@ With the above result, the RTSP URL would be `rtsp://admin:12345@173.16.100.45:5
|
||||
* **"-t, --target"**: Set custom target. Required.
|
||||
* **"-p, --ports"**: (Default: `554,8554`) Set custom ports.
|
||||
* **"-s, --speed"**: (Default: `4`) Set custom nmap discovery presets to improve speed or accuracy. It's recommended to lower it if you are attempting to scan an unstable and slow network, or to increase it if on a very performant and reliable network. See [this for more info on the nmap timing templates](https://nmap.org/book/man-performance.html).
|
||||
* **"-T, --timeout"**: (Default: `1000`) Set custom timeout value in miliseconds after which an attack attempt without an answer should give up.
|
||||
* **"-T, --timeout"**: (Default: `2000`) Set custom timeout value in miliseconds after which an attack attempt without an answer should give up. It's recommended to increase it when attempting to scan unstable and slow networks or to decrease it on very performant and reliable networks.
|
||||
* **"-r, --custom-routes"**: (Default: `dictionaries/routes`) Set custom dictionary path for routes
|
||||
* **"-c, --custom-credentials"**: (Default: `dictionaries/credentials.json`) Set custom dictionary path for credentials
|
||||
* **"-o, --nmap-output"**: (Default: `/tmp/cameradar_scan.xml`) Set custom nmap output path
|
||||
|
||||
@@ -60,7 +60,11 @@ func routeAttack(camera Stream, route string, timeout time.Duration, enableLogs
|
||||
easy.Setopt(curl.OPT_TIMEOUT_MS, int(timeout/time.Millisecond))
|
||||
|
||||
// Perform the request
|
||||
easy.Perform()
|
||||
err := easy.Perform()
|
||||
if err != nil {
|
||||
fmt.Printf("\nERROR: curl timeout on camera '%s' reached after %s.\nconsider increasing the timeout (-T, --timeout parameter) to at least 5000ms if scanning an unstable network.\n", camera.Address, timeout.String())
|
||||
return false
|
||||
}
|
||||
|
||||
// Get return code for the request
|
||||
rc, err := easy.Getinfo(curl.INFO_RESPONSE_CODE)
|
||||
@@ -68,12 +72,11 @@ func routeAttack(camera Stream, route string, timeout time.Duration, enableLogs
|
||||
return false
|
||||
}
|
||||
|
||||
// If it's a 404, it means that the route was not valid
|
||||
if rc == 404 {
|
||||
return false
|
||||
// If it's a 401 or 403, it means that the credentials are wrong but the route might be okay
|
||||
// If it's a 200, the camera is accessed successfully
|
||||
if rc == 200 || rc == 401 || rc == 403 {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -112,7 +115,11 @@ func credAttack(camera Stream, username string, password string, timeout time.Du
|
||||
easy.Setopt(curl.OPT_TIMEOUT_MS, int(timeout/time.Millisecond))
|
||||
|
||||
// Perform the request
|
||||
easy.Perform()
|
||||
err := easy.Perform()
|
||||
if err != nil {
|
||||
fmt.Printf("\nERROR: curl timeout on camera '%s' reached after %s.\nconsider increasing the timeout (-T, --timeout parameter) to at least 5000ms if scanning an unstable network.\n", camera.Address, timeout.String())
|
||||
return false
|
||||
}
|
||||
|
||||
// Get return code for the request
|
||||
rc, err := easy.Getinfo(curl.INFO_RESPONSE_CODE)
|
||||
@@ -120,12 +127,11 @@ func credAttack(camera Stream, username string, password string, timeout time.Du
|
||||
return false
|
||||
}
|
||||
|
||||
// If it's a 403 or a 401, it means that the credentials are not correct
|
||||
if rc == 403 || rc == 401 {
|
||||
return false
|
||||
// If it's a 404, it means that the route is incorrect but the credentials might be okay
|
||||
// If it's a 200, the camera is accessed successfully
|
||||
if rc == 200 || rc == 404 {
|
||||
return true
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -163,7 +169,12 @@ func attackCameraRoute(target Stream, routes Routes, resultsChan chan<- Stream,
|
||||
|
||||
// AttackCredentials attempts to guess the provided targets' credentials using the given
|
||||
// dictionary or the default dictionary if none was provided by the user.
|
||||
func AttackCredentials(targets []Stream, credentials Credentials, timeout time.Duration, log bool) (results []Stream, err error) {
|
||||
func AttackCredentials(targets []Stream, credentials Credentials, timeout time.Duration, log bool) ([]Stream, error) {
|
||||
err := curl.GlobalInit(curl.GLOBAL_ALL)
|
||||
if err != nil {
|
||||
return targets, errors.Wrap(err, "could not initialize curl")
|
||||
}
|
||||
|
||||
attacks := make(chan Stream)
|
||||
defer close(attacks)
|
||||
|
||||
@@ -198,7 +209,12 @@ func AttackCredentials(targets []Stream, credentials Credentials, timeout time.D
|
||||
|
||||
// AttackRoute attempts to guess the provided targets' streaming routes using the given
|
||||
// dictionary or the default dictionary if none was provided by the user.
|
||||
func AttackRoute(targets []Stream, routes Routes, timeout time.Duration, log bool) (results []Stream, err error) {
|
||||
func AttackRoute(targets []Stream, routes Routes, timeout time.Duration, log bool) ([]Stream, error) {
|
||||
err := curl.GlobalInit(curl.GLOBAL_ALL)
|
||||
if err != nil {
|
||||
return targets, errors.Wrap(err, "could not initialize curl")
|
||||
}
|
||||
|
||||
attacks := make(chan Stream)
|
||||
defer close(attacks)
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ func TestAttackCredentials(t *testing.T) {
|
||||
log: true,
|
||||
|
||||
expectedStreams: fakeTargets,
|
||||
expectedErrMsg: "no credentials found",
|
||||
},
|
||||
// Valid baseline without logs
|
||||
{
|
||||
@@ -69,6 +70,7 @@ func TestAttackCredentials(t *testing.T) {
|
||||
log: false,
|
||||
|
||||
expectedStreams: fakeTargets,
|
||||
expectedErrMsg: "no credentials found",
|
||||
},
|
||||
// TODO: Refacto and make tests with all possible error cases
|
||||
}
|
||||
@@ -134,6 +136,7 @@ func TestAttackRoute(t *testing.T) {
|
||||
log: true,
|
||||
|
||||
expectedStreams: fakeTargets,
|
||||
expectedErrMsg: "no routes found",
|
||||
},
|
||||
// Valid baseline without logs
|
||||
{
|
||||
@@ -143,6 +146,7 @@ func TestAttackRoute(t *testing.T) {
|
||||
log: false,
|
||||
|
||||
expectedStreams: fakeTargets,
|
||||
expectedErrMsg: "no routes found",
|
||||
},
|
||||
// TODO: Refacto and make tests with all possible error cases
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ type options struct {
|
||||
Routes string `short:"r" long:"custom-routes" description:"The path on which to load a custom routes dictionary" default:"../dictionaries/routes"`
|
||||
Credentials string `short:"c" long:"custom-credentials" description:"The path on which to load a custom credentials JSON dictionary" default:"../dictionaries/credentials.json"`
|
||||
Speed int `short:"s" long:"speed" description:"The nmap speed preset to use" default:"4"`
|
||||
Timeout int `short:"T" long:"timeout" description:"The timeout in miliseconds to use for attack attempts" default:"1000"`
|
||||
Timeout int `short:"T" long:"timeout" description:"The timeout in miliseconds to use for attack attempts" default:"2000"`
|
||||
EnableLogs bool `short:"l" long:"log" description:"Enable the logs for nmap's output to stdout"`
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user