MySejahtera is a Perfectly Good App With No Exploits

MySejahtera is a Perfectly Good App With No Exploits

Part 1 — MySejahtera is a Perfectly Good App With No Exploits

Part 2 — MySejahtera is a Perfectly Good App With No Exploits — Part 2

Final — MySejahtera is a Perfectly Good App With No Exploits — Final (Dual Fix Ver )

The series was supposed to be over, I promised myself to stop looking for more exploits with “MySejahtera”. But trust me, this exploit came to me, and it is kinda BIG.

So I was travelling back to Malaysia via flight. While being processed by personnel from the Ministry of Health (The frontliners), all travellers were asked to open “MySejahtera” or use a QR Code scanner to scan the typical “MySejahtera QR Code”.

The Port-of-Entry QR Code

The QR Code links to something like this:

Nothing out of the ordinary, just the usual information about yourself, mode of transportation and vaccination status.

Once checked in, the travellers were then asked to line up to show the frontline our documents (Like pre-departure PCR, whether you're going to home quarantine) and get our lovely pink tag (denoting we’re “Person Under Surveillance” aka “Under Quarantine).

The interesting thing I noticed is, there are no computers, the frontliners did not use any gadgets. But my status in “MySejahtera” had turned from the usual “Low Risk No Symptom” to “Person Under Surveillance (PUS)”.

I did play around with the QR Code check-in APIs before, there is no validation on the server-side, you can submit check-in to locations that don’t exist.

I quickly open up the link and check what are the APIs call made during the submission. The call was made to

https://mysejahtera.malaysia.gov.my/clockinTraveller

with the following schema:

The name , contact , userStatus and tenant seems interesting, my wild guess is that:

  • name is the name registered in “MySejahtera”

  • contact is either the phone number or email address used to register for “MySejahtera”

  • userStatus could be a enum of status that exists on server-side

  • tenant is the unique id for the check-in location

I created a few dummy “MySejahtera” account using email to test if this particular API call change the status on the app. After a couple of minutes of tinkering, Tadaa:

Without Quarantine Order

The worse thing about this? There is absolutely ZERO server-side validation. Forget about the schema we talked about earlier, just send contact and it will work. And as we know, contact can be in the form of phone numbers, some bad actor could’ve just enumerated the number so everyone become “PUS”

A simple server-side validation and admin portal where authorised personnel approve the change of status would’ve avoided this exploit.

Benefits of being “PUS”? You can legitimately tell your boss you can’t go to the office for the next 7 days😎.

Now, everyone can become “PUS” like me with a simple curl .

Update 1: Apparently tenant and createDate will trigger “Home Surveillance Order”.

Update 2: The endpoint had been taken down. While checking the qrscan page.

https://mysejahtera.malaysia.gov.my/qrscan/

The TRAVELLER and TRAVEL_QUARANTINE endpoint was always there.

In theory, one does not need to get the QR Code at the port of entry. Just simply call

https://mysejahtera.malaysia.gov.my/qrscan/?formType=TRAVELLER

and within the JS code, you will be able to know the exact API that was used for this exploit.

As of 7/11/2021, /clockinTraveller and clockinTravellerQuarantine had been removed and will return NOT FOUND 404 . But you will be able to get the successful check-in page as that was just a render on Frontend which doesn’t depend on a successful response from the backend.

As reported in the news
https://malaysia.news.yahoo.com/complaints-health-ministry-says-sorry-014832037.html