projectdiscovery / nuclei

Nuclei is a fast, customizable vulnerability scanner powered by the global security community and built on a simple YAML-based DSL, enabling collaboration to tackle trending vulnerabilities on the internet. It helps you find vulnerabilities in your applications, APIs, networks, DNS, and cloud configurations.
https://docs.projectdiscovery.io/tools/nuclei
MIT License
20.35k stars 2.48k forks source link

[BUG] Template scans user-specified port #5546

Closed daffainfo closed 1 month ago

daffainfo commented 2 months ago

Is there an existing issue for this?

Current Behavior

Even though port is already specified in the template, let's say this template /javascript/enumeration/redis/redis-require-auth.yaml. This template will scan port 6379, but if you specified another port in the user input, for example port 110. The template will scan 110 instead of 6379

Expected Behavior

The template should be stopped

DBG]  [redis-require-auth] Javascript Code:

        isPortOpen(Host, Port);

[WRN] [redis-require-auth] Could not execute request for 50.63.14.108:6379: errKind=network-permanent-error [address=50.63.14.108:6379] port closed or filtered; connection refused

Steps To Reproduce

Im using an IP address from shodan

  1. nuclei -t javascript/enumeration/redis/redis-require-auth.yaml -u 50.63.14.108:110 --debug

Relevant log output

% nuclei -t javascript/enumeration/redis/redis-require-auth.yaml -u 50.63.14.108:110 --debug 

                     __     _
   ____  __  _______/ /__  (_)
  / __ \/ / / / ___/ / _ \/ /
 / / / / /_/ / /__/ /  __/ /
/_/ /_/\__,_/\___/_/\___/_/   v3.3.1

                projectdiscovery.io

[INF] Current nuclei version: v3.3.1 (latest)
[INF] Current nuclei-templates version: v9.9.3 (latest)
[WRN] Scan results upload to cloud is disabled.
[INF] New templates added in latest release: 56
[INF] Templates loaded for current scan: 1
[INF] Executing 1 signed templates from projectdiscovery/nuclei-templates
[INF] Targets loaded for current scan: 1
[DBG] [redis-require-auth] Executing Precondition for request
[DBG]  [redis-require-auth] Javascript Code:

        isPortOpen(Host, Port);

[DBG] [redis-require-auth] Precondition for request was satisfied
[DBG] [redis-require-auth] Dumped Javascript request for 50.63.14.108:110:
Variables:
        1. Host => 50.63.14.108
        2. Port => 110 address=50.63.14.108:110
[DBG]  [redis-require-auth] Javascript Code:

        const redis = require('nuclei/redis');
        const isAuthenticated = redis.IsAuthenticated(Host, Port);
        Export(isAuthenticated);

[DBG] [redis-require-auth] Dumped Javascript response for 50.63.14.108:110:
        1. response => true
        2. success => true address=50.63.14.108:110
[redis-require-auth:dsl-1] [javascript] [info] 50.63.14.108:110

Environment

- OS: Mac
- Nuclei: 3.3.1
- Go: 1.22.3

Anything else?

I also found weird case like this, I scanned my own website which is daffa.info with port 443. And the output was something like this:

[DBG]  [redis-require-auth] Javascript Code:

        isPortOpen(Host, Port);

[WRN] [redis-require-auth] Could not execute request for daffa.info:443: errKind=network-permanent-error [address=daffa.info:6379] port closed or filtered; connection refused

As you can see it looks like they scanned port 443 and 6379? And it only happen if I specified port 80 and 443 in my input

dwisiswant0 commented 2 months ago

That's because the value of the Port parameter that's supplied as an argument is hardcoded.

daffainfo commented 2 months ago

@dwisiswant0 so that is the template fault or what? Because it produces a lot of false positive on my end

daffainfo commented 2 months ago

try this command, cc @dwisiswant0

echo '50.63.14.108' | naabu --top-ports 100 | nuclei -t javascript/enumeration/redis/redis-require-auth.yaml

Output:

[redis-require-auth] [javascript] [info] 50.63.14.108:110
[redis-require-auth] [javascript] [info] 50.63.14.108:143
[redis-require-auth] [javascript] [info] 50.63.14.108:139
[redis-require-auth] [javascript] [info] 50.63.14.108:21
[redis-require-auth] [javascript] [info] 50.63.14.108:49154
[redis-require-auth] [javascript] [info] 50.63.14.108:3389
[redis-require-auth] [javascript] [info] 50.63.14.108:135
[redis-require-auth] [javascript] [info] 50.63.14.108:49155
[redis-require-auth] [javascript] [info] 50.63.14.108:49156
dwisiswant0 commented 2 months ago

JavaScript argument is different from a dynamic runtime variable. That stdout you're seeing is the output from variable, so this is expected behavior.

daffainfo commented 2 months ago

@dwisiswant0 huh? but that is a lot of false positive. Should we remove the template or what? How to fix that?

dwisiswant0 commented 2 months ago

That's because the value of the Port parameter that's supplied as an argument is hardcoded.

      Port: "6379"

So, no matter what port value you supply to the engine, it will still try to connect to the port (argument) as (statically) defined in its template.

daffainfo commented 2 months ago

Should we remove the template or what? How to fix that?

@dwisiswant0 But the output looks like this, then how to fix it? I have asked many times but still no answer yet

[redis-require-auth] [javascript] [info] 50.63.14.108:110
[redis-require-auth] [javascript] [info] 50.63.14.108:143
[redis-require-auth] [javascript] [info] 50.63.14.108:139
[redis-require-auth] [javascript] [info] 50.63.14.108:21
[redis-require-auth] [javascript] [info] 50.63.14.108:49154
[redis-require-auth] [javascript] [info] 50.63.14.108:3389
[redis-require-auth] [javascript] [info] 50.63.14.108:135
[redis-require-auth] [javascript] [info] 50.63.14.108:49155
[redis-require-auth] [javascript] [info] 50.63.14.108:49156

The expected result is something like this because 6379 ISNT open

[INF] No results found. Better luck next time!
dwisiswant0 commented 2 months ago

@dwisiswant0 But the output looks like this, then how to fix it? I have asked many times but still no answer yet

Here's your answer - https://github.com/projectdiscovery/nuclei/issues/5546#issuecomment-2295902555

The expected result is something like this because 6379 ISNT open

I see. Do you have any idea why it's connecting to the port from variable instead of argument, @tarunKoyalwar?

dwisiswant0 commented 2 months ago

@daffainfo - can you confirm if you're supplying to the engine without port value to that template, will it connect to the hardcoded Port argument value?

daffainfo commented 2 months ago

@dwisiswant0 yes, youre correct. It will connect to harcoded port value. If i specifed the port in the argument, it will replaces the hardcoded port value

dwisiswant0 commented 2 months ago

Got you. A temporary fix for this issue seems to be changing the property used for hardcoded port values from the JavaScript protocol.

Meanwhile, I'm gonna reopen this issue until we get confirmation from the team.

tarunKoyalwar commented 1 month ago

@daffainfo @dwisiswant0 , this is expected behaviour , if you remember each tcp template had something like

tcp:
  - host:
      - "{{Hostname}}"
      - "{{Host}}:22"

basically nuclei would run it on given address (host:port) and on hardcoded port as well , but later on we simplified it to do this check internally by using Port field which first probes if port is open ( cached as well) and then attempts to run the template https://github.com/projectdiscovery/nuclei/pull/4123

ideal solution would be that templates have service field like service: ssh and nuclei would accept a service discovery ( nmap or something else) input and only run where it is applicable.

but this is more of a long term solution and the current behaviour you are experiencing is expected

@daffainfo current solution is to improve matchers in template so it doesn't produce FP