Reverse engineering Lyft Bikes for fun (and profit?)

https://news.ycombinator.com/rss Hits: 4
Summary

Reverse engineering Lyft bikes for fun (and profit?) One cold San Francisco summer morning in Haight-Ashbury, my commute down to Market was interrupted by the sight of a lucky duck taking the last Lyft bike – again. "I should really just wake up 15 minutes earlier", I thought, fleetingly. Then instead proceeded to spend the next month reverse engineering Lyft's private API, bypassing SSL encryption, chasing loose bikes across the city, triggering an internal incident, and somehow making a profit. I learned a lot doing this, so I'm writing it up in case you might too. Technical summary, for the impatient (spoilers!) Goal: Remotely unlock a Lyft bike. Steps: Capturing iOS App Encrypted Traffic – to re-construct request Replaying Modified Unlock Request – to bypass geofence Brute-forcing Bike ID – since not available remotely Capturing iOS App Encrypted Traffic I used Charles Proxy to capture outgoing requests from the Lyft app on my iPhone. Charles supports SSL Proxying, which injects its own ephemeral certificates during SSL handshake, making sure requests from both sides are being signed with keys it controls. This allows us to decrypt, read, and re-encrypt traffic in transit. The ephemeral certificates are signed by a Charles Certificate Authority, which needs to be installed on your phone so Charles's certificates are not rejected. SSL traffic content is then viewable. Replaying Modified Unlock Request From the Charles captures, we see the unlock request uses a rent endpoint with the following structure: POST "https://layer.bicyclesharing.net/mobile/v2/fgb/rent" HEADERS { "api-key": "sk-XXXXX", "authorization": "bearer-XXXXX", ... } DATA { "userLocation": { "lat": 37.7714859, "lon": -122.4449036 }, "qrCode": { "memberId": "user-XXXXX", "qrCode": "12345" }, ... } A simple python replay script: import requests url="https://layer.bicyclesharing.net/mobile/v2/fgb/rent" headers={ "api-key": "sk-XXXXX", "authorization": "bearer-XXXXX", } station_coords = { "lat": 37.773...

First seen: 2026-01-22 20:45

Last seen: 2026-01-22 23:45