robertdavidgraham / masscan

TCP port scanner, spews SYN packets asynchronously, scanning entire Internet in under 5 minutes.
GNU Affero General Public License v3.0
23k stars 3.02k forks source link

Multiple protocols on one port: example with TLS1.1 & TLS1.2 #728

Closed Frky closed 8 months ago

Frky commented 11 months ago

This PR aims to add the possibility to retry with another protocol when the first one failed. The implemented example is for TLS: if we have an alert when trying TLS 1.1, we want to retry on the same host, port with TLS 1.2.

The result is that the x509 certificate of a server that only supports TLS1.2 will now be successfully grabbed by masscanned (while before it would not have been):

$ sudo ./bin/masscan --banners -p443 -n $targetip
[+] resolving router 192.168.1.1 with ARP (may take some time)...
Starting masscan 1.3.2 (http://bit.ly/14GZzcT) at 2022-08-18 17:33:30 GMT
Initiating SYN Stealth Scan
Scanning 1 hosts [1 port/host]
Discovered open port 443/tcp on [...]                                  
Discovered open port 443/tcp on [...]                                  
Banner on port 443/tcp on [...]: [ssl] TLS/1.2 cipher:0xc030, [...]
Banner on port 443/tcp on [...]: [X509] MIIEPjCCAyagAwIB[...]
Banner on port 443/tcp on [...]: [X509] MIIFLTCCBBWgAwIB[...]
Banner on port 443/tcp on [...]: [X509] MIIHUDCCBjigAwIB[...]
Banner on port 443/tcp on [...]: [ssl]  ALERT(0x0246) 

However, I am not 100% confident this PR does not have important drawbacks on the performances or even if it breaks things, so any review/testing/feedback/suggestion is welcome.

Here is an overview on how it is implemented:

robertdavidgraham commented 8 months ago

This looks really good. I'd like to see this integrated. Right now I'm going through a phase of accepting the 40+ outstanding pull requests, so I don't have time to look at something this complex.

They way I'd intended to solve this was a little different, maybe a linked-list of protocols to iterate over rather than an array. I'm going to have to look at your design more.

Frky commented 8 months ago

I agree, a linked list would be way nicer. I will adapt my PR.

Also, one problem I encountered using this multi-protocols feature is that once we have multiple probes for one port, it is then needed to have a way in the output file (XML/bin/etc.) to know which probe led to which answer. I have an other draft PR (not pushed yet) to add an option --output-probes which adds a field probe=... in the output file. @p-l- has prepared an update of Ivre to support this, but it could break other tools parsing masscan output (although without the --output-probes flag the output would not change). What did you have in mind for that?

robertdavidgraham commented 8 months ago

I have vastly changed the TCP stack in the latest push. It now makes this much easier. To find all the changes, such search for reconnect in the code. I integrated your first proposal from the IVRE branch, and then rewrote most of it.

First of all, a new SYN-cookie isn't needed, so I removed all those parts. Once a new port is selected, a new SYN-cookie is generated automatically. I now default to using 16 source ports, so there should always be a source port available.

I cleaned up the TCP state-machine, so that when you do a "send" of the SYN rather than a "xmit". This means it's been queued up in the TCB, and if it doesn't get a reply, it'll resend the SYN a few times.

I'm setting this up to integrate Lua scripting, so that scripts can likewise open a new TCP connection whenever they like.

I'm going to close this pull request since I've completely redone the TCP stack in the last week. Also, request has actually been accepted, since I pulled it down from the IVRE fork, but it doesn't have anything you've added in the last week.

Go search for "reconnect", especially the _do_reconnect() function.