Add environment variables support

This commit is contained in:
Ishan Jain
2017-10-27 06:56:36 +05:30
committed by Brendan Le Glaunec
parent 6d296b84d5
commit df44c7d6f1
6 changed files with 217 additions and 28 deletions
+54
View File
@@ -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.) * **"-l, --log"**: Enable debug logs (nmap requests, curl describe requests, etc.)
* **"-h"** : Display the usage information * **"-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 ## Contribution
### Build ### Build
+87 -15
View File
@@ -13,6 +13,7 @@
package main package main
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@@ -21,29 +22,82 @@ import (
"github.com/EtixLabs/cameradar" "github.com/EtixLabs/cameradar"
"github.com/gernest/wow" "github.com/gernest/wow"
"github.com/gernest/wow/spin" "github.com/gernest/wow/spin"
"github.com/spf13/pflag"
"github.com/spf13/viper"
"github.com/fatih/color" "github.com/fatih/color"
"github.com/jessevdk/go-flags"
) )
type options struct { 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"` Target string
Ports string `short:"p" long:"ports" description:"The ports on which to search for RTSP streams" default:"554,8554"` Ports string
OutputFile string `short:"o" long:"nmap-output" description:"The path where nmap will create its XML result file" default:"/tmp/cameradar_scan.xml"` OutputFile string
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"` Routes string
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"` Credentials string
Speed int `short:"s" long:"speed" description:"The nmap speed preset to use" default:"4"` Speed int
Timeout int `short:"T" long:"timeout" description:"The timeout in miliseconds to use for attack attempts" default:"2000"` Timeout int
EnableLogs bool `short:"l" long:"log" description:"Enable the logs for nmap's output to stdout"` 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() { func main() {
var options options var options options
_, err := flags.ParseArgs(&options, os.Args[1:])
err := parseArguments()
if err != nil { 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) w := startSpinner(options.EnableLogs)
updateSpinner(w, "Loading dictionaries...", options.EnableLogs) updateSpinner(w, "Loading dictionaries...", options.EnableLogs)
@@ -64,15 +118,24 @@ func main() {
} }
updateSpinner(w, "Scanning the network...", options.EnableLogs) 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 // Most cameras will be accessed successfully with these two attacks
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Attacking their routes...", options.EnableLogs) 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) 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. // 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. // For these cameras, running another route attack will solve the problem.
@@ -80,7 +143,10 @@ func main() {
if stream.RouteFound == false || stream.CredentialsFound == false { if stream.RouteFound == false || stream.CredentialsFound == false {
updateSpinner(w, "Found "+fmt.Sprint(len(streams))+" streams. Final attack...", options.EnableLogs) 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 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) { func updateSpinner(w *wow.Wow, text string, disabled bool) {
if !disabled { if !disabled {
w.Text(" " + text) w.Text(" " + text)
Executable
BIN
View File
Binary file not shown.
+14 -9
View File
@@ -18,6 +18,7 @@ import (
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os/exec" "os/exec"
"strings"
"github.com/pkg/errors" "github.com/pkg/errors"
v "gopkg.in/go-playground/validator.v9" 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) return fmt.Errorf("invalid nmap speed value '%d'. Should be between '%d' and '%d'", nmapSpeed, PARANOIAC, INSANE)
} }
// Prepare nmap command cmdArgs := fmt.Sprintf(
cmd := execCommand( "-T%d -A -p %s -oX %s %s",
"nmap", nmapSpeed,
fmt.Sprintf("-T%d", nmapSpeed),
"-A",
"-p",
ports, ports,
"-oX",
resultFilePath, 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 // Pipe stdout to be able to write the logs in realtime
stdout, err := cmd.StdoutPipe() stdout, err := cmd.StdoutPipe()
Generated
+60 -2
View File
@@ -5,6 +5,8 @@ imports:
version: f8b334df3789fbdf98df3b3b22815e958b956c19 version: f8b334df3789fbdf98df3b3b22815e958b956c19
- name: github.com/fatih/color - name: github.com/fatih/color
version: 570b54cabe6b8eb0bc2dfce68d964677d63b5260 version: 570b54cabe6b8eb0bc2dfce68d964677d63b5260
- name: github.com/fsnotify/fsnotify
version: 4da3e2cfbabc9f751898f250b49f2439785783a1
- name: github.com/gernest/wow - name: github.com/gernest/wow
version: 57298475c6371a5a652e74dcf624c80edfc5ae1a version: 57298475c6371a5a652e74dcf624c80edfc5ae1a
subpackages: subpackages:
@@ -15,16 +17,72 @@ imports:
version: b32fa301c9fe55953584134cb6853a13c87ec0a1 version: b32fa301c9fe55953584134cb6853a13c87ec0a1
- name: github.com/gorilla/websocket - name: github.com/gorilla/websocket
version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b version: ea4d1f681babbce9545c9c5f3d5194a789c89f5b
- name: github.com/jessevdk/go-flags - name: github.com/hashicorp/hcl
version: 96dc06278ce32a0e9d957d590bb987c81ee66407 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 - name: github.com/pkg/errors
version: 645ef00459ed84a119197bfb8d8205042c6df63d 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 - name: github.com/stretchr/testify
version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0
subpackages: subpackages:
- mock - 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 - name: gopkg.in/go-playground/validator.v9
version: a021b2ec9a8a8bb970f3f15bc42617cb520e8a64 version: a021b2ec9a8a8bb970f3f15bc42617cb520e8a64
- name: gopkg.in/tylerb/graceful.v1 - name: gopkg.in/tylerb/graceful.v1
version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb version: 4654dfbb6ad53cb5e27f37d99b02e16c1872fbbb
- name: gopkg.in/yaml.v2
version: eb3733d160e74a9c7e442f435eb3bea458e1d19f
testImports: [] testImports: []
+2 -2
View File
@@ -8,8 +8,6 @@ import:
- spin - spin
- package: github.com/gorilla/websocket - package: github.com/gorilla/websocket
version: ~1.2.0 version: ~1.2.0
- package: github.com/jessevdk/go-flags
version: ~1.3.0
- package: github.com/pkg/errors - package: github.com/pkg/errors
version: ~0.8.0 version: ~0.8.0
- package: github.com/stretchr/testify - package: github.com/stretchr/testify
@@ -24,3 +22,5 @@ import:
version: ~0.16.0 version: ~0.16.0
- package: github.com/go-playground/locales - package: github.com/go-playground/locales
version: ~0.11.2 version: ~0.11.2
- package: github.com/spf13/pflag
- package: github.com/spf13/viper