Add stream validation -- need to add unit tests

This commit is contained in:
Brendan Le Glaunec
2018-07-22 16:25:56 +02:00
committed by Brendan LE GLAUNEC
parent 6e92eecdf6
commit 1ea9850842
2 changed files with 95 additions and 20 deletions
+94 -20
View File
@@ -9,18 +9,32 @@ import (
v "gopkg.in/go-playground/validator.v9"
)
// HTTP responses
const (
httpOK = 200
httpUnauthorized = 401
httpForbidden = 403
httpNotFound = 404
)
// CURL RTSP request types
const (
rtspDescribe = 2
rtspSetup = 4
)
// HACK: See https://stackoverflow.com/questions/3572397/lib-curl-in-c-disable-printing
func doNotWrite([]uint8, interface{}) bool {
return true
}
func routeAttack(c Curler, camera Stream, route string, timeout time.Duration, enableLogs bool) bool {
func routeAttack(c Curler, stream Stream, route string, timeout time.Duration, enableLogs bool) bool {
attackURL := fmt.Sprintf(
"rtsp://%s:%s@%s:%d/%s",
camera.Username,
camera.Password,
camera.Address,
camera.Port,
stream.Username,
stream.Password,
stream.Address,
stream.Port,
route,
)
@@ -36,19 +50,19 @@ func routeAttack(c Curler, camera Stream, route string, timeout time.Duration, e
c.Setopt(curl.OPT_NOSIGNAL, 1)
// Do not send a body in the describe request
c.Setopt(curl.OPT_NOBODY, 1)
// Send a request to the URL of the camera we want to attack
// Send a request to the URL of the stream we want to attack
c.Setopt(curl.OPT_URL, attackURL)
// Set the RTSP STREAM URI as the camera URL
// Set the RTSP STREAM URI as the stream URL
c.Setopt(curl.OPT_RTSP_STREAM_URI, attackURL)
// 2 is CURL_RTSPREQ_DESCRIBE
c.Setopt(curl.OPT_RTSP_REQUEST, 2)
c.Setopt(curl.OPT_RTSP_REQUEST, rtspDescribe)
// Set custom timeout
c.Setopt(curl.OPT_TIMEOUT_MS, int(timeout/time.Millisecond))
// Perform the request
err := c.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())
fmt.Printf("\nERROR: curl timeout on stream '%s' reached after %s.\nconsider increasing the timeout (-T, --timeout parameter) to at least 5000ms if scanning an unstable network.\n", stream.Address, timeout.String())
return false
}
@@ -59,21 +73,21 @@ func routeAttack(c Curler, camera Stream, route string, timeout time.Duration, e
}
// 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 {
// If it's a 200, the stream is accessed successfully
if rc == httpOK || rc == httpUnauthorized || rc == httpForbidden {
return true
}
return false
}
func credAttack(c Curler, camera Stream, username string, password string, timeout time.Duration, enableLogs bool) bool {
func credAttack(c Curler, stream Stream, username string, password string, timeout time.Duration, enableLogs bool) bool {
attackURL := fmt.Sprintf(
"rtsp://%s:%s@%s:%d/%s",
username,
password,
camera.Address,
camera.Port,
camera.Route,
stream.Address,
stream.Port,
stream.Route,
)
if enableLogs {
@@ -88,9 +102,9 @@ func credAttack(c Curler, camera Stream, username string, password string, timeo
c.Setopt(curl.OPT_NOSIGNAL, 1)
// Do not send a body in the describe request
c.Setopt(curl.OPT_NOBODY, 1)
// Send a request to the URL of the camera we want to attack
// Send a request to the URL of the stream we want to attack
c.Setopt(curl.OPT_URL, attackURL)
// Set the RTSP STREAM URI as the camera URL
// Set the RTSP STREAM URI as the stream URL
c.Setopt(curl.OPT_RTSP_STREAM_URI, attackURL)
// 2 is CURL_RTSPREQ_DESCRIBE
c.Setopt(curl.OPT_RTSP_REQUEST, 2)
@@ -100,7 +114,7 @@ func credAttack(c Curler, camera Stream, username string, password string, timeo
// Perform the request
err := c.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())
fmt.Printf("\nERROR: curl timeout on stream '%s' reached after %s.\nconsider increasing the timeout (-T, --timeout parameter) to at least 5000ms if scanning an unstable network.\n", stream.Address, timeout.String())
return false
}
@@ -111,13 +125,73 @@ func credAttack(c Curler, camera Stream, username string, password string, timeo
}
// 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 {
// If it's a 200, the stream is accessed successfully
if rc == httpOK || rc == httpNotFound {
return true
}
return false
}
func validateStream(c Curler, stream Stream, timeout time.Duration, enableLogs bool) bool {
attackURL := fmt.Sprintf(
"rtsp://%s:%s@%s:%d/%s",
stream.Username,
stream.Password,
stream.Address,
stream.Port,
stream.Route,
)
if enableLogs {
// Debug logs when logs are enabled
c.Setopt(curl.OPT_VERBOSE, 1)
} else {
// Do not write sdp in stdout
c.Setopt(curl.OPT_WRITEFUNCTION, doNotWrite)
}
// Do not use signals (would break multithreading)
c.Setopt(curl.OPT_NOSIGNAL, 1)
// Do not send a body in the describe request
c.Setopt(curl.OPT_NOBODY, 1)
// Send a request to the URL of the stream we want to attack
c.Setopt(curl.OPT_URL, attackURL)
// Set the RTSP STREAM URI as the stream URL
c.Setopt(curl.OPT_RTSP_STREAM_URI, attackURL)
// 2 is CURL_RTSPREQ_SETUP
c.Setopt(curl.OPT_RTSP_REQUEST, rtspSetup)
// Set custom timeout
c.Setopt(curl.OPT_TIMEOUT_MS, int(timeout/time.Millisecond))
// Perform the request
err := c.Perform()
if err != nil {
fmt.Printf("\nERROR: curl timeout on stream '%s' reached after %s.\nconsider increasing the timeout (-T, --timeout parameter) to at least 5000ms if scanning an unstable network.\n", stream.Address, timeout.String())
return false
}
// Get return code for the request
rc, err := c.Getinfo(curl.INFO_RESPONSE_CODE)
if err != nil {
return false
}
// If it's a 200, the stream is accessed successfully
if rc == httpOK {
return true
}
return false
}
// ValidateStreams tries to setup the stream to validate whether or not it is available
func ValidateStreams(c Curler, targets []Stream, timeout time.Duration, log bool) ([]Stream, error) {
for idx, target := range targets {
targets[idx].StreamAvailable = validateStream(c, target, timeout, log)
}
return targets, nil
}
func attackCameraCredentials(c Curler, target Stream, credentials Credentials, resultsChan chan<- Stream, timeout time.Duration, log bool) {
for _, username := range credentials.Usernames {
for _, password := range credentials.Passwords {
+1
View File
@@ -13,6 +13,7 @@ type Stream struct {
CredentialsFound bool `json:"credentials_found"`
RouteFound bool `json:"route_found"`
StreamAvailable bool `json:"stream_available"`
}
// Credentials is a map of credentials