Sunday, October 28, 2012

Monitoring GSM Networks with SNORT

Last December, during the annual Computer Chaos Congress, I was testing out OsmocomBB and monitoring the CCC test GSM base stations. It gave me a chance to monitor a GSM network being used in a test environment. Since the network was run by OpenBTS and OpenBSC I expected the network to exhibit some differences to more traditional equipment from Ericsson, Siemens, etc. I wanted to try to fingerprint the differences in GSM equipment in order to detect anomalies to assist in identifying rogue GSM towers and/or  what are often referred to as "IMSI-catchers". Within a few minutes of monitoring I realized I wouldn't be disappointed. The very first thing that caught my eye was this very interesting frame...

  As you can see, this is a normal "Identity Request" message from the cell tower (BTS) to a handset. What is not normal is that the BTS is requesting the IMEI (like a phone serial number). An "Identity Request" message is used in normal networks to ask the phone to identify itself, usually the first time a phone has entered a network or if the phone's temporary ID (TMSI) isn't known to the network for some reason. They're used sparingly on most networks, but exclusively to request the IMSI as far as I've seen. Proper network operators have a very simple system used to get the IMEI of a handset, which is to set a flag in the "Ciphering Mode" message requesting that the IMEI is sent by the phone right after the call begins encryption. Some networks do this for every call, some just a certain percentage of the time, but it is used by network operators for anti-fraud purposes and is supposed to be used to gather the IMEI so the identifier isn't leaked out over unencrypted channels. The only advantage to asking for the IMEI via an "Identity Request" message is that you don't actually have to have access to the authentication data (requested from the home GSM network), whereas to get the IMEI via a "Ciphering Mode" command the BTS has to actually have the relevant authentication and cryptogrpahic data in order to establish an encrypted call with the phone. In short: if you're running an "IMSI-catcher" type device, you're going to probably be using the "Identity Request" method.

  So, with this, I found the first item I could use to help identify BTS systems that were being naughty and trying to collect information about nearby phones. I continued and found other things that aren't likely to be seen in a production network, or at least not commonly. These include:

  • IMEI's being requested or sent in cleartext
  • SMS sent in cleartext
  • Frequent IMSI Identity Request messages 
  • Paging messages using IMSI only
  • Location Services Request (asking the phone where it is)

I took the ideas above, and converted them into SNORT rules. Thanks to the Osmocom team's fantastic work, the output of the tools is a UDP stream which lends itself to being analyzed by SNORT in real-time. This is by no means a comprehensive list of things a naughty BTS might exhibit, but this should help identify one if you've got inclination to look for one. New ideas and rules are welcome.


#Prevent decoding oddities from causing alerts on the GSM frames.
config disable_decode_alerts

#Define the port to monitor for GSMTAP traffic in IP. Default is 4729.
var GSM_PORT 4729

#Suspicious transmissions - IMSI Catcher
alert udp any any -> any $GSM_PORT ( msg: "IMEI request in cleartext - Possible IMSI-catcher!"; content:"|03200d051802|"; offset:16; depth:06; sid:9900001; rev:1; priority:2)

#Suspicious transmissions - IMSI Catcher
alert udp any any -> any $GSM_PORT ( msg: "IMEI sent in cleartext - Possible IMSI-catcher!"; content: "|0559083a|"; offset:19; depth:4; sid:9900002; rev:1; priority:2)

#Suspicious transmissions - IMSI Catcher? Unencrypted network?
#TODO: Fix this - too many false positives due to fragmented data
#alert udp any any -> any $GSM_PORT ( msg: "SMS transmission in cleartext - security failure"; content:"|0d00|"; offset:0; content:"|01|"; distance:2; within:1; sid:9900003; rev:1; priority:3; tag:session,6,packets;)

#Low-priority, normal traffic - SMS
#alert udp any any -> any $GSM_PORT ( msg: "SMS request"; content:"|0524|"; offset:19; depth:2; byte_test:1,!&,8,0,relative; byte_test:1,&,4,0,relative; byte_test:1,!&,2,0,relative; byte_test:1,!&,1,0,relative; sid:9900004; rev:1; priority:4;)

#Location service request - Handset tracking?
alert udp any any -> any $GSM_PORT ( msg: "Location services request"; content:"|0524|"; offset:19; depth:2; byte_test:1,&,8,0,relative; byte_test:1,!&,4,0,relative; byte_test:1,&,2,0,relative; byte_test:1,&,1,0,relative; sid:9900005; rev:1; priority:3;)

#Low-priority, normal traffic - IMSI paging
#alert udp any any -> any $GSM_PORT ( msg: "IMSI paging"; content:"|0621|"; offset:17; depth:2; content:"|08|"; distance:1; within:1; sid:9900007; rev:1; priority:4;)

#When IMSI paging becomes common or TMSIs are not used...something is odd
alert udp any any -> any $GSM_PORT ( msg: "Excessive IMSI type 1 paging"; content:"|0621|"; offset:17; depth:2; content:"|08|"; distance:1; within:1; detection_filter:track by_src, count 50, seconds 5; sid:9900008; rev:1; priority:3;)

#These are normal in small quantities. In excess this could indicate an "IMSI-catcher".
#alert udp any any -> any $GSM_PORT ( msg: "Identity request (IMSI) from BTS"; content:"|051801|"; offset:19; depth:3; sid:9900009; rev:1; priority:4;)

#Location update rejection could be used to find strange BTS, but without a specific reason code it's too broad of a rule.
#alert udp any any -> any $GSM_PORT ( msg: "Location update rejection"; content:"|0504|"; offset:19; depth:2; sid:9900010; rev:1; priority:4;)

#Location update request using an *IMEI* as an identity
alert udp any any -> any $GSM_PORT ( msg: "Location update request using IMEI - WTF?"; content:"|0508|"; offset:19; depth:2; content:"|08|"; distance:8; within:1; sid:9900011; rev:1; priority:4;)
#------------------end gsm.rules------------------