Skip to content

Commit 32ce3a7

Browse files
authored
Merge pull request #79 from projectdiscovery/feature-config-file
adding config file support
2 parents a57c60f + f1a3dd0 commit 32ce3a7

File tree

13 files changed

+411
-21
lines changed

13 files changed

+411
-21
lines changed

Dockerfile

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
# Build Container
2-
FROM golang:1.14-alpine AS build-env
3-
RUN apk add --no-cache --upgrade git openssh-client ca-certificates build-base libpcap libpcap-dev
1+
FROM golang:1.14
2+
RUN apt update && apt install -y nmap
43
WORKDIR /go/src/app
54

65
# Install
7-
RUN go get -u github.com/projectdiscovery/naabu/cmd/naabu
6+
RUN go get -v -u github.com/projectdiscovery/naabu/cmd/naabu
87

98
ENTRYPOINT ["naabu"]

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ require (
66
github.com/google/gopacket v1.1.18
77
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2
88
github.com/projectdiscovery/cdncheck v0.0.0-20200910082712-19e1db650e26
9-
github.com/projectdiscovery/fdmax v0.0.0-20200906213348-dc06b12b82c0
9+
github.com/projectdiscovery/fdmax v0.0.1
1010
github.com/projectdiscovery/gologger v1.0.1
1111
github.com/projectdiscovery/mapcidr v0.0.4
1212
github.com/remeh/sizedwaitgroup v1.0.0
1313
golang.org/x/net v0.0.0-20200904194848-62affa334b73
14+
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
1415
)

go.sum

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rK
88
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
99
github.com/projectdiscovery/cdncheck v0.0.0-20200910082712-19e1db650e26 h1:8LwryON7jJ8xKzghSTY6KxLMBgZM/Vqc9LlWMqf3pLA=
1010
github.com/projectdiscovery/cdncheck v0.0.0-20200910082712-19e1db650e26/go.mod h1:+CNeKlAVwecauIkA+PBNoA7zXGm4MZhL3KKFkkpIaZw=
11-
github.com/projectdiscovery/fdmax v0.0.0-20200906213348-dc06b12b82c0 h1:YNoKWlUGo5O3No882Du8zSzVlsH+Rd6m5uIIZKTXmvA=
12-
github.com/projectdiscovery/fdmax v0.0.0-20200906213348-dc06b12b82c0/go.mod h1:mbR7lJ9EONyxEfcsL2LlGtOSlzCQ5VraLzoJa/VTrAs=
11+
github.com/projectdiscovery/fdmax v0.0.1 h1:EDpan+CgIAAYJ1K1zpTii2SouIDPHQwpGQsYc2UGUj0=
12+
github.com/projectdiscovery/fdmax v0.0.1/go.mod h1:mbR7lJ9EONyxEfcsL2LlGtOSlzCQ5VraLzoJa/VTrAs=
1313
github.com/projectdiscovery/gologger v1.0.1 h1:FzoYQZnxz9DCvSi/eg5A6+ET4CQ0CDUs27l6Exr8zMQ=
1414
github.com/projectdiscovery/gologger v1.0.1/go.mod h1:Ok+axMqK53bWNwDSU1nTNwITLYMXMdZtRc8/y1c7sWE=
1515
github.com/projectdiscovery/mapcidr v0.0.4 h1:2vBSjkmbQASAcO/m2L/dhdulMVu2y9HdyWOrWYJ74rU=
@@ -34,3 +34,5 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
3434
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
3535
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
3636
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
37+
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
38+
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

pkg/runner/banners.go

Lines changed: 76 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package runner
22

33
import (
4+
"io/ioutil"
45
"net"
56
"strings"
67

@@ -30,14 +31,13 @@ func showBanner() {
3031

3132
// showNetworkCapabilities shows the network capabilities/scan types possible with the running user
3233
func showNetworkCapabilities() {
33-
accessLevel := "not root"
34-
scanType := "Connect (Full Handshake)"
34+
accessLevel := "non root"
35+
scanType := "CONNECT"
3536
if isRoot() {
3637
accessLevel = "root"
37-
scanType = "TCP/ICMP Probes + Syn Scan"
38+
scanType = "TCP/ICMP/SYN"
3839
}
39-
gologger.Infof("Access Level: %s\n", accessLevel)
40-
gologger.Infof("Scan Type: %s\n", scanType)
40+
gologger.Infof("Running %s scan with %s privileges\n", scanType, accessLevel)
4141
}
4242

4343
func showNetworkInterfaces() error {
@@ -79,3 +79,74 @@ func handlePrivileges(options *Options) error {
7979

8080
return nil
8181
}
82+
83+
func (options *Options) writeDefaultConfig() {
84+
dummyconfig := `
85+
# Number of retries
86+
# retries: 1
87+
# Packets rate
88+
# rate: 100
89+
# Number of threads
90+
# threads: 1
91+
# Timeout is the seconds to wait for ports to respond
92+
# timeout: 5
93+
# Hosts are the host to find ports for
94+
# host:
95+
# - 10.10.10.10
96+
# Ports is the ports to use for enumeration
97+
# ports:
98+
# - 80
99+
# - 100
100+
# ExcludePorts is the list of ports to exclude from enumeration
101+
# exclude-ports:
102+
# - 20
103+
# - 30
104+
# Verify is used to check if the ports found were valid using CONNECT method
105+
# verify: false
106+
# NoProbe skips probes to discover alive hosts
107+
# no-probe: false
108+
# Ping uses ping probes to discover fastest active host and discover dead hosts
109+
# ping: true
110+
# Port Probes (SYN-PORT, ACK-PORT)
111+
# port-probes:
112+
# - A80
113+
# - S110
114+
# Ips or cidr to be excluded from the scan
115+
# exclude-ips:
116+
# - 1.1.1.1
117+
# - 2.2.2.2
118+
# Top ports list
119+
# top-ports: 100
120+
# Attempts to run as root
121+
# privileged: true
122+
# Drop root privileges
123+
# unprivileged: true
124+
# Excludes ip of knows CDN ranges
125+
# exclude-cdn: true
126+
# IcmpEchoProbe before scanning
127+
# icmp-echo-probe: true
128+
# IcmpTimestampProbe before scanning
129+
# icmp-timestamp-probe: false
130+
# SourceIp to use in TCP packets
131+
# source-ip: 10.10.10.10
132+
# Interface to use for TCP packets
133+
# interface: eth0
134+
# WarmUpTime between scan phases
135+
# warm-up-time: 2
136+
# nmap command to invoke after scanning
137+
# nmap: nmap -SV
138+
`
139+
configFile, err := getDefaultConfigFile()
140+
if err != nil {
141+
gologger.Fatalf("Could not get default configuration file: %s\n", err)
142+
}
143+
if fileExists(configFile) {
144+
return
145+
}
146+
147+
err = ioutil.WriteFile(configFile, []byte(dummyconfig), 0755)
148+
if err != nil {
149+
gologger.Fatalf("Could not write configuration file to %s: %s\n", configFile, err)
150+
}
151+
gologger.Infof("Configuration file saved to %s\n", configFile)
152+
}

pkg/runner/config.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package runner
2+
3+
import (
4+
"os"
5+
"path"
6+
7+
"gopkg.in/yaml.v3"
8+
)
9+
10+
const ConfigDefaultFilename = "naabu.conf"
11+
12+
// ConfigFile contains the fields stored in the configuration file
13+
type ConfigFile struct {
14+
// Retries is the number of retries for the port
15+
Retries int `yaml:"retries,omitempty"`
16+
// Rate is the rate of port scan requests
17+
Rate int `yaml:"rate,omitempty"`
18+
// Thread controls the number of parallel host to enumerate
19+
Threads int `yaml:"threads,omitempty"`
20+
// Timeout is the seconds to wait for ports to respond
21+
Timeout int `yaml:"timeout,omitempty"`
22+
// Hosts are the host to find ports for
23+
Host []string `yaml:"host,omitempty"`
24+
// Ports is the ports to use for enumeration
25+
Ports []string `yaml:"ports,omitempty"`
26+
// ExcludePorts is the list of ports to exclude from enumeration
27+
ExcludePorts []string `yaml:"exclude-ports,omitempty"`
28+
// Verify is used to check if the ports found were valid using CONNECT method
29+
Verify bool `yaml:"verify,omitempty"`
30+
// NoProbe skips probes to discover alive hosts
31+
NoProbe bool `yaml:"no-probe,omitempty"`
32+
// Ping uses ping probes to discover fastest active host and discover dead hosts
33+
Ping bool `yaml:"ping,omitempty"`
34+
// Port Probes (SYN-PORT, ACK-PORT)
35+
PortProbes []string `yaml:"port-probes,omitempty"`
36+
// Ips or cidr to be excluded from the scan
37+
ExcludeIps []string `yaml:"exclude-ips,omitempty"`
38+
// Top ports list
39+
TopPorts string `yaml:"top-ports,omitempty"`
40+
// Attempts to run as root
41+
Privileged bool `yaml:"privileged,omitempty"`
42+
// Drop root privileges
43+
Unprivileged bool `yaml:"unprivileged,omitempty"`
44+
// Excludes ip of knows CDN ranges
45+
ExcludeCDN bool `yaml:"exclude-cdn,omitempty"`
46+
// IcmpEchoProbe before scanning
47+
IcmpEchoProbe bool `yaml:"icmp-echo-probe,omitempty"`
48+
// IcmpTimestampProbe before scanning
49+
IcmpTimestampProbe bool `yaml:"icmp-timestamp-probe,omitempty"`
50+
// SourceIp to use in TCP packets
51+
SourceIp string `yaml:"source-ip,omitempty"`
52+
// Interface to use for TCP packets
53+
Interface string `yaml:"interface,omitempty"`
54+
// WarmUpTime between scan phases
55+
WarmUpTime int `yaml:"warm-up-time,omitempty"`
56+
// NMapCommand to invoke after scanning
57+
NMapCommand string `yaml:"nmap,omitempty"`
58+
}
59+
60+
// GetConfigDirectory gets the subfinder config directory for a user
61+
func GetConfigDirectory() (string, error) {
62+
var config string
63+
64+
directory, err := os.UserHomeDir()
65+
if err != nil {
66+
return config, err
67+
}
68+
config = directory + "/.config/naabu"
69+
70+
// Create All directory for naabu even if they exist
71+
err = os.MkdirAll(config, os.ModePerm)
72+
if err != nil {
73+
return config, err
74+
}
75+
76+
return config, nil
77+
}
78+
79+
// CheckConfigExists checks if the config file exists in the given path
80+
func CheckConfigExists(configPath string) bool {
81+
if _, err := os.Stat(configPath); err == nil {
82+
return true
83+
} else if os.IsNotExist(err) {
84+
return false
85+
}
86+
return false
87+
}
88+
89+
// MarshalWrite writes the marshaled yaml config to disk
90+
func (c *ConfigFile) MarshalWrite(file string) error {
91+
f, err := os.OpenFile(file, os.O_WRONLY|os.O_CREATE, 0755)
92+
if err != nil {
93+
return err
94+
}
95+
96+
// Indent the spaces too
97+
enc := yaml.NewEncoder(f)
98+
err = enc.Encode(&c)
99+
f.Close()
100+
return err
101+
}
102+
103+
// UnmarshalRead reads the unmarshalled config yaml file from disk
104+
func UnmarshalRead(file string) (ConfigFile, error) {
105+
config := ConfigFile{}
106+
107+
f, err := os.Open(file)
108+
if err != nil {
109+
return config, err
110+
}
111+
err = yaml.NewDecoder(f).Decode(&config)
112+
f.Close()
113+
return config, err
114+
}
115+
116+
func getDefaultConfigFile() (string, error) {
117+
directory, err := GetConfigDirectory()
118+
if err != nil {
119+
return "", err
120+
}
121+
return path.Join(directory, ConfigDefaultFilename), nil
122+
}

pkg/runner/file.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package runner
2+
3+
import "os"
4+
5+
func fileExists(filename string) bool {
6+
info, err := os.Stat(filename)
7+
if os.IsNotExist(err) {
8+
return false
9+
}
10+
return !info.IsDir()
11+
}

pkg/runner/ips.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ func parseExcludedIps(options *Options) (map[string]struct{}, error) {
2323
allIps = append(allIps, strings.Split(string(data), "\n")...)
2424
}
2525

26+
if options.config != nil {
27+
for _, excludeIp := range options.config.ExcludeIps {
28+
allIps = append(allIps, strings.Split(excludeIp, ",")...)
29+
}
30+
}
31+
2632
for _, ip := range allIps {
2733
if ip == "" {
2834
continue

pkg/runner/nmap.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package runner
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"os/exec"
7+
"strings"
8+
9+
"github.com/projectdiscovery/gologger"
10+
)
11+
12+
func (r *Runner) handleNmap() {
13+
if r.options.config != nil && r.options.config.NMapCommand != "" {
14+
args := strings.Split(r.options.config.NMapCommand, " ")
15+
var (
16+
ips []string
17+
ports []string
18+
)
19+
allports := make(map[int]struct{})
20+
for ip, p := range r.scanner.ScanResults.M {
21+
ips = append(ips, ip)
22+
for pp := range p {
23+
allports[pp] = struct{}{}
24+
}
25+
}
26+
for p := range allports {
27+
ports = append(ports, fmt.Sprintf("%d", p))
28+
}
29+
30+
portsStr := strings.Join(ports, ",")
31+
ipsStr := strings.Join(ips, ",")
32+
33+
args = append(args, "-p")
34+
args = append(args, portsStr)
35+
args = append(args, ips...)
36+
37+
if r.options.Nmap {
38+
gologger.Infof("Running nmap command: %s -p %s %s", r.options.config.NMapCommand, portsStr, ipsStr)
39+
cmd := exec.Command(args[0], args[1:]...)
40+
cmd.Stdout = os.Stdout
41+
cmd.Run()
42+
} else {
43+
gologger.Infof("Suggested nmap command: %s -p %s %s", r.options.config.NMapCommand, portsStr, ipsStr)
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)