_______ __ _ _______ _______ _______ __ __
| || | | || || || || | | |
| _____|| |_| || _ || _ || _ || |_| |
| |_____ | || | | || | | || |_| || |
|_____ || _ || |_| || |_| || ___||_ _|
_____| || | | || || || | | |
|_______||_| |__||_______||_______||___| |___|
V0.1
"Amy, technology isn't intrinsically good or evil. It's how it's used. Like the Death Ray."
-Professor Farnsworth
Welcome to Snoopy; a distributed tracking and profiling framework. Snoopy is a work in progress, so please feel free to submit suggestions and/or corrections. This document outlines basic usage. To understand the background a little more, have a look at the following:
- Snoopy: A distributed tracking and profiling framework
- ZaCon4 - Glenn Wilkinson - Terrorism, tracking, privacy and human interactions
- INTRODUCTION AND OVERVIEW ============================= Snoopy consists of four components:
- Client software (aka Snoopy Drone software)
- Server software
- Web interface
- Maltego transforms
The client side software runs on what we call "Drones". A Drone can be any Linux based device that has a WiFi interface (with injection drivers) and outbound internet connectivity. Snoopy has been tested on a Nokia N900 and a laptop running BackTrack. The Drones perform the following two operations:
- Collect Probe SSIDs from nearby wireless devices
- Offer a Rogue Access Point for nearby wireless devices to connect to
Collected probe requests (e.g. Bob's iPhone looking for BTHomeHub-4123) are uploaded to the Snoopy server at regular intervals. All devices that associate to the Rogue AP have have their Internet served via the Snoopy Server.
The server populates all probe requests into a database, and uses Wigle to determine GPS coordinates, and Google Maps to determine street addresses (and street view photographs). This means that if you're probing for your home network, I may get a photograph of your house.
Each Drone connects to the server over OpenVPN, and has its own subnet. Associated clients receive an IP address from the Drone, and route traffic via it. This means that on the server we can match client IP addresses (and therefore MAC addresses) to internet activity.
On the server, the following happens:
- Internet traffic is transparently proxied through Squid, which logs all requests to MySQL
- SSLStrip attempts to rewrite webpages without HTTPS
- mitmproxy.py allows arbitrary injection into web pages
- Various scripts run to extract Social Media data (e.g. pulling Facebook profiles)
The network diagram looks like so:
Client1 Drone1 Snoopy Server
+----------+ +-----------------------+ +-----------------------+
| wlan0-|<---WiFi--->|-at0 | | eth0|<-squid-sslstrip-mitmproxy->Internet
| | | | 10.2.0.1 | | 11.22.33.44| |
| dhclient | | | | | | Traffic inspection
| | | | tap0-|<-openvpn----->|-tap0 | Social media analysis
+----------+ | | 192.168.42.2 | +--/| 192.168.42.1 |
10.2.0.2 | +-----------------------+ | +-----------------------+
| |
| | route 10.2.0.0 via 192.168.42.2
| | route 10.3.0.0 via 192.168.42.3
Client2 | |
+----------+ | |
| wlan0-|<---+ |
| | |
| dhclient | |
| | |
+----------+ |
10.2.0.3 |
|
|
|
Client3 Drone2 |
+----------+ +-----------------------+ |
| wlan0-|<---WiFi--->|-at0 | |
| | | | 10.3.0.1 | |
| dhclient | | | | |
| | | | tap0-|<-openvpn--+
+----------+ | | 192.168.42.3 |
10.3.0.2 | +-----------------------+
|
|
|
Client4 |
+----------+ |
| wlan0-|<---+
| |
| dhclient |
| |
+----------+
10.3.0.3
Walter wrote a web interface for Snoopy. It can be accessed from http://your-snoopy-server.com:5000/
Several Maltego transforms exist to graphically explore collected data (see below for more info).
-
INSTALLATION ================ Server installation should be straight forward. It's only been tested on a stock install of Ubuntu 12.04 LTS 32bit. Changes are made to several server components, so it's highly recommended to run the install script on a base installation, and not run much else on that box (if anything). If in doubt, go through the install.sh file and manually make the changes. Otherwise, just run (./install.sh) the installer.
-
USAGE ======== Once installation is finished you should just be able to type 'snoopy' for the server menu to load. If not (or in doubt) go to the home directory of the user created during the installation phase. Inside the 'snoopy/server/' directory there is a 'snoopy.sh' file which you may run. Below is the menu:
+---------------------------------------------------------------+ | Welcome to Snoopy V0.1 | | SERVER SIDE | | | | SensePost Information Security | | research@sensepost.com / www.sensepost.com | +---------------------------------------------------------------+ Date: Thu Nov 1 16:37:08 CET 2012 Snoopy Server Status: Stopped Connected Drones: 0 Wigle User: setYourWigleAccount Would you like to: [1] (Re)Start Snoopy server components [2] Stop Snoopy server components [3] Manage drone configuration packs [4] Configure server options [5] Set web traffic injection string [6] Observe logs [X] Exit [?] Help
-
Creating drone packs Option [3] in the menu will allow you to create client side 'packs' for your Drone devices. Each Drone gets its own OpenVPN and SSH keys, DHCP ranges, and routing tables. You will be provided with a download URL per Drone device. Make sure your server and drone have their time set correctly or the VPN connection will not establish.
-
Installing and Running Snoopy on the Drone You may have up to 100 drones (if you want more, check the source or email me, there's no actual limitation). Installation consists of downloading the configuration pack from the previous step, and running the relevant setup script. For the Nokia N900 an icon will be placed on your Desktop. e.g.:
haxor@drone001# wget http://snoopy-server.com/secretdir/drone001.tar.gz haxor@drone001# tar xzvf drone001.tar.gz haxor@drone001# cd snoopy && ./setup_n900.sh
-
Looking up SSID Locations Create an account on www.wigle.net, and set your credentials via 'Configure server options'
-
Web Interface You can access the web inteface via http://your-snoopy-server:5000/. You can write your own plugins to traverse and display data. Walter's made is easy for you (check the appendix to this document).
-
Exploring Data with Maltego In the Snoopy server menu go to 'Configure Server Options' > 'Maltego'. Here you will see URLs for downloading Snoopy entities, machines, and URLs for transforms. In order to use Maltego transforms you will need to:
- Add Snoopy entities to Maltego
- Create an account on http://cetas.paterva.com/TDS/
- Login to cetas.paterva.com/TDS/
- Create a seed on cetas.paterva.com/TDS/
- Add the transform URLs to the created seed
- Add the seed in Maltego (Manage > Discover Transforms (Advanced)
- Enter the name as 'Snoopy', and the seed URL as your seed
- Add the Snoopy machines to the machines section
Each Snoopy entity can have different transforms applied to it. Drag the 'Snoopy' entity on to your graph to get started. If you don't specify a start or end date in the entities properties it will fetch results for the last 5 minutes by default (this value can be changed in the server configuration menu).
The Snoopy machines allow you to automatically sequence transforms, and filter/delete nodes based on requirements. The source/comments should sufficiently outline how they work.
-
LEGAL CONSIDERATIONS ======================= All or some of the Snoopy components may be illegal where you live. Please find out before using the software. In the United Kingdom the probe collection component is legal due to the broadcast nature of the traffic. However, the rogue access point component is most likely illegal in most regions. SensePost takes no responsibility for you getting into trouble from using this tool.
-
SECURITY CONSIDERATIONS ========================== Each 'Drone pack' contains OpenVPN and SSH keys. If a Drone is compromised (by theft or otherwise) it may pose a security risk to your server. It is highly recommended that your Snoopy server run dedicated in its purpose. The user created on the server has the following automatically added to the .ssh/authorized_hosts file, for a little bit of extra security:
"no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="/usr/bin/rsync ${SSH_ORIGINAL_COMMAND#* }""
-
FUTURE WORK =============== There are lots of thing still to be done / added. This version is rather PoC.
- Integrate ToR support
- Add filters to easily add other traffic captures (e.g. mDNS)
- Incorporate aGPS hacking (since we already control victims DNS)
- Evilgrade
- Bluetooth/GSM tracking
- WiFi deauth / 3G jamming
- Camera with facial identification
- Stolen cookie Firefox plugin loader
- Replace data upload process (currently all drones rsync with the same user).
- KNOWN ISSUES / BUGS ======================
- SSIDs with unusual characters may cause trouble
- Currently all probe requests are captured and populated into a db. The db gets large rather quickly, especially in busy areas. The database should be normalized, and a decision on whether to keep all probes or not made.
- Originally the probe sniffing was done with Scapy, but replaced with a tshark one liner (due to Scapy's inability to read 802.11 signal strength parameter). A discovered caveat with the old version of tshark available on the N900 is that it does not support outputting the epoch time, only the local time. This messes badly with timezones. If you could compile a new tshark for the N900 that'd be great (here's looking at you PwnieExpress). Point being, make sure your server/drones are all in the same timezone for now.
- CONTACT ============== The code was written by Glenn (with the exception of Walter's web interface). You can email him via glenn@sensepost.com or bug^H^H^H follow him on Twitter: @glennzw. Glenn's not a developer, and apologies for his poor code. He's a hacker, and this tool let him hack you.
Thanks for help/advice/input from:
- The SensePost crew (cool place to work).
- DocScrutinizer, and the rest of the #maemo gang on Freenode for N900 help.
Q. We know that a foreign spy arrives at Heathrow on the 11th November, but we don't know when or on which flight. Our intel suggests he will stay at the Hilton after arriving, and catch a flight from Luton airport on the 14th (again we don't know what time or destination). He is a master of disguise. How can we identify him?
A. Deploy Snoopy drones at Heathrow, Hilton, and Luton. The 'CommonLocation' Maltego transform will note the intersection of all devices present at those three locations. Hopefully only one result - our human target. Once discovered, we can examine Google maps and street view photographs of where our spy has travelled to. His identify could be revealed if his device(s) are tricked into connecting to the Snoopy rogue access point (such as his Facebook, Twitter, or email).
Ask Snoopy to note all individuals who have connected to a WiFi spot in certain sandy^W undesirable countries.
Deploy Snoopy in your 10 department stores. Note human traffic, repeat customers, types of customers.
Inject malicious code to take over client devices and install malware. Exploits can be fired directly from the server to connected victims, due to routing tables.
TFL could deploy a Snoopy Drone in each London Underground. They could monitor human traffic, noting peak and trough times/days, and assign/reduce staff accordingly.
Deploy 500 Snoopy Drones all over London. Monitor people's movements when they pass by a Drone. Interesting human movement patterns are sure to manifest if applied over weeks/months.
For a Linux based Desktop/Laptop, the Alfa AWUS036H card performs average. A more reliable card is the Ubiquity SR-71. Any feedback on what works/doesn't work for you in terms of injection driver support would be appreciated.
For the N900, you will notice that the loading of injection drivers severely reduces the battery life. The TecNet 6600mAh battery pack gave around 6-8 hours in testing. You will, however, need an adapter to plug the N900 into any battery pack. Reducing (or disabling) the GPS polling frequency will also better serve battery life.
Tips on connecting your N900 to your laptop via USB (for the purpose of SSH) can be found here
I'm currently testing on the RaspberryPi, Alfa R36 mini AP, and SheevaPlug. Results to follow.
You can create your own Maltego transforms to explore collected data. The ones supplied are mostly to demonstrate what can be done. Check the source code, and go read:
- http://www.paterva.com/web6/documentation/developer.php
- http://www.paterva.com/web6/documentation/developer-tds.php
Contact glenn@sensepost.com if you have any queries (or ask the awesome Maltego guys).
The web ui code is accessible via ~user/snoopy/server/bin/snoopy/src/snoopy/
Plug-ins consist of two parts:
- Back-end (data providing) part, written in Python
- Front-end (displaying) part, written in JavaScript (optional)
A plug-in is a callable that is dynamically loaded by the Snoopy application. Let's start with an example:
from snoopy import db, pluginregistry
@pluginregistry.add('client-data', 'ssidlist', 'SSID List', js='/static/js/ssidlist.js')
def ssid_list(mac):
with db.SessionCtx() as session:
query = session.query(
distinct(db.Probe.probe_ssid) # SELECT DISTINCT probe_ssid FROM probes
).filter_by(
device_mac=mac # WHERE device_mac=$mac
).order_by(
db.Probe.probe_ssid # ORDER BY probe_ssid
)
return query.all()
Now for the blow-by-blow...
from snoopy import db, pluginregistry
We need db
to access the Snoopy database and pluginregistry
to register our
plug-in.
@pluginregistry.add('client-data', 'ssidlist', 'SSID List', js='/static/js/ssidlist.js')
This is how we register our plug-in (which can be any callable). The first
argument specifies the name of the group that this plug-in falls into. We
specified client-data
, since this plug-in accepts a MAC address and returns
data to be displayed in a client data window. Apart from client-data
, there
is also the session-data
group of plug-ins that operate on proximity
sessions. The second parameter is the plug-in name. This name is for internal
use only and should be JSON-friendly. The third parameter is the plug-in title.
Essentially it is the same as the name, but the title is displayed in the GUI.
More specifically, this is the title of the data section in the client data
window.
All keyword arguments after the title are saved as options. While the plug-in
system does not require any options, Snoopy supports the js
option. This
option specifies the URL (from the browser side, not from Snoopy's/the
server's side) of the JavaScript component of this plug-in.
def ssid_list(mac):
This plug-in is a simple function. It accepts a MAC address string, as
per client-data
plug-ins' definition. The name of the callable is not used.
The body of this example plug-in simply performs a SQLAlchemy query that
basically does SELECT DISTINCT probe_ssid FROM probes WHERE device_mac=$mac
and returns the results as a list. The return values of plug-ins are usually
added as part of a JSON response. Therefore the results has the limitation that
it must be JSON-friendly (as supported by Flask's jsonify()
function).
As simple as that!
Front-end plug-ins for client data are referred to as client data handlers.
They are registered via the Snoopy.registerPlugin(sectionName, dataHandler)
function. sectionName
is the name of the data section that the data handler
wants to handle. This name is the same as the back-end plug-in name that
generated the data. The dataHandler
must be a function with the following
signature: function($section, clientData) {...}
. $section
is a jQuery
object of the div element where the data handler may display data or affect
changes. The client data (generated by the back-end plug-in) is given in the
clientData
parameter.
Since the data handler's only allowed output is changes to the given div
($section
), no return value is necessary.