Chicken karahi with a side of data
This restaurant's attempt at good UX has quickly turned into a lesson in cybersecurity
A few weeks ago, I was out for a family dinner when my eye caught this QR code on the table.
For reasons that will become abundantly clear shortly, I’ve omitted the name of the restaurant and the full QR code.
Normally, when one encounters a QR code on a restaurant table, you can be sure it’s going to be the menu.
But this one just said “SCAN ME” very invitingly, so I obliged, even though we’d already placed our order.
I was blown away.
That’s the order we’d just placed.
This was brilliant: we could verify that they’d gotten our order right, and knew in advance what the bill was going to be.
While not especially useful, it was nice to see someone experimenting with making the restaurant experience a little bit more fun, and a little bit more digital.
To add to my excitement as an appreciator of good UX, they had these buttons at the top:
Fantastic.
Gone were the days of playing peek-a-boo trying to make eye contact with the waiter.
Or flailing your hands in the air making cheque-signing gestures to ask for the bill.
Or impatiently asking “how much longer will it take?” when you’re hungry (they’re just going to say “5 more minutes”, there’s no point asking this question).
Now you could do all of that…digitally.
Unfortunately the discovery of these buttons is just about the peak of this experience.
First, the ‘request for bill’ and ‘table bell’ buttons don’t work.
Sad.
Then if you try to track your order, you get this glorious mess:
Which is a shame, because order tracking would’ve been pretty cool.
That was the end of that. Nice idea, doesn’t work, oh well.
I swiped up to close the tab on my browser.
And then I saw this:
The URL seemed to be a little too basic.
It was simple enough to parse: I was viewing my invoice, which happened to be invoice number 67853.
But what if I tried changing to URL to invoice 67854?
…
…
Oh.
What about 67855?
Ohhh.
Those guys got complimentary golgappay. Where’s mine?
And so for the next 10 minutes, I started to increment the invoice numbers by 1 to look at the orders of all the tables around me.
And then I started to decrement to see how far back I could go. I went from invoice 67853 all the way to invoice #100.
Normally such URLs are strings of alphanumeric characters - complex enough that this sort of casual tomfoolery doesn’t work.
There’s a reason why a Facebook URL might look something like this, for example:
Now unless this is some next-level attempt at publicly showcasing your revenues and tax liabilities, a simple 5-digit string that’s accessible to anyone on the internet is decidedly not good.
Since I was invested, I had to take this further.
A conversation with a friend and him spending 10 minutes on ChatGPT later, we had some basic code to scrape the contents of every invoice number:
Throw the output into Excel:
And after applying some pivot tables, I can tell you that this restaurant has daily sales of [redacted], an average order amount of [redacted], and the most popular menu item is [redacted] mineral water.
Mineral water being the most popular item probably isn’t surprising.
What is surprising is that the script sent ~5,000 requests to their server to scrape this data, without ever slowing down or being blocked. So there’s no DDoS protection involved either.
(DDoS is when you flood a server with bogus requests so that it exceeds its capacity and crashes)
We could conceivably take down the restaurant’s entire ordering and invoicing system by spamming their server with millions of requests.
This is…bad.
For what it’s worth, I did show this article to the restaurant before publishing:
I’m not sure they fully understand the implications of the problem beyond “button not working”.
Anyway.
The food’s decent.
This newsletter should be paid. Truly, the greatest thing ever emailed to me.