D-5 (Kersha)w Scripting Wireless Utilities

Download Report

Transcript D-5 (Kersha)w Scripting Wireless Utilities

Scripting Wifi Security Software
Sharkfest 10
Mike Kershaw / Dragorn
Aruba Networks / Kismet
SHARKFEST ‘10
Stanford University
June 14-17, 2010
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Where We're Going
Why we'd script stuff
Scripting Kismet
Writing new tools
Scripting LORCON
Real world tools
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What's the point?
Automation
Alternate interfaces
Logging
(Boring, but useful)
Dynamic alerts
Extremely fast prototype and tool development
Real world security
tools
(Exciting and scary!)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Kismet
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Talking to Kismet
Kismet is pretty easy to script
But no-one seems to
Actually 2 programs – kismet_server and
kismet_client
Talks over standard TCP
And it's even a human-readable protocol, similar
to IMAP
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Where are you?
Kismet listens to port 2501 by default
Talk to it with netcat
Or telnet
Or any other TCP socket tools
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Kismet says “Hi there”
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
*KISMET: 0.0.0 1275891833 DRD1812 tuntap 1000
*PROTOCOLS:
KISMET,ERROR,ACK,PROTOCOLS,CAPABILITY,TERMINATE,T
IME,PACKET,STATUS,PLUGIN,SOURCE,ALERT,BTSCANDEV,D
15D4DEV,WEPKEY,STRING,GPS,BSSID,SSID,CLIENT,BSSID
SRC,CLISRC,NETTAG,CLITAG,REMOVE,CHANNEL,SPECTRUM,
INFO,BATTERY,CRITFAIL
*TIME: 1276050955
*TIME: 1276050956
*TIME: 1276050957
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Kismet sentences
Consist of a *sentence type followed by spacedelimited fields
Fields which contain free-form text are buffered
with \001 bytes
*FOO f1 f2 f3 \001f4 with spaces\001 f5
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Commands
Commands are !ID command parameters
The ID may be incremented or repeating
Kismet will include the ID in responses
Useful for figuring out if a queued command
completed
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Assumptions about you
Kismet assumes some sentences MUST be
handled by the client.
*KISMET, *TIME, *ERROR, *ACK, *PROTOCOLS,
*CAPABILITY, *TERMINATE
This doesn't mean you have to do something
smart
Just that you have to not fail
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Umpteenth normal form
Kismet protocols are vaguely like a normalized
database
When unknown numbers of dynamic records
reference the same data, they are a separate
sentence
F.E. networks are stored as BSSID (primary data)
and SSID (multiple SSID records indexed by
BSSID)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What can you do
Protocol fields are listed using the CAPABILITY
command
Different versions of Kismet may support
different fields, your client can examine this
Clients are expected to handle missing fields
gracefully
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Getting data
Similar to SQL, ALL fields or only SPECIFIC fields
can be requested
Fields may be requested in any order (and will
be returned in that order)
Enabled via the ENABLE command
Client is responsible for handling de-mux of
multiple protocol requests – Kismet will only
listen to the last req
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Initial burst
Kismet tracks things all the time
Clients are only connected sometimes
Non-realtime tracking records are sent in a burst
when a sentence is enabled
F.E. Enabling BSSID will cause Kismet to send all
existing BSSID records
Some protocols don't maintain history
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Down by the delta
Once Kismet has sent the initial burst of old data
New data is sent once per second as it changes
F.E. A BSSID record will be sent every second
while a network is in range
The client is expected to merge this cleanly with
existing known data
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Most useful
*BSSID – Networks seen
*SSID – Network SSID records
*CLIENT – Wireless client records
*GPS – (Obviously) GPS records
*ALERT – Alerts / IDS functions
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Cheap ways to talk
`netcat'
Bash
Sed
Incomprensible but easy
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Talking with bash
echo -e '\n!0 enable channel
channel,packets' | nc localhost 2501 |
awk 'BEGIN { CHN = 0; }; /CHANNEL:/ {
chnum[CHN]=$2; chval[CHN]=$3; CHN=CHN+1;
}; /TIME/ { if (CHN != 0) { printf("[");
for (x = 0; x < CHN; x++) {
printf("{\"id\":%s,\"value\":%s}",
chnum[x], chval[x]); if (x < (CHN-1))
printf(",") } printf("]\n"); CHN=0;
fflush(""); } };'
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Breaking it down
echo -e '\n!0 enable channel
channel,packets'
Send a command to enable the CHANNEL
sentence, with the fields 'channel' and
'packets'
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Breaking it down
nc localhost 2501
Netcat is a great tool for talking to tcp (or UDP)
network hosts from scripts
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Breaking it down
awk 'BEGIN { CHN = 0; }; /CHANNEL:/ {
chnum[CHN]=$2; chval[CHN]=$3;
CHN=CHN+1; }; /TIME/ { if (CHN != 0) …
Awk is a book in itself, but we begin by setting the # of
channels to 0, then when we get the CHANNEL sentence
recording it to an array
When we get the TIME sentence we know we've gotten all
the channels, so we output it
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Breaking it down
printf("["); for (x = 0; x < CHN; x++) {
printf("{\"id\":%s,\"value\":%s}", chnum[x],
chval[x]); if (x < (CHN-1)) printf(",") }
printf("]\n"); CHN=0; fflush(""); } };'
More awk nastiness, basically just iterates
through our array of channels and prints them
At the end, flush the output
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
The result
[{"id":1,"value":75202},{"id":2,"value":28589},{"id"
:3,"value":8613},{"id":4,"value":6042},{"id":5,"va
lue":9890},{"id":6,"value":27937},{"id":7,"value":
19615},{"id":8,"value":8644},{"id":9,"value":76189
5},{"id":10,"value":27690},{"id":11,"value":47546}
,{"id":48,"value":15994},{"id":149,"value":1322071
},{"id":165,"value":1},{"id":28928,"value":1617419
}]
Kismet TCP socket to JSON for an AJAX channel
display in 1 line of shell!
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
How it works
Kismet sends the TIME sentence once per
second, so we can use it for timing
We know if we see a TIME sentence, we've
gotten all the channels Kismet knows about
Normally we'd index by channel #, but this is
hard in awk, so we cheat
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
More intuitive
Ruby interface to Kismet
People seem to like Ruby. I'm not sure I do
If you don't, it's easy to port this to perl, python,
etc – patches welcome!
Committed to SVN already with examples
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Basic API setup
Require 'kismet'
Standard Ruby module
Kis = Kismet.new(host, port)
Defaults to localhost, 2501
Kis.connect
Kis.run
Connect and run as thread
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Subscribing
Kismet.rb allows subscribing to sentences with
callbacks
Callbacks called with a dictionary of fields
returned
Secondary callbacks when a command
completes (more on this soon)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Subscription
kis.subscribe("bssid", ["bssid",
"manuf", "channel"], Proc.new {|*args|
bssidcb(*args)})
Subscribe to a sentence (“bssid”) with a list of
fields, and a callback
Ruby doesn't do function passing per se, so we
use Proc to make a passable block. Bssidcb is
our callback function
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Callback
def bssidcb(proto, fields)
puts "Kismet saw network
#{fields['bssid']} manuf
#{fields['manuf']} on channel
#{fields['channel']}"
end
Callback function with sentence and fields
Fields in hash indexed by name
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Ack callbacks
Called when command completes
When requesting a sentence with historical
data, Kismet sends the historical data, then
the ACK
We can use this to trigger that we've gotten the
complete current state
It's a bit of a kluge but...
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Ack to die
def bssiddiecb(text)
$k.kill
exit
end
Ack-cb just calls “exit” - we only want to list the
networks we've seen so far
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Keep on trucking
Kismet.rb runs the network code in a separate
thread
To keep running with subscribed callbacks, call
the 'wait' function
Will wait for the Kismet session to end (either
naturally or via a kill command elsewhere)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What we've made easy
Kismet to Syslog bridge (subscribe to ALERT and
use Ruby logger)
Kismet to JSON
Programmatic handling of rogue networks
Pretty much any arbitrary use of Kismet data
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
LORCON
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
LORCON
Loss Of Radio CONtrol
Writing the same code for different drivers
sucks
Writing the same code for different platforms
sucks
Hopefully LORCON doesn't suck
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
LORCON2
Unfortunately, LORCON kind of sucked
LORCON2 API much cleaner
Designed to match the libpcap API
Really easy to use
C, Ruby API, Python under development
http://802.11ninja.net
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Super simple
Automatically determines the type of card
Automatically creates injection VAPs
Supports sniff, inject, or sniff+inject where
possible
Send arbitrary bytes OR use the packet
assembly API
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
It's even easy in C
lorcon_driver_t *dri;
lorcon_t *ctx;
uint8_t packet[...];
dri = lorcon_auto_driver(“wlan0”);
ctx = lorcon_create(“wlan0”, dri);
lorcon_open_injmon(ctx);
lorcon_set_channel(ctx, 6);
lorcon_send_bytes(ctx, sizeof(packet), packet);
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
And it comes with ruby
require "Lorcon2"
pp Lorcon.version
pp Lorcon.drivers
pp Lorcon.find_driver("mac80211")
pp Lorcon.auto_driver(“wlan0”)
tx = Lorcon::Device.new(intf)
tx.openinjmon()
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Goal: Simplicity
There's a lot of weird modes you can put a card
in
Most of the time you just want inject+monitor
Most of the time you just want to send bytes
And it'd be nice if it worked like pcap
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Pcap + Lorcon
def safe_loop(wifi)
@q = Queue.new
reader = Thread.new do
wifi.each_packet {|pkt| @q << pkt }
end
Some TLC needed (see test.rb in Lorcon) but we
integrate with each_packet
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Simple in C, too
void apitest_packet_hdlr(lorcon_t
*context, lorcon_packet_t *packet,
u_char *user) { ... }
dri = lorcon_auto_driver(interface);
ctx = lorcon_create(interface, dri)
lorcon_open_injmon(ctx)
lorcon_loop(ctx, 0, apitest_packet_hdlr,
NULL);
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Modeled on pcap_loop
Lorcon handles pcap internals (if you want it to)
lorcon_loop calls the provided function for each
packet
Easy access to dot3 via lorcon_packet_to_dot3
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Building packets
In Ruby, Racket handles most of the packet
assembly duties
There are other packet builders too
But a lot of them are REALLY REALLY slow
Orders of magnitude slower
No great dot11 generator, but Lorcon can
translate dot3 automatically
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Racket L2 – Looks like ether
response = Racket.new
response.l2 = Ethernet.new("01234567890123")
response.l2.dst_mac = eth.src_mac
response.l2.src_mac = eth.dst_mac
response.l2.ethertype = 0x0800
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Racket L3
response.l3 = IPv4.new
response.l3.src_ip = ip.dst_ip
response.l3.dst_ip = ip.src_ip
response.l3.protocol = ip.protocol
response.l3.ttl = ip.ttl
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
+ Lorcon
injpkt = Lorcon::Packet.new()
injpkt.dot3 = response.pack
injpkt.bssid = pkt.bssid
injpkt.direction =
Lorcon::Packet::LORCON_FROM_DS;
tx.inject(injpkt) or puts
"Failed to inject: " + tx.error
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Lorcon Packet Forge
Packet assembly made easy for 802.11
Uses a linked list of temporary data
Packets can be manipulated/appended at will
Exported into an array for transmit
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
LCPF notes
Lcpa_foo – Lorcon Packet Assembly, basic
functions for manipulating packets
Lcpf_foo – Lorcon Packet Forge, packet creation
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Building with LCPF
metapack = lcpa_init();
tx80211_initpacket(&txpack);
lcpf_randmac(sourcemac, 1);
lcpf_randmac(bssidmac, 1);
lcpf_80211headers(metapack, WLAN_FC_TYPE_DATA,
WLAN_FC_SUBTYPE_DATANULL, 0x02, /* fcflags, FromDS */
0x00, /* duration */, targetmac, bssidmac, sourcemac,
NULL, /* addr4 */ 0, /* Fragment number */, 0); /*
Sequence number */
lcpa_freeze(metapack, &txpack);
stuff();
lcpa_free(metapack);
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What can we do now?
Kismet + Lorcon + Ruby
Selective interaction with networks
“Aggresssive” IDS attacking rogue networks in
your building
“Renderman friendly network decloak” … Send a
probe req to a SSID w/ suspected names, let
Kismet decloak response
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Putting it in the real world
(AKA “the fun part of the talk”)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Putting this in the real world
Not a bunch of teenagers on MTV
Already part of Metasploit
LORCON + Ruby + MSF
220 lines of code
All scripting code (native Ruby)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
The inspiration
Wifi session hijacking
About 5 years ago, Airpwn was debuted by
Toast at Defcon
TCP stream hijacking on 802.11
Everyone forgot about this...
Not just for shock porn!
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Corps of Engineers
Rerouting TCP streams
“Ye Olde” 1990 shared media attack
TCP is only “secure” against hijacking because
the seq/ack numbers are random
I see your seq/ack over wireless
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Anatomy of a Session
Handshake (syn/synack/ack)
Client-> Server
“GET /foo HTTP/1.0”
Seq 123 Ack 0
Server-> Client
“HTTP headers, content”
Seq 10 ack 189
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What it takes
Lets add this to MSF
LORCON + Lorcon-Ruby wrapper
Racket (Ruby packet creator)
Ruby-PCAP
A little TLC
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
An evil session
Handshake
Client->Server (GET)
MSF <-Client (Hijack data)
MSF <-Client (FIN!)
Server <-Client (Real data, ignored)
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
In action
msf > use auxiliary/spoof/wifi/airpwn
msf auxiliary(airpwn) > set INTERFACE alfa0
INTERFACE => alfa0
msf auxiliary(airpwn) > set RESPONSE "Airpwn MSF!"
RESPONSE => Airpwn – MSF!
msf auxiliary(airpwn) > run
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Results
msf auxiliary(airpwn) > run
[*] AIRPWN: Response packet has no HTTP
headers, creating some.
[*] Auxiliary module execution completed
msf auxiliary(airpwn) >
[*] AIRPWN: 10.10.100.42 ->
208.127.144.14 HTTP GET
[/files/racket/src/doc/] TCP SEQ
542050816
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
And because it's Ruby
Fine tuning in YAML
Regex matching
Dynamic content generation
File injection or fragment in runtime
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Step 3: Profit
What does all this get us?
Arbitrary HTTP content replacement
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Or in other words
Full control of the DOM
Control over forms
Control over the browser environment
Access to anything in the security context of the
hijacked website
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Obviously scripted
So we can replace content
Big deal, what now?
Nearly every web-2.0-y site uses gobs of
background javascript
What happens if we replace one of those?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
It's not news, it's JS
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Fragments of JS
Especially attractive as a target
Totally invisible to the user
Multiple requests = multiple opportunies to land
attack
Run in same privilege domain as web page
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
I'm in your browser
… Rewriting your DOM
DOM – Document Object Model
Programmatic representation of page content
Once we're in the DOM we can anything
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
It's not stupid, it's advanced
var embeds =
document.getElementsByTagName('div');
for(var i=0; i < embeds.length; i++){ if
(embeds[i].getAttribute("class") ==
"cnnT1Img") { embeds[i].innerHTML = "...";
} else if (embeds[i].getAttribute("class")
== "cnnT1Txt") { embeds[i].innerHTML =
"..."; }}
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
DOM is tasty
What other mischief can we do?
Rewrite all forms to proxy through a logger
Rewrite all HTTPS to HTTP
Poison content topical to a conference?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
HTTP, not so S
var refs =
document.getElementsByTagName('a');
for (var i = 0; i < refs.length; i++){
var rval = refs[i].getAttribute("href");
if (rval == null) { continue; }
refs[i].setAttribute("href",
rval.replace(/^https:/, "http:");
}
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
This really matters
This matters
Like, a lot
No, seriously
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Persistence pays off
Who has read rsnakes VPN paper?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Quick cache
Short version:
Browsers have cache
Cache sticks around
Users don't notice
When I own your TCP session I own your cache
control
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
In control
Client fed spiked JS file
Malicious content
Cache headers say “keep for 10 years”
Malicious file is re-used every time they revisit
the site
From inside their company network!
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Don't think it's a problem?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
What can we do now?
User has spiked, cached file
Browser will re-use it
Iframe attacks? Kaminsky socket/sucket? New
browser exploits?
But a user would NEVER go to twitter at work,
right?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Poison the well
How many sites use Analytics?
Loading urchin.js from the same url?
And what happens if we poison that URL?
For every site loading it
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Calling home to Mom
Cache modified JS that loads content from an
attacker-controlled server
Maybe no good browser vulns this week?
Wait for a browser 0day then flip the switch
Everyone w/ cached callbacks gets owned
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
There are no innocents
No website is “innocent”
Websites that don't ask for logins are just as
capable as feeding the browser exploits
Any website can have browser-owning code
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Well aren't you clever
I'm smart!
I use a VPN!
-orI force my users to use a VPN via UAC
This won't work against me!
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Yeah, but...
Yeah, it wouldn't work...
Except your browser has no concept of security
domains
Something cached in an insecure domain...
Is still cached in a secure domain!
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
“Click OK to agree”
Many hotspots have a landing page to agree to
EULA
Many landing pages are not encrypted
Unencrypted page on an open network? Perfect
target
Now we can feed the user pre-VPN content
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Magic (h)8 ball
If the attacker controls your pre-vpn landing
page
They control your browser
They control what gets loaded
Iframes? Pop-unders? AJAX?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Americas top 40
Attacker hijacks VPN landing page
Injects code to load things over AJAX
Loads the top 40 pages the victim may be likely
to visit in the background
Cache-poison page requested in the background
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Smarter JS
Attacker can examine fetched content
If poison code not present...
Request it again!
We will load your website
And hit it with a brick
We will not run out of bricks
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Frequent landings
Take it one step further
VPN can access internal pages too, right?
We control L2, right?
Soo....
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Dumb Network Stuff
Can we use LORCON to attack other protocols?
Sure can!
Racing DNS isn't hard
Capture query, set QR bit, supply our own
response
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Your intranet is showing
We control DNS
We control page query
We can be sure a request went through
What stops us guessing pages like
http://intranet/ ?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Hint: Nothing
Nothing!
How about some JS that loads the original
intranet content...
Then crawls the DOM and ships it all off to the
attacker via POST?
Or rewrites your form DOMs to proxy out?
SHARKFEST ‘10 | Stanford University | June 14–17, 2010
Summary
Kismet is easy to talk to
LORCON is easy to write for
Open wifi is terrifying
http://www.kismetwireless.net
http://802.11ninja.net
SHARKFEST ‘10 | Stanford University | June 14–17, 2010