Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
April 12, 2022 05:34 pm GMT

How to Not Expose the Personal Data of 19,577 Canadians

A few months ago I spoke with CBC news to give an overview of a plethora of security flaws I found in PORTpass, an attempt to bring digital proof-of-vaccine to Canadians. While that article was meant for a broader audience, today I will outline their security flaws from a technical perspective for all the developers out there.

My Background

My name is Rida Fkih, I am a 21 year old Canadian software developer & reverse engineer at MaxRewards.

My development journey started at 15, from reverse-engineering to scammer-vigilantism then teaching coding to kids to web & mobile development.

What is PORTpass?

PORTpass was a private attempt by a local Calgarian entrepreneur to bring vaccine passports to Canadians.

What went wrong?

First, we must familiarize ourselves with Murphys Law.

Murphys law is an adage or epigram that is typically stated as: Anything that can go wrong will go wrong."

Wikipedia, Murphys Law

Id argue that PORTpass was the epitome of Murphy's Law from the perspective of the user, and criminal negligence on behalf of its creator due to their inaction after these issues were brought to light.

The Data at Risk

The data at risk wasnt light stuff.

PORTpass had the business requirement of collecting loads of personal data, collecting photos of government IDs, health card numbers, verification selfies, full names, dates of births, blood types, and more.

The data on PORTpass would be enough to be at risk of social engineering, or even have financial accounts opened in your name.

The Vulnerability

The primary vulnerability is called Improper Access Control, which is described by the Common Weakness Enumerationa community-developed list of software & hardware weakness typesas software [that] does not restrict or incorrectly restricts access to a resource from what should be an unauthorized actor.

Some pseudo-code to describe a properly managed & created endpoint may appear as follows.

import express from "express";import { loggedInUser } from "@/utils/authentication";import { getUserInfo } from "@/utils/users";const app = express();app.get("/user/:userId", (request, response) => {  const { userId } = request.params;  const authenticatedUserId = loggedInUser(request);   if (!authenticatedUserId  || authenticatedUserId !== userId)     return response.status(401).send("Unauthorized");   else     return response.status(200).json(getUserInfo(userId));});

Here, we would send a GET request to /user/[userId], and receive back user data only if we are authenticated into the same user we are requesting.

A poorly architected endpoint may be coded as follows.

app.get("/user/:userId", (request, response) => { const { userId } = request.params; if (!loggedInUser(request))  response.status(401).send("Unauthorized"); else  response.status(200).json(getUserInfo(userId));});

Here, were not checking which user is authenticated, only if the user is authenticated. Thus, an authenticated user could request ANY resource, even if it doesnt belong to them. For public posts this is appropriate, for private information like government-issued photo IDs, health care cards, and confirmation portraits, this is a massive flaw.

The Catalysts

Sequential User IDs

PORTpass users requested their resource by using sequential user IDs. This means that if you were the first user to sign up for their service, your ID would be 1, if you were the second, it would be 2, etc.

Had they used a cryptographic solutionsuch as UUIDv4scraping user information would have been significantly more difficult, however in this case formulating a script to collect all registered user data would be trivial, and would look something like...

/** * Gets the user profile from the PortPass API. * @param {number|string} userId The user ID of the target user. * @returns {Promise<any>} A user object. */const getUserProfile = async (userId) => {  const profile = await axios    .get(USER_PROFILE_URI + userId.toString())    .then((response) => response?.data)    .catch(() => ({}));  return profile;};for (let i = 0; i < 19577; i++)  getUserProfile(i + 1).then(saveUserData);

No SSL

Since PORTpass didn't have SSL certificates, packets that your device sends or receives could be altered or intercepted. With websites, its easy to identify a secure website by finding the little "lock icon" next to the URL, however with applications its a little more ambiguous.

Exposing Developer Tooling

PORTpass' backend was created using Django, which has an interface which allows you to test endpoints from your browser without having to use REST tooling like Postman, or Insomnia.

Optimally, PORTpass would have secured their endpoints so knowing their paths would provide no additional capabilities, however, they didn't, and thus traversing their entire backend was trivial.

Conclusion

We all want to get our projects out there, but if we don't have the experience necessary to accommodate for basic security considerations, getting your code reviewed or learning the basics of security should be considered good options.

In this case, a non-technical founder wanted to hastily get a product out there, so they hired a developer from overseas without the ability to evaluate the quality of code.

I'm very thankful to the CBC for their help in finally being able to hold the creator of PORTpass accountable, an address these concerns rather than simply ignoring them or claiming to be defamed.

You can read this article on Medium or my personal website.

If you enjoyed this content please consider following me on Twitter!


Original Link: https://dev.to/rida/how-to-not-expose-the-personal-data-of-19577-canadians-41gf

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To