Skip to content

Commit a34c01e

Browse files
committed
Land rapid7#8137 shodan honeyscore module
2 parents 0092818 + 3d860c2 commit a34c01e

File tree

2 files changed

+148
-0
lines changed

2 files changed

+148
-0
lines changed
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
The `shodan_honeyscore` module utilizes the [Shodan](https://www.shodan.io/) API to determine whether or not a server is a honeypot or not.
2+
When setting the module options, we aren't directly requesting `TARGET`, we are requesting the shodan API to analyze `TARGET` and return a honeyscore from 0.0 to 1.0. 0.0 being `not a honeypot` and 1.0 being a `honeypot`. The original website for the honeypot system can be found here: https://honeyscore.shodan.io/.
3+
4+
#### NOTE:
5+
In order for this module to function properly, a Shodan API key is needed. You can register for a free acount here: https://account.shodan.io/register
6+
7+
## Verification Steps
8+
9+
1. Start `msfconsole`
10+
2. Do: `use auxiliary/gather/shodan_honeyscore`
11+
3. Do: `set TARGET <targetip>`
12+
4. Do: `set SHODAN_APIKEY <your apikey>`
13+
5. Do: `run`
14+
6. If the API is up, you should recieve a score from 0.0 to 1.0.
15+
16+
## Options
17+
18+
**TARGET**
19+
20+
The remote host to request the API to scan.
21+
22+
**SHODAN_APIKEY**
23+
24+
This is the API key you recieve when signing up for a Shodan account. It should be a 32 character string of random letters and numbers.
25+
26+
27+
## Scenarios
28+
29+
Running the module against a real system (in this case, the Google DNS server):
30+
31+
```
32+
msf > use auxiliary/gather/shodan_honeyscore
33+
msf auxiliary(shodan_honeyscore) > options
34+
35+
Module options (auxiliary/gather/shodan_honeyscore):
36+
37+
Name Current Setting Required Description
38+
---- --------------- -------- -----------
39+
SHODAN_APIKEY yes The SHODAN API key
40+
TARGET yes The target to get the score of
41+
42+
msf auxiliary(shodan_honeyscore) > set TARGET 8.8.8.8
43+
TARGET => 8.8.8.8
44+
msf auxiliary(shodan_honeyscore) > set SHODAN_APIKEY [redacted]
45+
SHODAN_APIKEY => [redacted]
46+
msf auxiliary(shodan_honeyscore) > run
47+
48+
[*] Scanning 8.8.8.8
49+
[-] 8.8.8.8 is not a honeypot
50+
[*] 8.8.8.8 honeyscore: 0.0/1.0
51+
[*] Auxiliary module execution completed
52+
```
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
##
2+
# This module requires Metasploit: http://metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class MetasploitModule < Msf::Auxiliary
9+
10+
def initialize(info = {})
11+
super(update_info(info,
12+
'Name' => 'Shodan Honeyscore Client',
13+
'Description' => %q{
14+
This module uses the shodan API to check
15+
if a server is a honeypot or not. The api
16+
returns a score from 0.0 to 1.0. 1.0 being a honeypot.
17+
A shodan API key is needed for this module to work properly.
18+
19+
If you don't have an account, go here to register:
20+
https://account.shodan.io/register
21+
For more info on how their honeyscore system works, go here:
22+
https://honeyscore.shodan.io/
23+
},
24+
'Author' =>
25+
[ 'thecarterb' ], # Thanks to @rwhitcroft, @h00die and @wvu-r7 for the improvements and review!
26+
'License' => MSF_LICENSE,
27+
'References' =>
28+
[
29+
[ 'URL', 'https://honeyscore.shodan.io/']
30+
]
31+
)
32+
)
33+
34+
deregister_options('RHOST', 'SSL', 'DOMAIN', 'DigestAuthIIS', 'NTLM::SendLM',
35+
'NTLM::SendNTLM', 'VHOST', 'RPORT', 'NTLM::SendSPN', 'NTLM::UseLMKey',
36+
'NTLM::UseNTLM2_session', 'NTLM::UseNTLMv2')
37+
38+
register_options(
39+
[
40+
OptString.new('TARGET', [true, 'The target to get the score of']),
41+
OptString.new('SHODAN_APIKEY', [true, 'The SHODAN API key'])
42+
], self.class)
43+
end
44+
45+
def print_score(score)
46+
tgt = datastore['TARGET']
47+
print_status("#{tgt} honeyscore: #{score}/1.0")
48+
end
49+
50+
def run
51+
key = datastore['SHODAN_APIKEY']
52+
53+
# Check the length of the key (should be 32 chars)
54+
if key.length != 32
55+
print_error('Invalid API key (Not long enough)')
56+
return
57+
end
58+
59+
tgt = datastore['TARGET']
60+
print_status("Scanning #{tgt}")
61+
cli = Rex::Proto::Http::Client.new('api.shodan.io', 443, {}, true)
62+
cli.connect
63+
req = cli.request_cgi({
64+
'uri' => "/labs/honeyscore/#{tgt}?key=#{key}",
65+
'method' => 'GET'
66+
})
67+
res = cli.send_recv(req)
68+
cli.close
69+
if res.nil?
70+
fail_with(Failure::Unknown, 'Unable to connect to shodan')
71+
end
72+
73+
if res.code != 200
74+
print_error('Shodan did not respond in an expected way. Check your api key')
75+
return
76+
end
77+
78+
score = res.body.to_f # Change the score to a float to be able to determine value in the checks
79+
80+
if score == 0
81+
print_error("#{tgt} is not a honeypot")
82+
elsif score < 0.4 && score != 0.0
83+
print_error("#{tgt} is probably not a honeypot")
84+
elsif score > 0.4 && score < 0.6
85+
print_status("#{tgt} might be a honeypot")
86+
elsif score > 0.6 && score < 1.0
87+
print_good("#{tgt} is probably a honeypot")
88+
elsif score == 1.0
89+
print_good("#{tgt} is definitely a honeypot")
90+
else # We shouldn't ever get here as the previous checks should catch an unexpected response
91+
print_error('An unexpected error occured.')
92+
return
93+
end
94+
print_score(score)
95+
end
96+
end

0 commit comments

Comments
 (0)