Add stream validation -- need to add unit tests
This commit is contained in:
committed by
Brendan LE GLAUNEC
parent
6e92eecdf6
commit
1ea9850842
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user