do transport companies trust their clients? (some really shouldn't)
tl;dr
i was on a [redacted] train, got hungry, opened their online bar ordering system, and it turned out that :
- client controls the price (and other critical order fields)
- full credit card data was sent back in plaintext in the payment callback
- i validated an order at €0.01 instead of €5
- the wifi portal allows iframe embedding of any external site (instant phishing kit)
i responsibly disclosed the issue and got rewarded with a €50 company bonus. moral: the client is a liar, never trust them
a train, hunger and curiosity
it's 6pm, i'm on the train. didn't have the time to buy a sandwich at the train station and hadn't eaten for ~15 hours, i was kinda hungry. i discovered that you can order food directly on their website. neat!
but as usual too, curiosity wins. i wanted to see how this was all working (and it was worth it)
step 1 - the sandwich is expensive
this bar had all the prices you would expect at a train bar, sandwiches were crazy expensive and while a spider was already making a web inside of my wallet i wanted to check how the prices were retrieved from the server (and check maybe for less expensive currencies, who knows). no surprise here, the server gives you the bad news. the club sandwich is still €3.
so with some pain i decided that i would order one, and checked the order creation requests, when i saw something interesting: the client basically tells the server "here's what i have to pay, trust me :D"
i was like "??? there must be some kind of server check", so i tried putting €0.01 instead of €5, sent it and... it went through. and even the order number was client-generated. the result was a fully valid order, at whatever price i wanted.
step 2 - payment magic
ok, maybe just a bug in price calculation? and nah, the real kicker was the payment callback
/api/[redacted]/success returned the entire credit card data. PAN, expiry date, holder name and brand, all in a base64-encoded json. plus, this endpoint was reachable directly from the client after payment validation (very cute, very secure (no))
i reread it three times and laughed a bit, this is PCI DSS being shredded in technicolor
step 3 - wifi portal aka phishing heaven
and just when you think it's enough: the wifi portal has an endpoint /iframe?url= that lets you embed any external site under the official train domain, with valid tls and branding
so yeah drop a malicious qr code in that train and passengers will happily enter credentials on what looks like a legit domain
responsible disclosure
i reported everything on a bug bounty platform (even though the train company had neither a security.txt nor a dedicated bug bounty, another collaborator had a program). triage was fast, forwarded to the good company, and the collaborator awarded me a €50 company bonus (thanks!).
testing was limited to my own order and passive observation!!
the test order (€0.01 for a €5 item) was cancelled by the bar service, meaning the flow reached production but without impact on staff or resources (i didn't want to get that anyways)
moral of the story
- the client is far from being a math god: never trust them to calculate a price
- don't log full credit cards, that sounds like logic but it looks like it is not for everyone
- close your iframes unless your business model is PAAS (Phishing As A Service)
it was my first officially reported vulnerability (to a big company), first bonus, and a nice line for my resume!