Add environment variables support
This commit is contained in:
committed by
Brendan Le Glaunec
parent
6d296b84d5
commit
df44c7d6f1
@@ -152,6 +152,60 @@ With the above result, the RTSP URL would be `rtsp://admin:12345@173.16.100.45:5
|
||||
* **"-l, --log"**: Enable debug logs (nmap requests, curl describe requests, etc.)
|
||||
* **"-h"** : Display the usage information
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### `CAMERADAR_TARGET`
|
||||
|
||||
This variable is mandatory and specifies the target that cameradar should scan and attempt to access RTSP streams on.
|
||||
|
||||
Examples:
|
||||
|
||||
* `172.16.100.0/24`
|
||||
* `192.168.1.1`
|
||||
* `localhost`
|
||||
|
||||
### `CAMERADAR_PORTS`
|
||||
|
||||
This variable is optional and allows you to specify the ports on which to run the scans.
|
||||
|
||||
Default value: `554,8554`
|
||||
|
||||
It is recommended not to change these except if you are certain that cameras have been configured to stream RTSP over a different port. 99.9% of cameras are streaming on these ports.
|
||||
|
||||
### `CAMERADAR_NMAP_OUTPUT_FILE`
|
||||
|
||||
This variable is optional and allows you to specify on which file nmap will write its output.
|
||||
|
||||
Default value: `/tmp/cameradar_scan.xml`
|
||||
|
||||
This can be useful only if you want to read the files yourself, if you don't want it to write in your `/tmp` folder, or if you want to use only the RunNmap function in cameradar, and do its parsing manually.
|
||||
|
||||
### `CAMERADAR_CUSTOM_ROUTES`, `CAMERADAR_CUSTOM_CREDENTIALS`
|
||||
|
||||
These variables are optional, allowing to replace the default dictionaries with custom ones, for the dictionary attack.
|
||||
|
||||
Default values: `<CAMERADAR_GOPATH>/dictionaries/routes` and `<CAMERADAR_GOPATH>/dictionaries/credentials.json`
|
||||
|
||||
### `CAMERADAR_SPEED`
|
||||
|
||||
This optional variable allows you to 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).
|
||||
|
||||
Default value: `4`
|
||||
|
||||
### `CAMERADAR_TIMEOUT`
|
||||
|
||||
This optional variable allows you to 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.
|
||||
|
||||
Default value: `2000`
|
||||
|
||||
### `CAMERADAR_LOGS`
|
||||
|
||||
This optional variable allows you to enable a more verbose output to have more information about what is going on.
|
||||
|
||||
It will output nmap results, cURL requests, etc.
|
||||
|
||||
Default: `false`
|
||||
|
||||
## Contribution
|
||||
|
||||
### Build
|
||||
|
||||
+87
-15
@@ -13,6 +13,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -21,29 +22,82 @@ import (
|
||||
"github.com/EtixLabs/cameradar"
|
||||
"github.com/gernest/wow"
|
||||
"github.com/gernest/wow/spin"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/fatih/color"
|
||||
"github.com/jessevdk/go-flags"
|
||||
)
|
||||
|
||||
type options struct {
|
||||
Target string `short:"t" long:"target" description:"The target on which to scan for open RTSP streams - required (ex: 172.16.100.0/24)" required:"true"`
|
||||
Ports string `short:"p" long:"ports" description:"The ports on which to search for RTSP streams" default:"554,8554"`
|
||||
OutputFile string `short:"o" long:"nmap-output" description:"The path where nmap will create its XML result file" default:"/tmp/cameradar_scan.xml"`
|
||||
Routes string `short:"r" long:"custom-routes" description:"The path on which to load a custom routes dictionary" default:"<GOPATH>/src/github.com/EtixLabs/cameradar/dictionaries/routes"`
|
||||
Credentials string `short:"c" long:"custom-credentials" description:"The path on which to load a custom credentials JSON dictionary" default:"<GOPATH>/src/github.com/EtixLabs/cameradar/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:"2000"`
|
||||
EnableLogs bool `short:"l" long:"log" description:"Enable the logs for nmap's output to stdout"`
|
||||
Target string
|
||||
Ports string
|
||||
OutputFile string
|
||||
Routes string
|
||||
Credentials string
|
||||
Speed int
|
||||
Timeout int
|
||||
EnableLogs bool
|
||||
}
|
||||
|
||||
func parseArguments() error {
|
||||
|
||||
viper.BindEnv("target", "CAMERADAR_TARGET")
|
||||
viper.BindEnv("ports", "CAMERADAR_PORTS")
|
||||
viper.BindEnv("nmap-output", "CAMERADAR_NMAP_OUTPUT_FILE")
|
||||
viper.BindEnv("custom-routes", "CAMERADAR_CUSTOM_ROUTES")
|
||||
viper.BindEnv("custom-credentials", "CAMERADAR_CUSTOM_CREDENTIALS")
|
||||
viper.BindEnv("speed", "CAMERADAR_SPEED")
|
||||
viper.BindEnv("timeout", "CAMERADAR_TIMEOUT")
|
||||
viper.BindEnv("envlogs", "CAMERADAR_LOGS")
|
||||
|
||||
pflag.StringP("target", "t", "", "The target on which to scan for open RTSP streams - required (ex: 172.16.100.0/24)")
|
||||
pflag.StringP("ports", "p", "554,8554", "The ports on which to search for RTSP streams")
|
||||
pflag.StringP("nmap-output", "o", "/tmp/cameradar_scan.xml", "The path where nmap will create its XML result file")
|
||||
pflag.StringP("custom-routes", "r", "<GOPATH>/src/github.com/EtixLabs/cameradar/dictionaries/routes", "The path on which to load a custom routes dictionary")
|
||||
pflag.StringP("custom-credentials", "c", "<GOPATH>/src/github.com/EtixLabs/cameradar/dictionaries/credentials.json", "The path on which to load a custom credentials JSON dictionary")
|
||||
pflag.IntP("speed", "s", 4, "The nmap speed preset to use")
|
||||
pflag.IntP("timeout", "T", 2000, "The timeout in miliseconds to use for attack attempts")
|
||||
pflag.BoolP("log", "l", false, "Enable the logs for nmap's output to stdout")
|
||||
pflag.BoolP("help", "h", false, "displays this help message")
|
||||
|
||||
viper.AutomaticEnv()
|
||||
|
||||
pflag.Parse()
|
||||
|
||||
err := viper.BindPFlags(pflag.CommandLine)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if viper.GetBool("help") {
|
||||
pflag.Usage()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if viper.GetString("target") == "" {
|
||||
return errors.New("target (-t, --target) argument required\n examples:\n - 172.16.100.0/24\n - localhost\n - 8.8.8.8")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
var options options
|
||||
_, err := flags.ParseArgs(&options, os.Args[1:])
|
||||
|
||||
err := parseArguments()
|
||||
if err != nil {
|
||||
os.Exit(0)
|
||||
printErr(err)
|
||||
}
|
||||
|
||||
options.Credentials = viper.GetString("custom-credentials")
|
||||
options.EnableLogs = viper.GetBool("log") || viper.GetBool("envlogs")
|
||||
options.OutputFile = viper.GetString("nmap-output")
|
||||
options.Ports = viper.GetString("ports")
|
||||
options.Routes = viper.GetString("custom-routes")
|
||||
options.Speed = viper.GetInt("speed")
|
||||
options.Timeout = viper.GetInt("timeout")
|
||||
options.Target = viper.GetString("target")
|
||||
|
||||
w := startSpinner(options.EnableLogs)
|
||||
|
||||
updateSpinner(w, "Loading dictionaries...", options.EnableLogs)
|
||||
@@ -64,15 +118,24 @@ func main() {
|
||||
}
|
||||
|
||||
updateSpinner(w, "Scanning the network...", options.EnableLogs)
|
||||
streams, _ := cmrdr.Discover(options.Target, options.Ports, options.OutputFile, options.Speed, options.EnableLogs)
|
||||
streams, err := cmrdr.Discover(options.Target, options.Ports, options.OutputFile, options.Speed, options.EnableLogs)
|
||||
if err != nil && len(streams) > 0 {
|
||||
printErr(err)
|
||||
}
|
||||
|
||||
// Most cameras will be accessed successfully with these two attacks
|
||||
|
||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their routes...", options.EnableLogs)
|
||||
streams, _ = cmrdr.AttackRoute(streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
streams, err = cmrdr.AttackRoute(streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
if err != nil && len(streams) > 0 {
|
||||
printErr(err)
|
||||
}
|
||||
|
||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their credentials...", options.EnableLogs)
|
||||
streams, _ = cmrdr.AttackCredentials(streams, credentials, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
streams, err = cmrdr.AttackCredentials(streams, credentials, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
if err != nil && len(streams) > 0 {
|
||||
printErr(err)
|
||||
}
|
||||
|
||||
// But some cameras run GST RTSP Server which prioritizes 401 over 404 contrary to most cameras.
|
||||
// For these cameras, running another route attack will solve the problem.
|
||||
@@ -80,7 +143,10 @@ func main() {
|
||||
if stream.RouteFound == false || stream.CredentialsFound == false {
|
||||
|
||||
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Final attack...", options.EnableLogs)
|
||||
streams, _ = cmrdr.AttackRoute(streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
streams, err = cmrdr.AttackRoute(streams, routes, time.Duration(options.Timeout)*time.Millisecond, options.EnableLogs)
|
||||
if err != nil && len(streams) > 0 {
|
||||
printErr(err)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -135,6 +201,12 @@ func prettyPrint(streams []cmrdr.Stream) {
|
||||
}
|
||||
}
|
||||
|
||||
func printErr(err error) {
|
||||
red := color.New(color.FgRed, color.Bold).SprintFunc()
|
||||
fmt.Printf("%s %v\n", red("\xE2\x9C\x96"), err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func updateSpinner(w *wow.Wow, text string, disabled bool) {
|
||||
if !disabled {
|
||||
w.Text(" " + text)
|
||||
|
||||
+14
-9
@@ -18,6 +18,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
v "gopkg.in/go-playground/validator.v9"
|
||||
@@ -51,17 +52,21 @@ func NmapRun(targets, ports, resultFilePath string, nmapSpeed int, enableLogs bo
|
||||
return fmt.Errorf("invalid nmap speed value '%d'. Should be between '%d' and '%d'", nmapSpeed, PARANOIAC, INSANE)
|
||||
}
|
||||
|
||||
// Prepare nmap command
|
||||
cmd := execCommand(
|
||||
"nmap",
|
||||
fmt.Sprintf("-T%d", nmapSpeed),
|
||||
"-A",
|
||||
"-p",
|
||||
cmdArgs := fmt.Sprintf(
|
||||
"-T%d -A -p %s -oX %s %s",
|
||||
nmapSpeed,
|
||||
ports,
|
||||
"-oX",
|
||||
resultFilePath,
|
||||
targets,
|
||||
)
|
||||
targets)
|
||||
|
||||
if enableLogs {
|
||||
fmt.Printf("command: nmap %s\n", cmdArgs)
|
||||
}
|
||||
|
||||
args := strings.Split(cmdArgs, " ")
|
||||
|
||||
// Prepare nmap command
|
||||
cmd := execCommand("nmap", args...)
|
||||
|
||||
// Pipe stdout to be able to write the logs in realtime
|
||||
stdout, err := cmd.StdoutPipe()
|
||||
|
||||
Generated
+60
-2
@@ -5,6 +5,8 @@ imports:
|
||||
version: f8b334df3789fbdf98df3b3b22815e958b956c19
|
||||
- name: github.com/fatih/color
|
||||
version: 570b54cabe6b8eb0bc2dfce68d964677d63b5260
|
||||
- name: github.com/fsnotify/fsnotify
|
||||
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
|
||||
- name: github.com/gernest/wow
|
||||
version: 57298475c6371a5a652e74dcf624c80edfc5ae1a
|
||||
subpackages:
|
||||
@@ -15,16 +17,72 @@ imports:
|
||||
version: b32fa301c9fe55953584134cb6853a13c87ec0a1
|
||||
- name: github.com/gorilla/websocket
|
||||
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
|
||||
- name: github.com/jessevdk/go-flags
|
||||
version: 96dc06278ce32a0e9d957d590bb987c81ee66407
|
||||
- name: github.com/hashicorp/hcl
|
||||
version: 23c074d0eceb2b8a5bfdbb271ab780cde70f05a8
|
||||
subpackages:
|
||||
- hcl/ast
|
||||
- hcl/parser
|
||||
- hcl/scanner
|
||||
- hcl/strconv
|
||||
- hcl/token
|
||||
- json/parser
|
||||
- json/scanner
|
||||
- json/token
|
||||
- name: github.com/magiconair/properties
|
||||
version: 8d7837e64d3c1ee4e54a880c5a920ab4316fc90a
|
||||
- name: github.com/mattn/go-colorable
|
||||
version: 5411d3eea5978e6cdc258b30de592b60df6aba96
|
||||
repo: https://github.com/mattn/go-colorable
|
||||
- name: github.com/mattn/go-isatty
|
||||
version: 57fdcb988a5c543893cc61bce354a6e24ab70022
|
||||
repo: https://github.com/mattn/go-isatty
|
||||
- name: github.com/mitchellh/mapstructure
|
||||
version: 06020f85339e21b2478f756a78e295255ffa4d6a
|
||||
- name: github.com/pelletier/go-toml
|
||||
version: 4e9e0ee19b60b13eb79915933f44d8ed5f268bdd
|
||||
- name: github.com/pkg/errors
|
||||
version: 645ef00459ed84a119197bfb8d8205042c6df63d
|
||||
- name: github.com/pmezard/go-difflib
|
||||
version: d8ed2627bdf02c080bf22230dbb337003b7aba2d
|
||||
subpackages:
|
||||
- difflib
|
||||
- name: github.com/spf13/afero
|
||||
version: 5660eeed305fe5f69c8fc6cf899132a459a97064
|
||||
subpackages:
|
||||
- mem
|
||||
- name: github.com/spf13/cast
|
||||
version: acbeb36b902d72a7a4c18e8f3241075e7ab763e4
|
||||
- name: github.com/spf13/jwalterweatherman
|
||||
version: 12bd96e66386c1960ab0f74ced1362f66f552f7b
|
||||
- name: github.com/spf13/pflag
|
||||
version: 97afa5e7ca8a08a383cb259e06636b5e2cc7897f
|
||||
- name: github.com/spf13/viper
|
||||
version: 8ef37cbca71638bf32f3d5e194117d4cb46da163
|
||||
- name: github.com/stretchr/objx
|
||||
version: cbeaeb16a013161a98496fad62933b1d21786672
|
||||
- name: github.com/stretchr/testify
|
||||
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
|
||||
subpackages:
|
||||
- mock
|
||||
- name: golang.org/x/crypto
|
||||
version: 2509b142fb2b797aa7587dad548f113b2c0f20ce
|
||||
subpackages:
|
||||
- ssh/terminal
|
||||
- name: golang.org/x/sys
|
||||
version: e24f485414aeafb646f6fca458b0bf869c0880a1
|
||||
repo: https://go.googlesource.com/sys
|
||||
subpackages:
|
||||
- unix
|
||||
- windows
|
||||
- name: golang.org/x/text
|
||||
version: 6eab0e8f74e86c598ec3b6fad4888e0c11482d48
|
||||
subpackages:
|
||||
- transform
|
||||
- unicode/norm
|
||||
- name: gopkg.in/go-playground/validator.v9
|
||||
version: a021b2ec9a8a8bb970f3f15bc42617cb520e8a64
|
||||
- name: gopkg.in/tylerb/graceful.v1
|
||||
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
|
||||
- name: gopkg.in/yaml.v2
|
||||
version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
|
||||
testImports: []
|
||||
|
||||
+2
-2
@@ -8,8 +8,6 @@ import:
|
||||
- spin
|
||||
- package: github.com/gorilla/websocket
|
||||
version: ~1.2.0
|
||||
- package: github.com/jessevdk/go-flags
|
||||
version: ~1.3.0
|
||||
- package: github.com/pkg/errors
|
||||
version: ~0.8.0
|
||||
- package: github.com/stretchr/testify
|
||||
@@ -24,3 +22,5 @@ import:
|
||||
version: ~0.16.0
|
||||
- package: github.com/go-playground/locales
|
||||
version: ~0.11.2
|
||||
- package: github.com/spf13/pflag
|
||||
- package: github.com/spf13/viper
|
||||
|
||||
Reference in New Issue
Block a user