To make authenticated REST API calls in applications, several authentication schemes are used by developers. Some of them use HTTP Basic Authentication scheme, and others, as per their needs(or wants), use custom authentication schemes. Now, it’s good to experiment but not at the cost of security. In this blog, we will look into the common ‘basic authentication’ scheme along with its securiity implications. Furthermore, we will discuss the need of custom authentication schemes and see a vulnerable implementation of one of such custom authentication schemes.
Let’s first look at the basic authentication scheme.
This is a common authentication method used in applictions. Let’s understand the working of this method through an example:
An application ‘example.com’ requires its users to make authenticated api calls to access their information. Being stateless, the API calls require user credentials to be sent with each API request. That’s where basic authentication scheme comes into play.
To authenticate himself, a user enters the username and password. This username and password values are clubbed together separated by a colon to create a new string. For example, if the user enters Username: johndoe and Password: 12345, then the new string becomes johndoe:12345.
This string is then base-64 encoded and is added as the value of the HTTP Authorization header along with the ‘Basic’ keyword, thus stating that basic authentication scheme is being followed.
Following the above example, the value of Authorization header in our case(johndoe:12345) becomes ‘Basic am9obmRvZToxMjM0NQ==’. Now, each API request by the user contains this header.
When the server receives an API request, it reads the Authorization header value, base-64 decodes it and checks if those credentials are correct by searching them in the database. If the user details are present in the database, the request is authorised by the server and the requested action is carried out. If the credentials don’t match to any of the username-password pairs stored in the database, the server throws a 401 Unauthorised error.
Now, if we look at this scheme from a security point of view, sending password of the user in each request does not feel right. Also, the application must use TLS protocol to safeguard traffic from MITM attacks. If HTTPS is not being used, then the credentials of the user are exposed to the attacker as it can be sniffed and decoded easily by the attacker. So, ensure that you use TLS if you are implementing basic authentication in your application.
Sometimes, as the application demands, custom authentication schemes are used by developers to authenticate user. Commonly, in a custom authentication scheme, a ‘single sign on’ token is generated while authentication and it is further used to make authenticated api calls. In the course of implementing custom authentication schemes, many a times security loopholes are introduced. Due to these loopholes, sometimes the custom authentication schemes cause more harm than good.
While performing a pentest for a client, I discovered a vulnerable implementation of custom authentication scheme. Let’s look into it.
1. User enters his username and password and clicks on submit.
2. The following api request is generated.
3. In response, if the credentials the user entered were correct, a token is assigned to the user.
4. This token is then added as the value of Authorization Header and is sent with each request.
Till now, it was fine as this is how it should work. But after looking into it more, I was able to find a loophole. The loophole existed in Forgot Password mechanism.
So let’s see what actually went wrong?
It is pretty much clear that the token is the key here and if someone gets their hands on them, then it’s game over. The same happened here.
If a user forgot his password and chose to reset it, the application asked for his email id. If the email existed in the database, a reset password email was sent to the user. So? This is how it is supposed to work, right?
Yes, but you do not return a single sign on ‘token’ in the response if the email exists in your database! When a user forgot his password and entered his email, an api request was generated to check if the user had an account or not. Strangely enough, if the user account was present then the application sent a valid ‘token’ in response. Using this an attacker could take over any user’s session by entering the email address of victim in the forgot password form.
So, to sum up, as a developer you are free to use whichever authentication scheme suits your restful services the best, and it is better to be watchful while you are at it.