8531c006d4
* enhancement: supporting http tunneled rtsp * refactor: simplify HTTP tunnel support per review feedback - Extract streamCandidate() for nmap port classification - Add isCommonHTTPPort() for masscan and nmap fallback - Move URL building to Stream.String() and Stream.URL() - Pass Stream directly to attack methods instead of individual args - Add TLS config for HTTPS tunnel support - Make auth detection non-fatal for tunneled streams - Rename HTTPTunnel to UseHTTPTunnel * - Testing the auth workflow for the tunneled streams is not blocking the rest of the pipeline since I changed the return values to Auth unknown and nil - added extra ports in the test according to suggestions * fixing some lint errors * removing the unused buildrtspurl * delayed the urlstream call for clarity removed error messages refactored the test that used the deprecated buildTRSPurl to use stream.URL and stream.String() methods * extracting iscommonHTTP port to pkg/ports (package ports) switching on u.scheme to create proper schemes for http and https * refactor: replace HTTP tunnel bool with scheme-based detection; enable TLS only for HTTPS-tunneled streams * chore: simnplify InferTunnelScheme and newRTSPClient * fix: remove rendundant check in streamCandidate * fix: typo in parseScheme * tests: coverage for new schemes * fix: use RTSP and not RTSPS for HTTPS URLs * fix: tunneled RTSP scheme handling and auth detection fallback * ui: render empty credentials as none in summary and TUI * chore: ignore duplicate-string warning for none literal * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * fix: rtsps probe headers --------- Co-authored-by: Brendan Le Glaunec <brendan@glaulabs.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
85 lines
2.5 KiB
Go
85 lines
2.5 KiB
Go
package attack
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/Ullaakut/cameradar/v6"
|
|
"github.com/bluenviron/gortsplib/v5/pkg/base"
|
|
)
|
|
|
|
func (a Attacker) detectAuthMethods(ctx context.Context, targets []cameradar.Stream) ([]cameradar.Stream, error) {
|
|
streams, err := runParallel(ctx, targets, a.detectAuthMethod)
|
|
if err != nil {
|
|
return streams, err
|
|
}
|
|
|
|
for i := range streams {
|
|
a.reporter.Progress(cameradar.StepDetectAuth, cameradar.ProgressTickMessage())
|
|
|
|
var authMethod string
|
|
switch streams[i].AuthenticationType {
|
|
case cameradar.AuthNone:
|
|
authMethod = "no"
|
|
case cameradar.AuthBasic:
|
|
authMethod = "basic"
|
|
case cameradar.AuthDigest:
|
|
authMethod = "digest"
|
|
case cameradar.AuthUnknown:
|
|
authMethod = "unknown"
|
|
default:
|
|
authMethod = fmt.Sprintf("unknown (%d)", streams[i].AuthenticationType)
|
|
}
|
|
|
|
a.reporter.Progress(cameradar.StepDetectAuth, fmt.Sprintf("Detected %s authentication for %s:%d", authMethod, streams[i].Address.String(), streams[i].Port))
|
|
}
|
|
|
|
return streams, nil
|
|
}
|
|
|
|
func (a Attacker) detectAuthMethod(ctx context.Context, stream cameradar.Stream) (cameradar.Stream, error) {
|
|
if ctx.Err() != nil {
|
|
return stream, ctx.Err()
|
|
}
|
|
u, err := stream.URL()
|
|
if err != nil {
|
|
return stream, fmt.Errorf("building rtsp url: %w", err)
|
|
}
|
|
|
|
statusCode, headers, err := a.probeDescribeHeaders(ctx, u)
|
|
if err != nil {
|
|
a.reporter.Debug(cameradar.StepDetectAuth, fmt.Sprintf("DESCRIBE %s RTSP/1.0 > error: %v", u, err))
|
|
if stream.Scheme == schemeHTTP || stream.Scheme == schemeHTTPS {
|
|
statusCode, statusErr := a.describeStatus(stream)
|
|
if statusErr == nil {
|
|
a.reporter.Debug(cameradar.StepDetectAuth, fmt.Sprintf("DESCRIBE %s RTSP/1.0 > %d (fallback)", u, statusCode))
|
|
stream.AuthenticationType = authTypeFromStatus(statusCode, nil)
|
|
return stream, nil
|
|
}
|
|
|
|
stream.AuthenticationType = cameradar.AuthUnknown
|
|
return stream, nil
|
|
}
|
|
|
|
stream.AuthenticationType = cameradar.AuthUnknown
|
|
return stream, fmt.Errorf("performing describe request at %q: %w", u, err)
|
|
}
|
|
|
|
a.reporter.Debug(cameradar.StepDetectAuth, fmt.Sprintf("DESCRIBE %s RTSP/1.0 > %d", u, statusCode))
|
|
values := headerValues(headers, "WWW-Authenticate")
|
|
stream.AuthenticationType = authTypeFromStatus(statusCode, values)
|
|
|
|
return stream, nil
|
|
}
|
|
|
|
func authTypeFromStatus(statusCode base.StatusCode, wwwAuthenticate base.HeaderValue) cameradar.AuthType {
|
|
switch statusCode {
|
|
case base.StatusOK:
|
|
return cameradar.AuthNone
|
|
case base.StatusUnauthorized:
|
|
return authTypeFromHeaders(wwwAuthenticate)
|
|
default:
|
|
return cameradar.AuthUnknown
|
|
}
|
|
}
|