Go back

VulnCheck go-exploit Goes Scanless

avatar
Jacob Baines@Junior_Baines

go-exploit is VulnCheck’s open-source exploit development framework. Besides exploitation and c2 primitives, the framework features built-in asset detection and version scanning capabilities. A recent update to go-exploit allows for the exploits to share information across runs. This makes go-exploit the only exploit framework to scan HTTP targets without ever connecting to them!

The security industry puts a lot of effort into internet scanning. Our friends over at GreyNoise track almost 100 different industry “actors” that scan the internet. There are countless others that stand up their own Tenable, Nuclei, Metasploit, etc. and scan, without attribution, from Amazon, Digital Ocean, and more. go-exploit was always intended to fall within this mass-scanning category too.

But now, go-exploit, using the exact same code for active scanning, supports scanless asset detection and version scanning. To see how that works, let’s find all the internet-facing Atlassian Confluence servers vulnerable to CVE-2023-22527. To start, let’s say we agree on this Shodan query for Confluence.

Confluence on Shodan

How can we quickly determine which servers in the query are vulnerable? Tenable Nessus has a version scanner for this CVE, but the thought of configuring Nessus and scanning thousands of hosts is about as appealing as lying in a coffin full of scorpions. Nuclei has a template! But running it against internet-hosts is bordering on a criminal act. Scanless go-exploit sounds downright pleasant compared to those two.

Step 1: Convert a Shodan Query into a Database

Our first step is to convert the Shodan query into something go-exploit can understand. go-exploit-cache can convert a Shodan gzip file into a go-exploit database. All we have to do is download the data from Shodan and pass it to go-exploit-cache. We’ve provided a sample of that data here, and you can use it with go-exploit-cache like so:

albinolobster@mournland:~/go-exploit-cache$ ./build/go-exploit-cache -type shodan-gzip -in ./test/testdata/shodan-confluence.json.gz -out confluence.db
2024/07/19 14:37:36 Decompressing the Shodan GZIP... this can be slow
2024/07/19 14:37:37 Decompressed file written to .tmp/shodan.json
2024/07/19 14:37:37 Generating database entries...
albinolobster@mournland:~/go-exploit-cache$

go-exploit-cache produces an sqlite database that is consumable by go-exploit. If you open up the database, you can find the cached HTTP responses in the http_cache table:

albinolobster@mournland:~/go-exploit-cache$ sqlite3 confluence.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> select rhost,rport from http_cache limit 10;
52.207.194.59|80
52.200.210.54|80
135.181.36.116|443
122.152.230.161|8090
31.148.148.9|443
65.203.128.117|8443
85.184.249.239|443
129.241.14.197|443
158.160.120.182|443
52.34.139.174|443
sqlite> select count(*) from http_cache;
2313
sqlite>

Step 2: Grab a go-exploit Scanner

Now that we’ve converted the Shodan Confluence query into a database, we need a go-exploit scanner. Fortunately, VulnCheck published three exploits for CVE-2023-22527 on GitHub back in March, all of which have asset detection and version scanning built in. We can grab any of them and run a scanless version check using the generated database.

Step 3: Run go-exploit against your target hosts

In the following, we use the first entry listed in the database above (52.207.194.59:80) and use unshare -n to demonstrate that go-exploit doesn’t require network access.

albinolobster@mournland:~/cve-2023-22527/reverseshell$ sudo unshare -n ./build/cve-2023-22527_linux-arm64 -c -v -rhost 52.207.194.59 -rport 80 -db ~/go-exploit-cache/confluence.db
time=2024-07-19T15:06:11.519-04:00 level=STATUS msg="Starting target" index=0 host=52.207.194.59 port=80 ssl=false "ssl auto"=false
time=2024-07-19T15:06:11.519-04:00 level=STATUS msg="Validating Confluence target" host=52.207.194.59 port=80
time=2024-07-19T15:06:11.531-04:00 level=SUCCESS msg="Target verification succeeded!" host=52.207.194.59 port=80 verified=true
time=2024-07-19T15:06:11.531-04:00 level=STATUS msg="Running a version check on the remote target" host=52.207.194.59 port=80
time=2024-07-19T15:06:11.532-04:00 level=VERSION msg="The reported version is 7.19.17" host=52.207.194.59 port=80 version=7.19.17
time=2024-07-19T15:06:11.542-04:00 level=STATUS msg="The target appears to be a patched version." host=52.207.194.59 port=80 vulnerable=no

Above you can see the scanner validated the target as Atlassian Confluence, extracted a version number (7.19.17), and determined the host is using an unaffected version. All that without ever connecting to the host! The scanner also updated the verified table:

albinolobster@mournland:~/go-exploit-cache$ sqlite3 confluence.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> select * from verified;
1|1721417205|Confluence|1|7.19.17|52.207.194.59|80
sqlite>

Go Scanless Across Multiple Hosts

But that’s just one target out of a couple thousand entries in the database. To scan all of the database, you can just loop over all rows in the http_cache table. VulnCheck has an inhouse tool called db-scanner that does this. Below we use time to demonstrate how quickly a scanless version scan can analyze all the hosts.

albinolobster@mournland:~/initial-access/tools/db-scanner$ time sudo ./build/db-scanner -db ~/go-exploit-cache/confluence.db -scanners ~/cve-2023-22527/reverseshell/build/ -logfile conflue
nce.log

real    0m8.335s
user    0m3.154s
sys     0m3.123s

After 8 seconds, we have results for all entries in the database / Shodan query. We can quickly grep the log file for results.

albinolobster@mournland:~/initial-access/tools/db-scanner$ cat confluence.log | grep "vulnerable=yes" | wc -l
56
albinolobster@mournland:~/initial-access/tools/db-scanner$ cat confluence.log | grep "vulnerable=no" | wc -l
2114

And, of course, the database also stores all the details.

sqlite> select * from verified limit 10;
1|1721417427|Confluence|1|7.19.17|52.200.210.54|80
2|1721417427|Confluence|1|7.19.16|135.181.36.116|443
3|1721417427|Confluence|1|7.19.17|52.207.194.59|80
4|1721417427|Confluence|1|8.5.3|122.152.230.161|8090
5|1721417427|Confluence|1|8.9.1|31.148.148.9|443
6|1721417427|Confluence|1|8.9.1|65.203.128.117|8443
7|1721417427|Confluence|1|7.19.18|85.184.249.239|443
8|1721417427|Confluence|1|8.9.3|129.241.14.197|443
9|1721417427|Confluence|1|8.5.5|158.160.120.182|443
10|1721417427|Confluence|1|7.19.19|52.34.139.174|443

So when a new emergent Confluence vulnerability comes out (like it does every quarter), we will be able to say who / how many are vulnerable within seconds. Very useful!

A Real World Example of Going Scanless w/ go-exploit

We don’t have to limit ourselves to just one CVE or product though. Consider the following query that covers Northeastern University.

Northeastern on ShodanNortheastern on Shodan

Northeastern has thousands of hosts/assets on their networks, but it's difficult to say what exactly they are from this view. By converting this query into a go-exploit cache database and pushing them through the scanners VulnCheck from our Initial Access Intelligence offering, we are able to passively identify hundreds of assets, their versions, and what they are vulnerable to (including at least one unauthenticated remote code execution issue). Here is a small sample from the resulting verified table:

sqlite> select * from verified where installed = 1 order by id desc limit 10;
264875|1721415612|XWiki|1|13.10.8|155.33.23.90|443
230005|1721413745|ASUS|1||129.10.132.218|8443
223128|1721413373|Tinyproxy|1|1.8.2|155.33.213.146|8080
223057|1721413370|Tinyproxy|1|1.8.2|129.10.14.218|8080
221645|1721413311|Tinyproxy|1|1.8.2|129.10.73.222|8080
221337|1721413298|ownCloud|1||129.10.115.142|443
153259|1721410531|PaperCut NG/MF|1|66961|155.33.36.94|443
109011|1721409204|Confluence|1|8.5.12|129.10.117.205|443
66874|1721408317|Grafana|1||129.10.134.74|3000
64903|1721408289|Apache HTTP Server|1|2.4.59|129.10.111.148|80

go-exploit-cache also supports converting a PCAP into a cache database. We deliver PCAPs with our exploits to all Initial Access customers, so they are also able to test the scanners asset detection and version scanning logic without configuring a target themselves. Once again, we provided a Confluence sample in the go-exploit-cache repository. You can test it like so:

albinolobster@mournland:~/go-exploit-cache$ ./build/go-exploit-cache -type pcap -in ./test/testdata/confluence-exploit.pcapng -out confluence.db
2024/07/23 10:45:21 Locating all HTTP requests...
2024/07/23 10:45:21 Locating all HTTP responses...
2024/07/23 10:45:21 Generating database entries...

The resulting database contains two cached queries:

albinolobster@mournland:~/go-exploit-cache$ sqlite3 confluence.db
SQLite version 3.31.1 2020-01-27 19:55:54
Enter ".help" for usage hints.
sqlite> select rhost,rport,uri from http_cache;
10.9.49.88|8090|/
10.9.49.88|8090|/login.action?os_destination=%2Findex.action&permissionViolation=true

And, of course, our Confluence exploits are able to use this pcap-generated database to do a scanless asset detection and version scan.

albinolobster@mournland:~/cve-2023-22527/reverseshell$ ./build/cve-2023-22527_linux-arm64 -rhost 10.9.49.88 -rport 8090 -db ~/go-exploit-cache/confluence.db -v -c -fll TRACE
time=2024-07-23T10:47:41.284-04:00 level=DEBUG msg="Using the HTTP User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36"
time=2024-07-23T10:47:41.287-04:00 level=STATUS msg="Starting target" index=0 host=10.9.49.88 port=8090 ssl=false "ssl auto"=false
time=2024-07-23T10:47:41.287-04:00 level=STATUS msg="Validating Confluence target" host=10.9.49.88 port=8090
time=2024-07-23T10:47:41.288-04:00 level=TRACE msg="HTTP cache hit: http://10.9.49.88:8090/"
time=2024-07-23T10:47:41.289-04:00 level=SUCCESS msg="Target verification succeeded!" host=10.9.49.88 port=8090 verified=true
time=2024-07-23T10:47:41.289-04:00 level=STATUS msg="Running a version check on the remote target" host=10.9.49.88 port=8090
time=2024-07-23T10:47:41.289-04:00 level=TRACE msg="HTTP cache hit: http://10.9.49.88:8090/"
time=2024-07-23T10:47:41.289-04:00 level=VERSION msg="The reported version is 8.5.3" host=10.9.49.88 port=8090 version=8.5.3
time=2024-07-23T10:47:41.290-04:00 level=SUCCESS msg="The target appears to be a vulnerable version!" host=10.9.49.88 port=8090 vulnerable=yes

Scanless makes a lot of sense for both attackers and defenders, and we don’t think there is any other framework that is doing quite what we are doing here. If you find this compelling, come hack with us on go-exploit or check out our Initial Access Intelligence offering.