Monday, October 16, 2017

Securing your front-end


An extremely common and dangerous flaw in web apps security is relying solely in client side security as we already discussed on this blog here and here. On this post we’ll examine the most frequent mistakes developers make and how to protect from them.

Before we proceed though, if you want to catch up, we are still discussing web application security. For all the topics on security, please click here.

Law of Security #4

We already reviewed the 10 laws of security on this blog. So, you may recall our Law #4:
If you allow a bad guy to upload programs to your Web site, it’s not your website any more.
That's probably, the main (but not the only) reason why web applications are so insecure: users are constantly submitting data to your application and changing data state. So what should we do?
Should you trust all data that's being submitted to you?
No.

Can you trust data from cookies sent to you?
No.

Can you trust everything that you are getting in your web application layer?
Of course not.

You cannot trust client side security

Because you don’t have control of what runs on your client or how that information is being submitted - if it was manipulated or came from a different source than you expect - you should never trust the data you are getting in a request. That's why you should always re-validate in your server data sent to you. The only actual info you should trust is the session, stored on the server.

So what are the most common mistakes?

In the context of web applications, the most common mistakes web developers make are:
  • Hiding info in hidden fields
  • Relying on Http cookies
  • Relying on Url parameters
  • Using Form action urls for backend logic
  • Using the Referer header for backend logic
  • Trying to be cryptic or to obfuscate info
  • Rely purely on the ASP.Net Viewstate
  • Rely only on html form attributes
  • Only run Javascript validation

Mistake #1 - Hiding info in hidden fields

In the past, developers used to hide essential information in hidden form fields as:
<input type=”hidden” name=”price” value=”45”>
So when a post was submitted to the server, something like the below would be sent:
POST /page.aspx HTTP/1.1
Host: mysite.net
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
quantity=1&price=449

Hacking this application is as simple as:
  1. changing the price value using devtools and resubmitting the form;
  2. issuing a post from a different tool to the server.

Luckily, this anti-pattern is no longer common anymore.

Solution

The solution here is simlpy not use hidden fields to pass sensitive information to the client. Use the Id of the product or some other type of identifier instead.

Mistake #2 - Relying on HTTP cookies

This one is less common but is still being used. Developers are still saving sensitive information in cookies, which are stored in the client side and can be easily manipulated.

Consider this response from the server:
HTTP/1.1 200 OK
Set-Cookie: Discount=20
Content-Length: 100
Assuming that the Discount value set in the cookie was used to perform some calculation in the server, a malicious user could easily change that information to 100 for example, and get the product for free. Not what we want.
POST /store.aspx HTTP/1.1 
Cookie: Discount=100
Content-Length: 10

Solution

The solution here is simlpy not use cookies fields to exchange/store sensitive information to the client. If you need to save, save it on the session, on the server. Upon each request, get the session value and process it from there.

Mistake #3 - Relying on Url parameters

Often, urls are very easily hackeable:
 somesite.com/store/view?prod=3&price=100
Anyone using a web browser or curl for example could alter that url and, if that property was used to provide the price to the server, alter it and benefit from your security issue.

Others can be more obscure but also open to attacks:
 somesite.com/store/view?prod=3&price=100&price_tkn=VJ58k6UxCFdUHiVj
 Remember that security trough obscurity does not work flawlessly.

Solution

Avoid using the query string to pass sensitive information. Even if some urls are meant to be hackeable, that's not the objective here.

Mistake #4 - Using Form action urls for backend logic

Similar to mistake #3, hidden but still modifiable, form actions can also be used to pass information :
<form action="/store/submit?discount=10">
...
</form>
Remember, this approach could be easily manipulated.

Solution

Avoid using the query string to pass sensitive information. Even if some urls are meant to be hackeable, that's not the objective here.

Mistake #5 - Using the Referer header for backend logic

Less common, the Http Referer header can be used to simulated authentication logic in the server. For example, a request like:
GET /auth/CreateUser.aspx HTTP/1.1
Host: mdsec.net
Referer: https://mysite.com/auth/admin.aspx

Could be interpreted in the server that the user indeed came from the admin page. While this could be true for non-malicious requests, it could also be manipulated.

Solution

Avoid using the Referer for authentication as can be easily manipulated in the client side.

Mistake #6 - Trying to be cryptic or to obfuscate info

We already provided an example in mistake #3. Trying to be cryptic or obfuscating information is not a 100% reliable solution. Yes, it could be used as part of a solution but should not be the sole solution.

Solution

Be creative securing your services and avoid security trough obscurity.

Mistake #7 - Rely only on html form attributes

Html form attributes like maxlength and disabled are nice but can be easily circumvented by simply removing them in developer tools or by submitting. Example:

Solution

Keep using those components to provide more friendlier applications but never rely only on them to validate your data. Always have similar validation in the server and in the backend if necessary.

Mistake #8 - Only run Javascript validation

As in mistake #8, relying solely on javascript is highly insecure as javascript can be disable or be easily removed, altered or manipulated in the client machine.

Solution

Make use of javascript to serve more friendlier applications but never rely only on it to validate your data. Always have similar validation in the server and in the backend if necessary.

Conclusion


So there you are, hope this post has helped you identifying the threats your app may be facing and how you could protect against them. But only for your front end.

Please note, that I'm not saying you should not secure your front end at all or skip using javascript or html attributes for example. My point is that front end security is a complementary effort toward a good security framework.

See Also

Integrated security vulnerability alerts on GitHub - Why it matters
Why you should start using .Net Core
Package Management in .Net Core
Exporting Html to Pdf using only JavaScript
Importing CSVs with .Net Core and C#
Exporting a CSV generated in-memory in Asp.Net with C#
Building and Running Asp.Net Core apps on Linux
Asp.Net / Asp.Net Core: Generating views in the backend
Testing Javascript on Asp.Net Core Applications