In addition to travel apps like Uber and Lyft, there's a new form of crowed-sourced transportation popping up all over the place. Scooters! These electric scooters can be found in cities all over the world and I wondered how much location data they're keeping. So I dug in, and man I was excited at what I started to find.
This post is going to focus on the Lime application for iOS. https://apps.apple.com/us/app/lime-your-ride-anytime/id1199780189 You can find this application on devices by its bundle ID: com.limebike. Full disclaimer info: this analysis was on a full file-system style iOS image. I'll do some additional testing in the future to figure out if other acquisition techniques reveal the same goodies.
To start, I'll dig into the database LimeBike.sqlite. This database will contain user data, payment data, and even trip data of the trips we take as users. The ZPSUSER table is going to contain information on the users that have signed into this application.
Here you can see that I didn't actually give it a full name so I'm "Lime Rider" but that ZREMOTEID is going to come in handy later. As is that number of trips.
Query: SELECT ZISCURRENT, ZNUMOFTRIPS, ZCURRENTBALANCE, ZJUICERUSER, ZEMAIL, ZGIVENNAME, ZNAME, ZREMOTEID, ZSURNAME from ZPSUSER;
Next comes the ZPSBIKE table which tracks the devices you've rented.
The Last Activity column or ZLASTACTIVITYAT column tracks when you stopped your ride in UTC. The Latitude and Longitude columns are where your ride ended.
Query: SELECT datetime ('2001-01-01', `ZLASTACTIVITYAT` || " seconds" ) AS LASTACTIVITY, ZLATITUDE, ZLONGITUDE, ZBATTERYLEVEL, ZLICENSEPLATENUMBER, ZPLATENUMBER, ZREMOTEID, ZTYPE from ZPSBIKE;
The ZPSRIDERSUMMARY table is going to track your usage of the app. How many meters the rider has gone in the last week, and over a lifetime.
Query: SELECT ZTOTALDISTANCEMETERS, ZTOTALTRIPSTAKEN, ZWEEKLYDISTANCEMETERS, ZWEEKLYTRIPSTAKEN, ZUSERID from ZPSRIDERSUMMARY;
The ZPSTRIP is going to log the start and end times for each trip the user has taken. More on that ZREMOTEID later.
Query: SELECT ZPSTRIP.ZBIKE, ZPSUSER.ZNAME, ZPSTRIP.ZCOMPLETEDAT, ZPSTRIP.ZSTARTEDAT, ZPSTRIP.ZSTATUS, ZPSTRIP.ZREMOTEID from ZPSTRIP JOIN ZPSUSER ON ZPSUSER.Z_PK = ZPSTRIP.ZUSER;
The last table is the ZPSTRIPROUTE table.
The ZLOCATION column has some great embedded JSON data. Looking at the first row:
The timestamps in this one get confusing. They don't seem to be in any certain order. If only there was something a little better...
Then I found this little guy. In the same folder as the database is a folder called RideHistory. Inside THAT folder there's a .png file. The name of the file is the same as the ZREMOTEID in the ZPSTRIP table!
Woo! Free location data!
Future research on this section is going to include other scooter apps (because it's super fun to generate data for them) as well as Android testing. Know a specific scooter app that should be tested? Let me know!