/
config.go
142 lines (116 loc) · 3.39 KB
/
config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package config
import (
"errors"
"flag"
"os"
"strings"
"github.com/Escape-Technologies/goctopus/internal/utils"
log "github.com/sirupsen/logrus"
)
type Config struct {
InputFile string
Addresses []string
OutputFile string
MaxWorkers int
Verbose bool
Silent bool
Timeout int
Introspection bool
FieldSuggestion bool
WebhookUrl string
SubdomainEnumeration bool
Proxies []string
}
var (
c *Config
)
func Get() *Config {
if c == nil {
log.Panic("Config not initialized")
}
return c
}
func parseArgs() []string {
if flag.Arg(0) == "" {
log.Error("Invalid addresses argument")
utils.PrintUsage()
os.Exit(1)
}
input := flag.Arg(0)
return strings.Split(input, ",")
}
func LoadFromArgs() {
flag.Usage = utils.PrintUsage
config := Config{}
// -- INPUT --
flag.StringVar(&config.InputFile, "f", "", "Input file")
// -- CONFIG --
flag.StringVar(&config.OutputFile, "o", "", "Output file (json-lines format)")
flag.StringVar(&config.WebhookUrl, "webhook", "", "Webhook URL")
flag.IntVar(&config.MaxWorkers, "w", 40, "Max workers")
flag.BoolVar(&config.Verbose, "v", false, "Verbose")
flag.BoolVar(&config.Silent, "s", false, "Silent")
flag.IntVar(&config.Timeout, "t", 30, "Request timeout (seconds)")
flag.BoolVar(&config.Introspection, "introspect", false, "Enable introspection fingerprinting")
flag.BoolVar(&config.FieldSuggestion, "suggest", false, "Enable fields suggestion fingerprinting.\nNeeds \"introspection\" to be enabled.")
flag.BoolVar(&config.SubdomainEnumeration, "subdomain", false, "Enable subdomain enumeration")
proxyStr := flag.String("proxy", "", "Proxies urls (comma separated)")
// -a (All) flag enables all fingerprinting methods
all := flag.Bool("a", false, "(All) Enable all fingerprinting methods: introspection, field suggestion, subdomain enumeration")
flag.Parse()
if *all {
config.Introspection = true
config.FieldSuggestion = true
config.SubdomainEnumeration = true
}
if *proxyStr != "" {
config.Proxies = strings.Split(*proxyStr, ",")
}
if config.InputFile == "" {
config.Addresses = parseArgs()
}
if config.Verbose {
log.SetLevel(log.DebugLevel)
}
if config.Silent {
log.SetLevel(log.ErrorLevel)
}
if err := validateConfig(&config, true); err != nil {
log.Error(err)
flag.PrintDefaults()
os.Exit(1)
}
c = &config
}
// Validates the config.
// `cli` is used to determine if the config is loaded from the CLI or from a file.
// If cli is false, then the addresses check is skipped.
func validateConfig(conf *Config, isCli bool) error {
if conf.MaxWorkers < 1 {
return errors.New("[Invalid config] Max workers must be greater than 0")
}
if conf.Timeout < 1 {
return errors.New("[Invalid config] Timeout must be greater than 0")
}
if !conf.Introspection && conf.FieldSuggestion {
return errors.New("[Invalid config] Introspection has to be enabled to use field suggestion fingerprinting")
}
if isCli && conf.InputFile == "" && len(conf.Addresses) == 0 {
return errors.New("[Invalid config] Please specify an input file or a list of addresses")
}
return nil
}
func Load(config *Config) {
if err := validateConfig(config, false); err != nil {
log.Error(err)
flag.PrintDefaults()
os.Exit(1)
}
c = config
if c.Verbose {
log.SetLevel(log.DebugLevel)
}
if c.Silent {
log.SetLevel(log.ErrorLevel)
}
}