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:
Brendan LE GLAUNEC
2017-10-18 08:43:02 +02:00
committed by Brendan Le Glaunec
parent 216d30fd45
commit 89647ae457
4 changed files with 36 additions and 16 deletions
+1 -1
View File
@@ -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
+30 -14
View File
@@ -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)
+4
View File
@@ -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
}
+1 -1
View File
@@ -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"`
}