Personal - and in some cases sensitive - information about 63,000 students could be accessed. Here are the details that the newspaper article did not give.
|Mon, September 10, 2018, 06:55
Social Security numbers
Behind the news
OWASP 2013 A2
OWASP 2013 A3
OWASP 2013 A5
I got in contact with a parent concerned about the security in a new messaging app used for communication between pupils, teachers and parents (Norwegian link) in the schools of Oslo. The app - which is called Skolemelding - was released this summer and is developed by CGI Norge. Unfortunately the concerns turned out to be justified. Please note that I was not the one to discover any of these issues.
The Norwegian newspaper Aftenposten broke the news about the vulnerabilities September 6th (follow-up article) and the system was temporarily shut down.
The security vulnerabilities were really bad. The system is designed for sending messages between school and home, including messages related to student absence. According to Norwegian law health information is regarded as sensitive personal information, and therefore I would assume that the system should be designed with the appropriate security level to prevent unauthorized access.
Anyone with either a valid login or anyone who got hold of a guardian's Social Security number could access any and all messages across all 63,000 pupils + guardians and teachers. This includes not only communication between guardians and school, but also communication between teachers was accessible through these vulnerabilities.
Anyone who got hold of a guardian's Social Security number could access details about a pupil's family (full names, Social Security Numbers, usernames, e-mail addresses, phone numbers) (in addition to the guardian's messages). I have published a couple of cases where one easily could get a specific person's Social Security number.
There are two apps - one for parents and one for teachers + students. Looking at the Android apps they are pretty much the same app with just different build variant (flavors). Parents use a different login than the teachers and students.
To fetch a message the app calls
This is where we find the first failure. The server did not do an authorization check on the
messageId and therefore let one read any other message in the system. And to make this a huge problem; the IDs were a sequential number that let one go through all messages available.
The parent/guardian version of the app uses a common log-in solution by the Agency for Public Management and eGovernment (Difi) called ID-porten. The teacher + student version of the app uses a log-in solution called Feide - a pretty common solution among schools. It's important to emphasize that there were no weaknesses in these two solutions in this case. However, the usage and implementation in the apps was horrible.
In the parent version of the app, when pressing the Log in button, the user is taken through the log-in flow of ID-porten as expected. However, there was a big flaw in the logic of the authentication server (called midporten) used by this system. The "token" returned from that server was just the user ID - the parent's Social Security number. One could intercept the call at this stage and replace the user ID/SSN with another one and get full access.
Reading the last sentence you might ask what the client really did with the user ID. Well, the client sent the user's SSN to the school portal (the app's API) to generate an access token. This means that it was possible to just skip the whole flow of midporten and ID-porten and just ask the app's backend to get an access token for any valid user ID. Wow.
So the flow was like this (with optional faking of user ID in either step 5 or 6):
While not a direct flaw, it is interesting to look at the structure of the data from the server. There's a call going to
/api/settings which returns information about the logged in user and the belonging student(s). The JSON returned is actually LDAP data. And it contains full names, usernames, e-mails, Social Security numbers, possibly phone numbers of guardians and belonging student(s). It looks like a dump of the LDAP. Why would one need this information in the app? And why are Social Security numbers stored in a way like this in a directory where an app has access? We're talking about hundreds - maybe thousands - of lines of LDAP data.
The fix for the login vulnerability was - instead of sending the user ID to generate the access token - to send a JSON Web Token (JWT). The JWT does not contain any user information, meaning that it has be checked on the server side to see which user is asking for an access token.
What is surprising is that the JWT does not contain some internal user ID (like a UUID), but rather a timestamp. And the JWT cannot actually be verified on the backend (other than string comparison) as it is sent back as lower-case.
What happens if two users log in at the exact same time? Is it possible that the timestamps (and therefore JWT) can end up being the same? Would one user get access to the other?
With these vulnerabilities you can start to wonder if there are other problems here. I have not tested any of these things, but it is something for the vendor to look into.
It's easy to make mistakes when programming, and not all programmers will have a good enough understanding of security (though I think we should try to improve this!). What really sticks out here is how both CGI Norge and the City of Oslo could release a product like this without testing the security. I do not believe this is a case where a pen tester overlooked something. This must be a case where there has been no external testing of the system. And that's a shame.