Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@ jobs:
with:
go-version: 1.17

- name: Check out code
uses: actions/checkout@v2

- name: Install libpcap-dev
run: sudo apt install libpcap-dev

- name: Check out code
uses: actions/checkout@v2
- name: Install nmap
run: sudo apt install nmap

- name: Test
run: go test .
working-directory: v2/cmd/naabu/
run: go test ./...
working-directory: v2/

- name: Build
run: go build .
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ jobs:
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]

steps:
- name: Install libpcap-dev
run: sudo apt install libpcap-dev

- name: Checkout repository
uses: actions/checkout@v2

Expand Down
10 changes: 8 additions & 2 deletions v2/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,19 +22,25 @@ require (
go.uber.org/ratelimit v0.2.0
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
)

require (
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.7.0
)

require (
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/cnf/structhash v0.0.0-20201127153200-e1b16c1ebc08 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/json-iterator/go v1.1.11 // indirect
github.com/karrick/godirwalk v1.16.1 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/miekg/dns v1.1.43 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/projectdiscovery/hmap v0.0.1 // indirect
github.com/projectdiscovery/retryabledns v1.0.13-0.20210927160332-db15799e2e4d // indirect
github.com/projectdiscovery/retryablehttp-go v1.0.2 // indirect
Expand Down
6 changes: 4 additions & 2 deletions v2/pkg/result/results.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ type Result struct {
// NewResult structure
func NewResult() *Result {
ipPorts := make(map[string]map[int]struct{})
ipDomains := make(map[string]struct{})
return &Result{IPPorts: ipPorts, IPS: ipDomains}
ips := make(map[string]struct{})
return &Result{IPPorts: ipPorts, IPS: ips}
}

// AddPort to a specific ip
Expand All @@ -26,6 +26,7 @@ func (r *Result) AddPort(k string, v int) {
}

r.IPPorts[k][v] = struct{}{}
r.IPS[k] = struct{}{}
}

// SetPorts for a specific ip
Expand All @@ -34,6 +35,7 @@ func (r *Result) SetPorts(k string, v map[int]struct{}) {
defer r.Unlock()

r.IPPorts[k] = v
r.IPS[k] = struct{}{}
}

// IPHasPort checks if an ip has a specific port
Expand Down
64 changes: 64 additions & 0 deletions v2/pkg/result/results_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package result

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestAddPort(t *testing.T) {
targetIP := "127.0.0.1"
targetPort := 8080
targetPorts := map[int]struct{}{targetPort: {}}

res := NewResult()
res.AddPort(targetIP, targetPort)

expectedIPS := map[string]struct{}{targetIP: {}}
assert.Equal(t, res.IPS, expectedIPS)

expectedIPSPorts := map[string]map[int]struct{}{targetIP: targetPorts}
assert.Equal(t, res.IPPorts, expectedIPSPorts)
}

func TestSetPorts(t *testing.T) {
targetIP := "127.0.0.1"
targetPorts := map[int]struct{}{80: {}, 8080: {}}

res := NewResult()
res.SetPorts(targetIP, targetPorts)

expectedIPS := map[string]struct{}{targetIP: {}}
assert.Equal(t, res.IPS, expectedIPS)

expectedIPSPorts := map[string]map[int]struct{}{targetIP: targetPorts}
assert.Equal(t, res.IPPorts, expectedIPSPorts)
}

func TestIPHasPort(t *testing.T) {
targetIP := "127.0.0.1"
targetPort := 8080

res := NewResult()
res.AddPort(targetIP, targetPort)
assert.True(t, res.IPHasPort(targetIP, targetPort))
assert.False(t, res.IPHasPort(targetIP, 1111))
}

func TestSetIP(t *testing.T) {
targetIP := "127.0.0.1"

res := NewResult()
res.SetIP(targetIP)
expectedIPS := map[string]struct{}{targetIP: {}}
assert.Equal(t, res.IPS, expectedIPS)
}

func TestHasIP(t *testing.T) {
targetIP := "127.0.0.1"

res := NewResult()
res.SetIP(targetIP)
assert.True(t, res.HasIP(targetIP))
assert.False(t, res.HasIP("1.2.3.4"))
}
12 changes: 12 additions & 0 deletions v2/pkg/runner/banners_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package runner

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestShowNetworkInterfaces(t *testing.T) {
// non root users should be able to list interfaces
assert.Nil(t, showNetworkInterfaces())
}
39 changes: 39 additions & 0 deletions v2/pkg/runner/ips_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package runner

import (
"os"
"strings"
"testing"

"github.com/projectdiscovery/fileutil"
"github.com/stretchr/testify/assert"
)

func TestParseExcludedIps(t *testing.T) {
tmpFileName, err := fileutil.GetTempFileName()
assert.Nil(t, err)
expectedIpsFromCLI := []string{"8.8.8.0/24", "7.7.7.7"}
expectedIpsFromFile := []string{"10.10.10.0/24", "192.168.1.0/24"}
assert.Nil(t, os.WriteFile(tmpFileName, []byte(strings.Join(expectedIpsFromFile, "\n")), 0755))
expected := append(expectedIpsFromCLI, expectedIpsFromFile...)

actual, err := parseExcludedIps(&Options{
ExcludeIps: strings.Join(expectedIpsFromCLI, ","),
ExcludeIpsFile: tmpFileName,
})
assert.Nil(t, err)
assert.Equal(t, expected, actual)

defer os.RemoveAll(tmpFileName)
}

func TestIsIpOrCidr(t *testing.T) {
valid := []string{"1.1.1.1", "2.2.2.2", "1.1.1.0/24"}
invalid := []string{"1.1.1.1.1", "a.a.a.a", "77"}
for _, validItem := range valid {
assert.True(t, isIpOrCidr(validItem))
}
for _, invalidItem := range invalid {
assert.False(t, isIpOrCidr(invalidItem))
}
}
16 changes: 11 additions & 5 deletions v2/pkg/runner/nmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import (
"os/exec"
"strings"

"github.com/pkg/errors"

"github.com/projectdiscovery/gologger"
)

func (r *Runner) handleNmap() {
func (r *Runner) handleNmap() error {
// command from CLI
command := r.options.NmapCLI
hasCLI := r.options.NmapCLI != ""
Expand All @@ -33,8 +35,9 @@ func (r *Runner) handleNmap() {

// if we have no open ports we avoid running nmap
if len(ports) == 0 {
gologger.Info().Msgf("Skipping nmap scan as no open ports were found")
return
errMsg := errors.New("Skipping nmap scan as no open ports were found")
gologger.Info().Msgf(errMsg.Error())
return errMsg
}

portsStr := strings.Join(ports, ",")
Expand All @@ -50,11 +53,14 @@ func (r *Runner) handleNmap() {
cmd.Stdout = os.Stdout
err := cmd.Run()
if err != nil {
gologger.Error().Msgf("Could not run nmap command: %s\n", err)
return
errMsg := errors.Wrap(err, "Could not run nmap command")
gologger.Error().Msgf(errMsg.Error())
return errMsg
}
} else {
gologger.Info().Msgf("Suggested nmap command: %s -p %s %s", command, portsStr, ipsStr)
}
}

return nil
}
25 changes: 25 additions & 0 deletions v2/pkg/runner/nmap_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package runner

import (
"testing"

"github.com/projectdiscovery/naabu/v2/pkg/result"
"github.com/projectdiscovery/naabu/v2/pkg/scan"
"github.com/stretchr/testify/assert"
)

func TestHandleNmap(t *testing.T) {
// just attempt to start nmap
var r Runner
r.options = &Options{}
// nmap with empty cli shouldn't trigger any error
res := result.NewResult()
r.scanner = &scan.Scanner{}
r.scanner.ScanResults = res
assert.Nil(t, r.handleNmap())
r.scanner.ScanResults.IPPorts = make(map[string]map[int]struct{})
// nmap syntax error (this test might fail if nmap is not installed on the box)
assert.Nil(t, r.handleNmap())
r.scanner.ScanResults.IPPorts = map[string]map[int]struct{}{"127.0.0.1": {8080: struct{}{}}}
assert.Nil(t, r.handleNmap())
}
28 changes: 28 additions & 0 deletions v2/pkg/runner/output_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package runner

import (
"bytes"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

func TestWriteHostOutput(t *testing.T) {
host := "127.0.0.1"
ports := map[int]struct{}{80: {}, 8080: {}}
var s string
buf := bytes.NewBufferString(s)
assert.Nil(t, WriteHostOutput(host, ports, buf))
assert.Equal(t, "127.0.0.1:80\n127.0.0.1:8080\n", buf.String())
}

func TestWriteJSONOutput(t *testing.T) {
host := "localhost"
ip := "127.0.0.1"
ports := map[int]struct{}{80: {}, 8080: {}}
var s string
buf := bytes.NewBufferString(s)
assert.Nil(t, WriteJSONOutput(host, ip, ports, buf))
assert.Equal(t, 3, len(strings.Split(buf.String(), "\n")))
}
22 changes: 10 additions & 12 deletions v2/pkg/runner/ports.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"sort"
"strconv"
"strings"

"github.com/pkg/errors"
)

const portListStrParts = 2
Expand Down Expand Up @@ -42,8 +44,8 @@ func ParsePorts(options *Options) ([]int, error) {

// If the user has specfied top ports, use them as well
if options.TopPorts != "" {
// If the user has specfied full ports, use them
if strings.EqualFold(options.TopPorts, "full") {
switch strings.ToLower(options.TopPorts) {
case "full": // If the user has specfied full ports, use them
var err error
ports, err := parsePortsList(Full)
if err != nil {
Expand All @@ -53,10 +55,7 @@ func ParsePorts(options *Options) ([]int, error) {
if err != nil {
return nil, fmt.Errorf("could not read ports: %s", err)
}
}

// If the user has specfied top-100, use them
if strings.EqualFold(options.TopPorts, "top-100") {
case "top-100": // If the user has specfied top-100, use them
ports, err := parsePortsList(NmapTop100)
if err != nil {
return nil, fmt.Errorf("could not read ports: %s", err)
Expand All @@ -65,10 +64,7 @@ func ParsePorts(options *Options) ([]int, error) {
if err != nil {
return nil, fmt.Errorf("could not read ports: %s", err)
}
}

// If the user has specfied top-1000, use them
if strings.EqualFold(options.TopPorts, "top-1000") {
case "top-1000": // If the user has specfied top-1000, use them
ports, err := parsePortsList(NmapTop1000)
if err != nil {
return nil, fmt.Errorf("could not read ports: %s", err)
Expand All @@ -77,10 +73,12 @@ func ParsePorts(options *Options) ([]int, error) {
if err != nil {
return nil, fmt.Errorf("could not read ports: %s", err)
}
default:
return nil, errors.New("invalid top ports option")
}
}

// If the user has specfied top option, use them too
// If the user has specfied ports option, use them too
if options.Ports != "" {
// "-" equals to all ports
if options.Ports == "-" {
Expand All @@ -97,7 +95,7 @@ func ParsePorts(options *Options) ([]int, error) {
}
}

// merge all the specified ports (meaningless is "all" is used)
// merge all the specified ports (meaningless if "all" is used)
portsConfigMap := merge(portsConfigList...)
ports := merge(portsFileMap, portsCLIMap, topPortsCLIMap, portsConfigMap)

Expand Down
Loading