diff --git a/.github/workflows/lint-test.yml b/.github/workflows/lint-test.yml index 22106aab..78324526 100644 --- a/.github/workflows/lint-test.yml +++ b/.github/workflows/lint-test.yml @@ -24,7 +24,7 @@ jobs: run: sudo apt install libpcap-dev - name: Run golangci-lint - uses: golangci/golangci-lint-action@v6.1.1 + uses: golangci/golangci-lint-action@v6.2.0 with: version: latest args: --timeout 5m \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 3e2e3a80..b12e3535 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build -FROM golang:1.23.3-alpine AS build-env +FROM golang:1.23.5-alpine AS build-env RUN apk add --no-cache build-base libpcap-dev WORKDIR /app COPY . /app @@ -7,7 +7,7 @@ RUN go mod download RUN go build ./cmd/naabu # Release -FROM alpine:3.20.3 +FROM alpine:3.21.2 RUN apk upgrade --no-cache \ && apk add --no-cache nmap libpcap-dev bind-tools ca-certificates nmap-scripts COPY --from=build-env /app/naabu /usr/local/bin/ diff --git a/cmd/integration-test/library.go b/cmd/integration-test/library.go index 6757a860..5fd5fc01 100644 --- a/cmd/integration-test/library.go +++ b/cmd/integration-test/library.go @@ -5,7 +5,9 @@ import ( "errors" "os" "os/user" + "time" + "github.com/armon/go-socks5" "github.com/projectdiscovery/naabu/v2/internal/testutils" "github.com/projectdiscovery/naabu/v2/pkg/privileges" "github.com/projectdiscovery/naabu/v2/pkg/result" @@ -18,6 +20,7 @@ var libraryTestcases = map[string]testutils.TestCase{ "sdk - multiple executions - connect": &naabuMultipleExecLibrary{scanType: "c"}, "sdk - one execution - syn": &naabuSingleLibrary{scanType: "s"}, "sdk - multiple executions - syn": &naabuMultipleExecLibrary{scanType: "s"}, + "sdk - connect with proxy": &naabuWithSocks5{}, } type naabuPassiveSingleLibrary struct { @@ -137,3 +140,60 @@ func (h *naabuMultipleExecLibrary) Execute() error { } return nil } + +type naabuWithSocks5 struct{} + +func (h *naabuWithSocks5) Execute() error { + // Start local SOCKS5 proxy server with test:test credentials + conf := &socks5.Config{ + Credentials: socks5.StaticCredentials{ + "test": "test", + }, + } + server, err := socks5.New(conf) + if err != nil { + panic(err) + } + go func() { + if err = server.ListenAndServe("tcp", "127.0.0.1:38401"); err != nil { + panic(err) + } + }() + + testFile := "test.txt" + err = os.WriteFile(testFile, []byte("scanme.sh"), 0644) + if err != nil { + return err + } + defer os.RemoveAll(testFile) + + var got bool + + options := runner.Options{ + HostsFile: testFile, + Ports: "80", + ScanType: "c", + Proxy: "127.0.0.1:38401", + ProxyAuth: "test:test", + OnResult: func(hr *result.HostResult) { + got = true + }, + WarmUpTime: 2, + Timeout: 10 * time.Second, + } + + naabuRunner, err := runner.NewRunner(&options) + if err != nil { + return err + } + defer naabuRunner.Close() + + if err = naabuRunner.RunEnumeration(context.TODO()); err != nil { + return err + } + if !got { + return errors.New("no results found") + } + + return nil +} diff --git a/cmd/test/main.go b/cmd/test/main.go new file mode 100644 index 00000000..e6ca1068 --- /dev/null +++ b/cmd/test/main.go @@ -0,0 +1,69 @@ +package main + +import ( + "context" + "log" + "net" + "os" + "time" + + "github.com/armon/go-socks5" + "github.com/projectdiscovery/naabu/v2/pkg/result" + "github.com/projectdiscovery/naabu/v2/pkg/runner" +) + +func main() { + conf := &socks5.Config{ + Credentials: socks5.StaticCredentials{ + "test": "test", + }, + Dial: func(ctx context.Context, network, addr string) (net.Conn, error) { + log.Println("dialing", network, addr) + return net.Dial(network, addr) + }, + } + server, err := socks5.New(conf) + if err != nil { + panic(err) + } + go func() { + if err = server.ListenAndServe("tcp", "127.0.0.1:38401"); err != nil { + panic(err) + } + }() + + testFile := "test.txt" + err = os.WriteFile(testFile, []byte("scanme.sh"), 0644) + if err != nil { + panic(err) + } + defer os.RemoveAll(testFile) + + var got bool + + options := runner.Options{ + HostsFile: testFile, + Ports: "80", + ScanType: "c", + Proxy: "127.0.0.1:38401", + ProxyAuth: "test:test", + OnResult: func(hr *result.HostResult) { + got = true + }, + WarmUpTime: 2, + Timeout: 10 * time.Second, + } + + naabuRunner, err := runner.NewRunner(&options) + if err != nil { + panic(err) + } + defer naabuRunner.Close() + + if err = naabuRunner.RunEnumeration(context.TODO()); err != nil { + panic(err) + } + if !got { + panic("no results found") + } +} diff --git a/go.mod b/go.mod index 1875ce6a..ae96d255 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.21 require ( github.com/Mzack9999/gcache v0.0.0-20230410081825-519e28eab057 + github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 github.com/gopacket/gopacket v1.2.0 github.com/logrusorgru/aurora v2.0.3+incompatible @@ -15,21 +16,21 @@ require ( github.com/projectdiscovery/dnsx v1.2.1 github.com/projectdiscovery/fdmax v0.0.4 github.com/projectdiscovery/freeport v0.0.7 - github.com/projectdiscovery/goflags v0.1.65 - github.com/projectdiscovery/gologger v1.1.33 + github.com/projectdiscovery/goflags v0.1.68 + github.com/projectdiscovery/gologger v1.1.41 github.com/projectdiscovery/ipranger v0.0.53 github.com/projectdiscovery/mapcidr v1.1.34 - github.com/projectdiscovery/networkpolicy v0.0.9 - github.com/projectdiscovery/ratelimit v0.0.63 - github.com/projectdiscovery/retryablehttp-go v1.0.88 + github.com/projectdiscovery/networkpolicy v0.1.1 + github.com/projectdiscovery/ratelimit v0.0.68 + github.com/projectdiscovery/retryablehttp-go v1.0.96 github.com/projectdiscovery/uncover v1.0.9 - github.com/projectdiscovery/utils v0.2.21 + github.com/projectdiscovery/utils v0.4.6 github.com/remeh/sizedwaitgroup v1.0.0 github.com/stretchr/testify v1.9.0 go.uber.org/multierr v1.11.0 golang.org/x/exp v0.0.0-20231006140011-7918f672742d - golang.org/x/net v0.29.0 - golang.org/x/sys v0.25.0 + golang.org/x/net v0.33.0 + golang.org/x/sys v0.28.0 ) require ( @@ -84,10 +85,10 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/projectdiscovery/asnmap v1.1.1 // indirect - github.com/projectdiscovery/fastdialer v0.2.10 // indirect - github.com/projectdiscovery/hmap v0.0.68 // indirect + github.com/projectdiscovery/fastdialer v0.2.15 // indirect + github.com/projectdiscovery/hmap v0.0.76 // indirect github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 // indirect - github.com/projectdiscovery/retryabledns v1.0.86 // indirect + github.com/projectdiscovery/retryabledns v1.0.93 // indirect github.com/refraction-networking/utls v1.6.7 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d // indirect @@ -115,12 +116,12 @@ require ( github.com/zmap/rc2 v0.0.0-20190804163417-abaa70531248 // indirect github.com/zmap/zcrypto v0.0.0-20230814193918-dbe676986518 // indirect go.etcd.io/bbolt v1.3.7 // indirect - golang.org/x/crypto v0.27.0 // indirect + golang.org/x/crypto v0.31.0 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/term v0.24.0 // indirect - golang.org/x/text v0.18.0 // indirect + golang.org/x/sync v0.10.0 // indirect + golang.org/x/term v0.27.0 // indirect + golang.org/x/text v0.21.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect google.golang.org/appengine v1.6.8 // indirect diff --git a/go.sum b/go.sum index af7208ba..3d3a5f8d 100644 --- a/go.sum +++ b/go.sum @@ -21,6 +21,8 @@ github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW5 github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= @@ -192,36 +194,36 @@ github.com/projectdiscovery/clistats v0.1.1 h1:8mwbdbwTU4aT88TJvwIzTpiNeow3XnAB7 github.com/projectdiscovery/clistats v0.1.1/go.mod h1:4LtTC9Oy//RiuT1+76MfTg8Hqs7FQp1JIGBM3nHK6a0= github.com/projectdiscovery/dnsx v1.2.1 h1:TxslYvp1Z/YZ4CP/J0gx5RYpvXREnVmyoacmTcGu5yg= github.com/projectdiscovery/dnsx v1.2.1/go.mod h1:6dAsMCEDu7FArZy2qjyTeUQrqpZ4ITLU11fcmUvFqt0= -github.com/projectdiscovery/fastdialer v0.2.10 h1:5iciZXMPdynbk/9iuqkJT1gqMXwzgEpFSWdoj/5CHCo= -github.com/projectdiscovery/fastdialer v0.2.10/go.mod h1:21rwXMecVsPVdSvON8Up761/GgxC4OSc9Rvx5LNH5fY= +github.com/projectdiscovery/fastdialer v0.2.15 h1:mq79KOx+XXvXfid2FyRy7vYzFT9uWZbCwJ9XxrHiytA= +github.com/projectdiscovery/fastdialer v0.2.15/go.mod h1:Q0YLArvpx9GAfY/NcTPMCA9qZuVOGnuVoNYWzKBwxdQ= github.com/projectdiscovery/fdmax v0.0.4 h1:K9tIl5MUZrEMzjvwn/G4drsHms2aufTn1xUdeVcmhmc= github.com/projectdiscovery/fdmax v0.0.4/go.mod h1:oZLqbhMuJ5FmcoaalOm31B1P4Vka/CqP50nWjgtSz+I= github.com/projectdiscovery/freeport v0.0.7 h1:Q6uXo/j8SaV/GlAHkEYQi8WQoPXyJWxyspx+aFmz9Qk= github.com/projectdiscovery/freeport v0.0.7/go.mod h1:cOhWKvNBe9xM6dFJ3RrrLvJ5vXx2NQ36SecuwjenV2k= -github.com/projectdiscovery/goflags v0.1.65 h1:rjoj+5lP/FDzgeM0WILUTX9AOOnw0J0LXtl8P1SVeGE= -github.com/projectdiscovery/goflags v0.1.65/go.mod h1:cg6+yrLlaekP1hnefBc/UXbH1YGWa0fuzEW9iS1aG4g= -github.com/projectdiscovery/gologger v1.1.33 h1:wQxaQ8p/0Rx89lowBp0PnY2QSWiqf9QW1vGYAllsVJ4= -github.com/projectdiscovery/gologger v1.1.33/go.mod h1:P/WwqKstshQATJxN39V0KJ9ZuiGLOizmSqHIYrrz1T4= -github.com/projectdiscovery/hmap v0.0.68 h1:/z1Cz2wKYedTJc97UNzBBgdm744xkXi6j7125b7toqg= -github.com/projectdiscovery/hmap v0.0.68/go.mod h1:B37g7giW6i7+X1pJAeG0NPoKFpFJ7M26a18gfwfLeEc= +github.com/projectdiscovery/goflags v0.1.68 h1:o+uROASO6hNkLEU127/SXjUyGC0wCjiyGZedKejhW8k= +github.com/projectdiscovery/goflags v0.1.68/go.mod h1:WmVQzaIzh8xFZ3Akz8RzA6yfULkJdbWWgWu+5hZD9cg= +github.com/projectdiscovery/gologger v1.1.41 h1:s5iAOhYDoKnUay5CtvhFpZdGzQKXeARJbpQubThT1Bs= +github.com/projectdiscovery/gologger v1.1.41/go.mod h1:68ltkt+p8WquBsi4CQ2Z2nfrDXhuraC7GQbtH15B0PI= +github.com/projectdiscovery/hmap v0.0.76 h1:m13e18HEJYkCddcnHucn0XxO/tG8Av6TX+U1dw+PQzQ= +github.com/projectdiscovery/hmap v0.0.76/go.mod h1:AmLVOcAQKX4Iq4vTE/07LONuctMNUOveofI5EHb4oMQ= github.com/projectdiscovery/ipranger v0.0.53 h1:gb4yEqtC2MJl1tSdx/ycao1A1wl7sHqjHeifZidO3Z4= github.com/projectdiscovery/ipranger v0.0.53/go.mod h1:r6R0DFKQRo4QR2zjZXqLRCp0ovbco8F/NmOI+pK4db8= github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983 h1:ZScLodGSezQVwsQDtBSMFp72WDq0nNN+KE/5DHKY5QE= github.com/projectdiscovery/machineid v0.0.0-20240226150047-2e2c51e35983/go.mod h1:3G3BRKui7nMuDFAZKR/M2hiOLtaOmyukT20g88qRQjI= github.com/projectdiscovery/mapcidr v1.1.34 h1:udr83vQ7oz3kEOwlsU6NC6o08leJzSDQtls1wmXN/kM= github.com/projectdiscovery/mapcidr v1.1.34/go.mod h1:1+1R6OkKSAKtWDXE9RvxXtXPoajXTYX0eiEdkqlhQqQ= -github.com/projectdiscovery/networkpolicy v0.0.9 h1:IrlDoYZagNNO8y+7iZeHT8k5izE+nek7TdtvEBwCxqk= -github.com/projectdiscovery/networkpolicy v0.0.9/go.mod h1:XFJ2Lnv8BE/ziQCFjBHMsH1w6VmkPiQtk+NlBpdMU7M= -github.com/projectdiscovery/ratelimit v0.0.63 h1:lFZxO2BlUEle+mGLhsYz4s2B/WedY/RhavG4Kx115/c= -github.com/projectdiscovery/ratelimit v0.0.63/go.mod h1:+hhUPFKiDLSlvWeaz6+BI2LC0RuQOt8rBkTyKy0swMA= -github.com/projectdiscovery/retryabledns v1.0.86 h1:8YMJGJ94lFBKKN3t7NOzJfbGsZoh9qNpi49xdfJcZVc= -github.com/projectdiscovery/retryabledns v1.0.86/go.mod h1:5PhXvlLkEFmlYOt9i4wiKA1eONLrNiZ6DQE88Ph9rgU= -github.com/projectdiscovery/retryablehttp-go v1.0.88 h1:uR6T+i8Sy1isfG1KClhhsXnOqkOR6E8MAvuyOFq3T10= -github.com/projectdiscovery/retryablehttp-go v1.0.88/go.mod h1:ktjiIKyej+plUeK9vksqRf3wGicqY3E1rW84V/O7p0M= +github.com/projectdiscovery/networkpolicy v0.1.1 h1:iv9gECukD5KAZp98KVh+T3TEPTkY6dr3sKsdbh9XyZU= +github.com/projectdiscovery/networkpolicy v0.1.1/go.mod h1:/Hg2ieLewSe/BagFF+UYXAQo3NwmVMq16MSAl492XkU= +github.com/projectdiscovery/ratelimit v0.0.68 h1:gMLD1aB4R8w7BIpKvtQf6TNb6+5zsJO9WSRWZ9pxwe4= +github.com/projectdiscovery/ratelimit v0.0.68/go.mod h1:ieU9nNu9Ie8nVMKdj3bsX3JA3kfNI8qn4pkNXsyRxsw= +github.com/projectdiscovery/retryabledns v1.0.93 h1:iKcEEEH77WwUf5EGimhHxCDdqBF2kOl7WhQi3VQXB8Q= +github.com/projectdiscovery/retryabledns v1.0.93/go.mod h1:f5HmPdVr3CUm4tHHiB0UyiZVQTYYAKTqfoj8M2gCvqo= +github.com/projectdiscovery/retryablehttp-go v1.0.96 h1:/88LMgEGVx5rpqdLYIqxyJHBluuREKxJxPVIWi1zOlA= +github.com/projectdiscovery/retryablehttp-go v1.0.96/go.mod h1:YIN8SpckCijt5J1AV+nQApUWyCC3Y+8nAwDfK/RwhWs= github.com/projectdiscovery/uncover v1.0.9 h1:s5RbkD/V4r8QcPkys4gTTqMuRSgXq0JprejqLSopN9Y= github.com/projectdiscovery/uncover v1.0.9/go.mod h1:2PUF3SpB5QNIJ8epaB2xbRzkPaxEAWRDm3Ir2ijt81U= -github.com/projectdiscovery/utils v0.2.21 h1:5YHyf+viDg0FFJnWFNEw0u608dXHj7nYdMGLUQzvwew= -github.com/projectdiscovery/utils v0.2.21/go.mod h1:LuiMbnvhvQV5qUQY44sQeGnfg4+fGEeuYFRRpxOyvwo= +github.com/projectdiscovery/utils v0.4.6 h1:lwbS5d/f70wyDwuwF6lAVkn390hEI/0LOtqyqJEI+qE= +github.com/projectdiscovery/utils v0.4.6/go.mod h1:eevtW7+x7ydrBdmOenmHdqqJKRv3VqY2QUR7vs4qRfU= github.com/refraction-networking/utls v1.6.7 h1:zVJ7sP1dJx/WtVuITug3qYUq034cDq9B2MR1K67ULZM= github.com/refraction-networking/utls v1.6.7/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= github.com/remeh/sizedwaitgroup v1.0.0 h1:VNGGFwNo/R5+MJBf6yrsr110p0m4/OX4S3DCy7Kyl5E= @@ -332,8 +334,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= -golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= +golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= +golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -354,8 +356,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= -golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo= -golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= @@ -364,8 +366,8 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= +golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -390,8 +392,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= -golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -399,8 +401,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= -golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= -golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= +golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q= +golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -412,8 +414,8 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224= -golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= +golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/pkg/routing/router_freebsd.go b/pkg/routing/router_freebsd.go new file mode 100644 index 00000000..94f57503 --- /dev/null +++ b/pkg/routing/router_freebsd.go @@ -0,0 +1,152 @@ +//go:build freebsd + +package routing + +import ( + "bufio" + "bytes" + "fmt" + "net" + "os/exec" + "strings" + + "github.com/pkg/errors" + "github.com/projectdiscovery/gologger" + sliceutil "github.com/projectdiscovery/utils/slice" + stringsutil "github.com/projectdiscovery/utils/strings" + "go.uber.org/multierr" +) + +// New creates a routing engine for FreeBSD +func New() (Router, error) { + var routes []*Route + netstatCmd := exec.Command("netstat", "-nr") + netstatOutput, err := netstatCmd.Output() + if err != nil { + var route4, route6 *Route + // create default routes with outgoing ips + ip4, ip6, errOutboundIps := GetOutboundIPs() + if ip4 != nil { + interface4, err := FindInterfaceByIp(ip4) + if err != nil { + return nil, err + } + route4 = &Route{ + Type: IPv4, + Default: true, + DefaultSourceIP: ip4, + NetworkInterface: interface4, + } + routes = append(routes, route4) + } + + // try to find outbound route for ipv6 + if ip6 != nil { + interface6, _ := FindInterfaceByIp(ip6) + route6 = &Route{ + Type: IPv6, + Default: true, + DefaultSourceIP: ip6, + NetworkInterface: interface6, + } + routes = append(routes, route6) + } else { + // if we fail, use the same network interface for ipv4 + route6 = &Route{ + Type: IPv6, + Default: true, + NetworkInterface: route4.NetworkInterface, + } + routes = append(routes, route6) + } + if len(routes) > 0 { + return &RouterFreebsd{Routes: routes}, nil + } + return nil, multierr.Combine(err, errOutboundIps) + } + + var lastType RouteType + + scanner := bufio.NewScanner(bytes.NewReader(netstatOutput)) + for scanner.Scan() { + outputLine := strings.TrimSpace(scanner.Text()) + if outputLine == "" { + continue + } + + parts := stringsutil.SplitAny(outputLine, " \t") + if len(parts) >= 4 && !sliceutil.Contains(parts, "Destination") { + expire := "-1" + if len(parts) > 4 { + expire = parts[4] + } + + route := &Route{ + Default: stringsutil.EqualFoldAny(parts[0], "default"), + Destination: parts[0], + Gateway: parts[1], + Flags: parts[2], + Expire: expire, + } + + if networkInterface, err := net.InterfaceByName(parts[3]); err == nil { + route.NetworkInterface = networkInterface + } + + hasDots := stringsutil.ContainsAny(route.Destination, ".") || stringsutil.ContainsAny(route.Gateway, ".") + hasSemicolon := stringsutil.ContainsAny(route.Destination, ":") || stringsutil.ContainsAny(route.Gateway, ":") + switch { + case hasDots: + route.Type = IPv4 + case hasSemicolon: + route.Type = IPv6 + default: + // use last route type and print a warning + if lastType != "" { + gologger.Debug().Msgf("using '%s' for unknown route type: '%s'\n", lastType, outputLine) + route.Type = lastType + } else { + // we can't determine the route type + return nil, fmt.Errorf("could not determine route type for: '%s'", outputLine) + } + } + lastType = route.Type + routes = append(routes, route) + } + } + + return &RouterFreebsd{Routes: routes}, err +} + +type RouterFreebsd struct { + Routes []*Route +} + +func (r *RouterFreebsd) Route(dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) { + route, err := FindRouteForIp(dst, r.Routes) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "could not find route") + } + + if route.DefaultSourceIP != nil { + return nil, nil, route.DefaultSourceIP, nil + } + + if route.NetworkInterface == nil { + return nil, nil, nil, errors.Wrap(err, "could not find network interface") + } + ip, err := FindSourceIpForIp(route, dst) + if err != nil { + return nil, nil, nil, errors.Wrap(err, "could not find source ip") + } + + return route.NetworkInterface, net.ParseIP(route.Gateway), ip, nil +} + +func (r *RouterFreebsd) RouteWithSrc(input net.HardwareAddr, src, dst net.IP) (iface *net.Interface, gateway, preferredSrc net.IP, err error) { + route, err := FindRouteWithHwAndIp(input, src, r.Routes) + if err != nil { + return nil, nil, nil, err + } + return route.NetworkInterface, net.ParseIP(route.Gateway), src, nil +} diff --git a/pkg/runner/banners.go b/pkg/runner/banners.go index 5b0b8899..48d36b5c 100644 --- a/pkg/runner/banners.go +++ b/pkg/runner/banners.go @@ -19,7 +19,7 @@ const banner = ` ` // Version is the current version of naabu -const version = `2.3.3` +const version = `2.3.4` // showBanner is used to show the banner to the user func showBanner() { diff --git a/pkg/runner/default.go b/pkg/runner/default.go index 0f3b3a5e..2ce366db 100644 --- a/pkg/runner/default.go +++ b/pkg/runner/default.go @@ -1,8 +1,10 @@ package runner +import "time" + const ( - DefaultPortTimeoutSynScan = 1000 - DefaultPortTimeoutConnectScan = 5000 + DefaultPortTimeoutSynScan = time.Second + DefaultPortTimeoutConnectScan = time.Duration(5 * time.Second) DefaultRateSynScan = 1000 DefaultRateConnectScan = 1500 diff --git a/pkg/runner/options.go b/pkg/runner/options.go index 29c7e74b..436a5821 100644 --- a/pkg/runner/options.go +++ b/pkg/runner/options.go @@ -32,9 +32,10 @@ type Options struct { Nmap bool // Invoke nmap detailed scan on results InterfacesList bool // InterfacesList show interfaces list - Retries int // Retries is the number of retries for the port - Rate int // Rate is the rate of port scan requests - Timeout int // Timeout is the seconds to wait for ports to respond + Retries int // Retries is the number of retries for the port + Rate int // Rate is the rate of port scan requests + // Timeout int // Timeout is the milliseconds to wait for ports to respond + Timeout time.Duration WarmUpTime int // WarmUpTime between scan phases Host goflags.StringSlice // Host is the single host or comma-separated list of hosts to find ports for HostsFile string // HostsFile is the file containing list of hosts to find port for @@ -189,7 +190,7 @@ func ParseOptions() *Options { flagSet.CreateGroup("optimization", "Optimization", flagSet.IntVar(&options.Retries, "retries", DefaultRetriesSynScan, "number of retries for the port scan"), - flagSet.IntVar(&options.Timeout, "timeout", DefaultPortTimeoutSynScan, "millisecond to wait before timing out"), + flagSet.DurationVar(&options.Timeout, "timeout", DefaultPortTimeoutSynScan, "millisecond to wait before timing out"), flagSet.IntVar(&options.WarmUpTime, "warm-up-time", 2, "time in seconds between scan phases"), flagSet.BoolVar(&options.Ping, "ping", false, "ping probes for verification of host"), flagSet.BoolVar(&options.Verify, "verify", false, "validate the ports again with TCP verification"), diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go index 7cb9eb21..acec7470 100644 --- a/pkg/runner/runner.go +++ b/pkg/runner/runner.go @@ -28,7 +28,9 @@ import ( "github.com/projectdiscovery/naabu/v2/pkg/privileges" "github.com/projectdiscovery/naabu/v2/pkg/protocol" "github.com/projectdiscovery/naabu/v2/pkg/result" + "github.com/projectdiscovery/naabu/v2/pkg/result/confidence" "github.com/projectdiscovery/naabu/v2/pkg/scan" + "github.com/projectdiscovery/naabu/v2/pkg/utils/limits" "github.com/projectdiscovery/ratelimit" "github.com/projectdiscovery/retryablehttp-go" "github.com/projectdiscovery/uncover/sources/agent/shodanidb" @@ -114,7 +116,7 @@ func NewRunner(options *Options) (*Runner, error) { runner.unique = uniqueCache scanOpts := &scan.Options{ - Timeout: time.Duration(options.Timeout) * time.Millisecond, + Timeout: options.Timeout, Retries: options.Retries, Rate: options.Rate, PortThreshold: options.PortThreshold, @@ -282,6 +284,11 @@ func (r *Runner) RunEnumeration(pctx context.Context) error { } } + // automatically adjust rate limit if proxy is used + if r.options.Proxy != "" { + r.options.Rate = limits.RateLimitWithProxy(r.options.Rate) + } + // Scan workers r.wgscan = sizedwaitgroup.New(r.options.Rate) r.limiter = ratelimit.New(context.Background(), uint(r.options.Rate), time.Second) @@ -435,10 +442,15 @@ func (r *Runner) RunEnumeration(pctx context.Context) error { return } for _, p := range filteredPorts { + r.scanner.ScanResults.AddPort(ip, p) + // ignore OnReceive when verification is enabled + if r.options.Verify { + continue + } if r.scanner.OnReceive != nil { r.scanner.OnReceive(&result.HostResult{IP: ip, Ports: []*port.Port{p}}) } - r.scanner.ScanResults.AddPort(ip, p) + } }(ip) } @@ -734,17 +746,24 @@ func (r *Runner) ConnectVerification() { for hostResult := range r.scanner.ScanResults.GetIPsPorts() { limiter.Take() + swg.Add(1) go func(hostResult *result.HostResult) { defer swg.Done() + + // skip low confidence + if hostResult.Confidence == confidence.Low { + return + } + results := r.scanner.ConnectVerify(hostResult.IP, hostResult.Ports) verifiedResult.SetPorts(hostResult.IP, results) }(hostResult) } - r.scanner.ScanResults = verifiedResult - swg.Wait() + + r.scanner.ScanResults = verifiedResult } func (r *Runner) BackgroundWorkers(ctx context.Context) { @@ -817,6 +836,10 @@ func (r *Runner) handleHostPort(ctx context.Context, host string, p *port.Port) open, err := r.scanner.ConnectPort(host, p, time.Duration(r.options.Timeout)*time.Millisecond) if open && err == nil { r.scanner.ScanResults.AddPort(host, p) + // ignore OnReceive when verification is enabled + if r.options.Verify { + return + } if r.scanner.OnReceive != nil { r.scanner.OnReceive(&result.HostResult{IP: host, Ports: []*port.Port{p}}) } @@ -911,6 +934,12 @@ func (r *Runner) handleOutput(scanResults *result.Result) { output string ) + if r.options.Verify { + for hostResult := range scanResults.GetIPsPorts() { + r.scanner.OnReceive(hostResult) + } + } + // In case the user has given an output file, write all the found // ports to the output file. if r.options.Output != "" { diff --git a/pkg/runner/validate.go b/pkg/runner/validate.go index 84f17c25..73436fa2 100644 --- a/pkg/runner/validate.go +++ b/pkg/runner/validate.go @@ -35,6 +35,11 @@ func (options *Options) ValidateOptions() error { return errNoInputList } + if (options.WithHostDiscovery || options.OnlyHostDiscovery) && options.ScanType != SynScan { + gologger.Warning().Msgf("host discovery requires syn scan, automatically switching to syn scan") + options.ScanType = SynScan + } + // Both verbose and silent flags were used if options.Verbose && options.Silent { return errOutputMode diff --git a/pkg/scan/scan.go b/pkg/scan/scan.go index dc6945a0..cef17a4f 100644 --- a/pkg/scan/scan.go +++ b/pkg/scan/scan.go @@ -17,6 +17,7 @@ import ( "github.com/projectdiscovery/naabu/v2/pkg/port" "github.com/projectdiscovery/naabu/v2/pkg/protocol" "github.com/projectdiscovery/naabu/v2/pkg/result" + "github.com/projectdiscovery/naabu/v2/pkg/utils/limits" "github.com/projectdiscovery/networkpolicy" "golang.org/x/net/proxy" ) @@ -158,7 +159,7 @@ func NewScanner(options *Options) (*Scanner, error) { } if options.Proxy != "" { - proxyDialer, err := proxy.SOCKS5("tcp", options.Proxy, auth, &net.Dialer{Timeout: options.Timeout}) + proxyDialer, err := proxy.SOCKS5("tcp", options.Proxy, auth, &net.Dialer{Timeout: limits.TimeoutWithProxy(options.Timeout)}) if err != nil { return nil, err } @@ -375,7 +376,7 @@ func (s *Scanner) ConnectPort(host string, p *port.Port, timeout time.Duration) conn net.Conn ) if s.proxyDialer != nil { - ctx, cancel := context.WithTimeout(context.Background(), timeout) + ctx, cancel := context.WithTimeout(context.Background(), limits.TimeoutWithProxy(timeout)) defer cancel() proxyDialer, ok := s.proxyDialer.(proxy.ContextDialer) if !ok { diff --git a/pkg/utils/limits/rate.go b/pkg/utils/limits/rate.go new file mode 100644 index 00000000..8820dcd1 --- /dev/null +++ b/pkg/utils/limits/rate.go @@ -0,0 +1,5 @@ +package limits + +func RateLimitWithProxy(rateLimit int) int { + return rateLimit / 2 +} diff --git a/pkg/utils/limits/timeout.go b/pkg/utils/limits/timeout.go new file mode 100644 index 00000000..9d3a8d36 --- /dev/null +++ b/pkg/utils/limits/timeout.go @@ -0,0 +1,7 @@ +package limits + +import "time" + +func TimeoutWithProxy(timeout time.Duration) time.Duration { + return timeout * 2 +}