Igår eftermiddag, dagen efter Trafikverket presenterade Läget i trafiken, lanserade SJ en app till Android. Jag började snabbt titta på datatrafiken till och från appen. Precis som i Trafikverkets fall handlar det om ett helt öppet och oskyddat API, dock inte lika exponerat.
SJ exponerade personlig data
Om du tittar lite närmare i svarsdatan från SJ:s API nedan, närmare bestämt i värdefältet för deviceID
. Detta innehåller den privata, unika identifieraren för den enhet du använder när en ny bevakning skapas. SJ exponerar alltså denna data, om alla som valt att bevaka tåg via deras app.
Detta är väldigt kritiskt data, som varken Google eller Apple tillåter att utvecklare tillgängliggör. Med informationen, som Theodor nämner i sitt inlägg, är det exempelvis möjligt att skapa, ändra och ta bort andra användares bevakningar.
Jag uppmanar alla användare att ta bort alla sina bevakningar som skapats via appen, tills dess att SJ har säkrat sitt API.
SJ har bemött kritiken via Twitter
“Nu har vi svar. Det finns ingen personlig info i appen, inte ens UD ID. Det vi kallar device ID är endast kopplat till appen. Trots det ska vi göra om den så den blir krypterad så fort som möjligt.” — @SJ_AB
Intressant svar. Inget är fel, men det ska ändå åtgärdas? Detta är fel. Appen skickar UDID i klartext till SJ:s API. Theodor har tydliggjort detta med enkla skärmdumpar i sitt inlägg. Därefter var det dags att bekänna.
“Vi var övertygade om att vi hade rätt. Nu undersöker vi vad detta beror på och ska åtgärda snarast.” — @SJ_AB
Jättebra agerande av marknadsavdelningen tycker jag. Nu hoppas vi bara att SJ först kommunicerar problemet med sina användare och sedan stänger in användardatan snarast.
Uppdatering: SJ har nu säkrat den mest kritiska bristen i sitt API. Men fortfarande skickas iOS-enheters UDID i klartext till och från appen.
- Endpoint: http://sjmg.sj.se/api/
- Format: JSON
Metoder (deprecated)
Första versionen av SJ API fungerar inte längre som dokumenterat nedan. Se dokumentation av SJ API 2.
- Get stations
- Get station
- Get station timetable
- Get train
- Get train timetable
Get subscriptions- New subscription
Get stations
GET /stations.json
Returnerar alla stationer. Exempel för /stations.json:
{
"stations":
[
{
"id": 1,
"stationName": "Stockholm C",
"city": "Stockholm C",
"stationType": "sj"
},
…
{
"id": 924,
"stationName": "Stenstorp",
"city": "Stenstorp",
"stationType": "sj"
}
]
}
Get station
GET /station/#{id}.json
Returnerar given station. Exempel för /station/1.json:
{
"id": 1,
"stationName": "Stockholm C",
"city": "Stockholm C",
"stationType": "SJ"
}
Get station timetable
GET /stationTimeTable/#{id}.json
Returnerar tidtabell för given station. Exempel för /stationTimeTable/1.json:
{
"id": 1,
"stationName": "Stockholm C",
"city": "Stockholm C",
"stationType": "SJ",
"arrivals":
[
{
"trainNumber": "11",
"time":
{
"scheduledTime": "2011-09-29T08:16",
"newTime": "2011-09-29T08:18"
},
"track":
{
"scheduledTrack": "7",
"newTrack": ""
},
"fromStationName": "Falun C",
"toStationName": "Stockholm C",
"stationNames":
[
"Falun C",
"Borlänge C",
"Säter",
"Hedemora",
"Avesta Krylbo",
"Sala",
"Uppsala C",
"Arlanda C",
"Stockholm C"
],
"cancelled": false
},
…
{
"trainNumber": "861",
"time":
{
"scheduledTime": "2011-09-29T19:49",
"newTime":""
},
"track":
{
"scheduledTrack": "3",
"newTrack": ""
},
"fromStationName": "Uppsala C",
"toStationName": "Stockholm C",
"stationNames":
[
"Uppsala C",
"Knivsta",
"Märsta",
"Stockholm C"
],
"cancelled": false
},
…
{
"trainNumber": "10759",
"time":
{
"scheduledTime": "2011-09-29T20:00",
"newTime": ""
},
"track":
{
"scheduledTrack": "7",
"newTrack": ""
},
"fromStationName": "Örebro C",
"toStationName": "Stockholm C",
"stationNames":
[
"Örebro C",
"Arboga",
"Köping",
"Västerås C",
"Enköping",
"Bålsta",
"Sundbyberg",
"Stockholm C"
],
"cancelled": false
}
],
"departures":
[
{
"trainNumber": "425",
"time":
{
"scheduledTime": "2011-09-29T08:10",
"newTime": ""
},
"track":
{
"scheduledTrack": "10",
"newTrack": ""
},
"fromStationName": "Stockholm C",
"toStationName": "Göteborg C",
"stationNames":
[
"Stockholm C",
"Södertälje Syd",
"Katrineholm C",
"Skövde C",
"Alingsås",
"Göteborg C"
],
"cancelled":false
},
…
{
"trainNumber": "860",
"time":
{
"scheduledTime": "2011-09-29T20:11",
"newTime": ""
},
"track":
{
"scheduledTrack": "3",
"newTrack": ""
},
"fromStationName": "Stockholm C",
"toStationName": "Uppsala C",
"stationNames":
[
"Stockholm C",
"Märsta",
"Knivsta",
"Uppsala C"
],
"cancelled":false
}
]
}
Get train
GET /train/#{nr}.json
Returnerar position för givet tågnummer. Exempel för /train/220.json:
{
"trainNumber": "220",
"trainType": "",
"fromStationName": "Linköping C",
"toStationName": "Stockholm C",
"trainPosition":
{
"latitude": 59.154098,
"longitude": 17.762635,
"timestamp": "2011-10-03T08:09"
}
}
Get train timetable
GET /trainTimeTable/#{nr}.json
Returnerar stationer och position för givet tågnummer. Exempel för /trainTimeTable/538.json:
{
"trainNumber": "538",
"trainType": "",
"fromStationName": "Malmö C",
"toStationName": "Stockholm C",
"trainPosition":
{
"latitude": 58.417037,
"longitude": 15.624342,
"timestamp": "2011-09-28T17:52"
},
"stops":
[
{
"station":
{
"id": 3,
"stationName": "Malmö C",
"city": "Malmö C",
"stationType": "SJ"
},
"arrivalTime":
{
"scheduledTime": "2011-09-28T13:09",
"newTime":""
},
"departureTime":
{
"scheduledTime": "2011-09-28T13:17",
"newTime": "2011-09-28T13:37"
},
"track":
{
"scheduledTrack": "6",
"newTrack": ""
},
"isCancelled" :true,
"isPassed":true
},
…
{
"station":
{
"id": 1,
"stationName": "Stockholm C",
"city": "Stockholm C",
"stationType": "SJ"
},
"arrivalTime":
{
"scheduledTime": "2011-09-28T17:39",
"newTime": "2011-09-28T19:30"
},
"departureTime":
{
"scheduledTime": "",
"newTime": ""
},
"track":
{
"scheduledTrack": "10",
"newTrack": ""
},
"isCancelled": false,
"isPassed": false
}
],
"nextStop":7
}
Get subscriptions
GET /subscriptions.json
Returnerade tidigare alla bevakningar. Exempel för /subscriptions.json:
{
"subscriptionsDTO":
[
{
"id": "censurerad",
"deviceID": "censurerad",
"deviceType": "Android",
"fromStationName": "Stockholm C",
"toStationName": "Malmö C",
"fromStationID": 1,
"toStationID": 3,
"enabled": true,
"fromTime": "19:25",
"toTime": "22:28",
"weekdays":
[
"Tuesday",
"Friday"
]
},
…
{
"id": "censurerad",
"deviceID": "censurerad",
"deviceType": "Android",
"fromStationName": "Västerås C",
"toStationName": "Katrineholm C",
"fromStationID": 99,
"toStationID": 166,
"enabled": true,
"fromTime": "06:55",
"toTime": "08:00",
"weekdays":
[
"Thursday",
"Monday",
"Tuesday",
"Wednesday"
]
}
]
}
New subscription
POST /subscriptions.json
Skapar ny bevakning. Exempelfrågan:
{
"enabled":true,
"deviceType": "iphone",
"weekdays":
[
"Thursday"
],
"deviceID": "censurerad",
"toStationName": "Uppsala C",
"fromStationName": "Stockholm C",
"fromStationID": 1,
"toStationID": 5,
"fromTime": "10:41",
"toTime": "11:41"
}
ger svaret:
{
"id": "censurerad",
"deviceID": "censurerad",
"deviceType": "iphone",
"fromStationName": "Stockholm C",
"toStationName": "Uppsala C",
"fromStationID": 1,
"toStationID": 5,
"enabled": true,
"fromTime": "10:41",
"toTime": "11:41",
"weekdays":
[
"Thursday"
]
}
Andra som skrivit om SJ:s API
- API Måndag – Trafikverket, SJ, Bredbandskollen och E-delegationen av Andreas Krohn, Mashup.se
- SJ läckte info om användare av Sujay Dutt, DN
- SJs app läcker användardata av Ludvig Mjöbring, Computer Sweden
- SJ släppte app – som läckte telefonens identitet av Lisa Röstlund, Aftonbladet
- SJs app läcker resenärsinformation av Theodor Storm
- SJ läcker info om användare av Roman Pixell, Mobil Business
- SJ:s nya appar läcker information om användare, Travel News
- Fel om Upptåget i SJ-app "Mina resor", Upplands Lokaltrafik
- SJ-app läckte info om användare, The Scandinavian Travel Trade Journal
- Ny app från SJ ska underlätta resandet, Androidbloggen
För att kommentera det här inlägget, skriv en tweet.