Hacking Mumbai's Metro ChatBot and APIs for FUN πŸ€ΈπŸ»β€β™‚οΈ

This blog post is regarding the time when I hacked into Mumbai's Metro Booking System from ChatBot to SQLi and breaking encryption.

BackStory

A few months ago, me and my friends were going for an event in Mumbai. While reaching to the metro station, I noticed one of my friend was using Mumbai's metro WhatsApp ChatBot which provided functionality to generate session codes and OTP for booking metro ticket.

I was curious how secure it was! So I tried to book a ticket myself and understand its flow. Flow goes this way:

  • Ping whatsapp bot to generate OTP/Link with session code.

  • Traveler can use the link to book ticket or OTP at the ticketing counter.

  • When traveler clicks on the link they're asked about their source, destination, journey type, number of individuals, etc.

  • Once traveler has filled the required details, they can proceed with payment. They'll be redirected to payment gateway where they can pay using their desired payment option (Debit Card/Credit Card/UPI)

  • After payment they'll be assigned a QR Code which can be used to enter and exit metro stations.

What Can Go Wrong?

Web Application Bad Practices

No Obfuscation on Client/Browser Side Source Code

Redirecting user to web application provided me an opportunity to reverse engineer their web application by reading their client side source code. It helped me to understand how their web application works what user inputs are needed to which endpoint.

The Browser side code wasn't obfuscated so I was able to break their client side encryption which provided me to forge checksum.

PoC Code Link: https://github.com/dmdhrumilmistry/hacking-mumbai-metro/ (This might not work now)

Application Running in Debug Mode

Since, Source code was readily available, I used jsluice to extract API endpoints and other urls.

I started fuzzing endpoints manually to in hope to generate tracebacks. I found out that the application was running in debug mode using laravel in the backend.

Now I was able to read few parts of the backend source code. During which I found that there was no input validation and sanitization in the API. Most of the API endpoints are crashed were vulnerable to SQL Injection attack vector due to missing sanitization and input validation.

In Laravel, the where() method is a helper method that constructs a simple where clause for an Eloquent query. When you use the where() method with a string argument, Laravel will automatically escape the string to prevent SQL injection attacks. However, when you use the where() method with a Closure argument, Laravel will not escape the Closure, which means that any unescaped user input passed to the Closure will be included in the SQL query as-is.

In above example code, the where() method is used with a Closure argument to construct a where clause that compares the sale_or_no column to the order_id variable. If the order_id variable is not properly sanitized and validated, an attacker can inject malicious SQL code into the variable, which can then be executed by the database server.

Want to avoid such attacks in your apps?

Checkout my project which automatically pentests your APIs using OWASP OFFAT and fix security issues before they're deployed to production environment.

How to avoid such mistakes?

  • Never run any of your app in debug mode for production environments. It can leak so much information about the production environment.

  • Never ever trust user input data, always validate and sanitize their inputs.

  • Always obfuscate/uglify code for client side applications.

Conclusion

We usually learn from our mistakes but let's learn from others mistakes as well. Let's sanitize user inputs each and every time, which will help us take one step towards creating robust and secure applications.

Last updated