Common Web Application Security Vulnerabilities and Fixes

We were en-trusted with developing a web application for one of our clients, who were into securing their customer’s sensitive data. We were asked to come with a document listing common security vulnerabilities with respect to a web application and were asked to provide solutions for each of them. We came up with the below vulnerabilities & solutions, which we wanted to both share and discuss with all of you folks out there.

Cookie Stealing/Session Hijacking

Cookie Stealing/Session hijacking is the exploitation of a valid computer session to gain unauthorized access to information or services in a remote server. In a web application, HTTP cookies are sometimes used to maintain a session, which could be easily stolen by an attacker using an intermediary computer or with access to the saved cookies on the victim’s computer.

One of the common ways to steal cookies is using source-routed IP packets. This method allows an attacker at point B in a network to participate in a conversation between A and C by encouraging the IP packets to pass through B’s machine.

If source-routing is off, an attacker can use a technique called “blind” hijacking, whereby it guesses the responses of the two machines. Using blind hijacking, an attacker can send a command, but can never see the response. But, a common command would be to set a password which would enable the hacker to access the site from somewhere else on the net.

An attacker can also be “inline” between A and C using a sniffing program to watch the conversation. This is known as a “man-in-the-middle attack”.

session-hijacking

Solutions

  1. We decided to use https (SSL) to encrypt all the content that goes over the network. SSL mainly prevents, man in the middle attack.
  2. We also decided to use HTTP Only Cookie for each call between client and server. We generated a unique token for each user when they login and cleared that token when user logs out.

Token = MD5(user_id + IP + Current Time)

The following is a fragment of the user table containing token information:

Id user id Token Ip address created_time
1 1 xyus#4sdsdoesd 145.10.15.16 09/05/15 11:02 AM
2 2 uops$itusynkk 120.1.12.25 09/05/15 12:40 PM

The generated token is sent to the server with every request over SSL and is compared with the token in the user table to allow access to secure information in the site.

Cross Site Request Forgery

Cross Site Request Forgery or CSRF is forces a malicious action on a legitimate website from an end user’s browser when they are on the site using a valid authenticated session.

Once the user is authenticated on a website, every action performed from his browser will belong to the user. The server assumes that each request is coming from the user.

The key in understanding CSRF attacks is to recognize that websites typically don’t verify that a request came from an authorized user. Instead, they verify only that the request came from the browser of an authorized user.

This attack is commonly done by hackers when users perform actions like: change of password , fund transfer from bank account, purchase of an item etc.

This attack is performed by making fake forms or requests that behaves exactly like an original website. When these requests are sent to a website from an authenticated user’s browser, the website thinks that the request has been made by that user.

CSRF

How CSRF Works ?

  • The user navigates in their browser to an application
  • The server returns a basic web page and a JavaScript application
  • The JavaScript application can’t find an authentication token in the web site’s cookies
  • The JavaScript application displays a login form
  • The user enters correct login credentials and then submits the form
  • The server validates the login information and creates an authentication token for the user
  • The server sets the authentication token in a cookie and returns it to the JavaScript application
  • The JavaScript application makes a request for some protected data, sending the authentication token in a custom header
  • The server validates the token and then returns the data

How to prevent CSRF vulnerability ?

Checking for Referral Header

Checking for a referral header can help in preventing the CSRF. If the request is coming from some other domain, it must be a fake request, so block it. Always allow the requests which come from the same domain.

This method fails if the website has open redirection vulnerabilities. Attackers can perform GET CSRF by using open redirection.This method will also fail, if the website uses https.

Captcha Verification in forms

This is another nice way to prevent CSRF attacks on forms. Captcha verification process was initially developed to prevent BOT spam in forms. But it can also be helpful in preventing CSRF.

As the captcha is generated on the client side randomly, an attacker cannot guess the pattern. So, he will never be able to send the correct Captcha with a fake request, and all fake requests will be blocked by a Captcha verification function.

This method is not user friendly. Most of the users don’t want to fill the Captcha on the website. So, we should find ways that prevent CSRF vulnerability without adding any extra burdens on users.

User side Prevention

CSRF is a harmful vulnerability so, users should also follow few steps to ensure their security. These are the few important points:

  • Always logout important web accounts when not in use.
  • Never use important web accounts (such as online banking) along with free web surfing.
  • Use No-Script browser add-on to protect yourself from malicious scripts.

Cookie-to-Header Token

Cookie-to-Header Tokens are mainly used in web applications which use javascript heavily. This technique works on the principal of same-origin which states that javascript can not access cookies from other websites.

When a user logs into a web application, it sets a cookie (containing a random token) which is going to be used for the remainder of the login session. JavaScript executing on the client side reads its value and copies it into a custom HTTP header sent with each HTTP request to the server.

JavaScript running from a rogue file or email won’t be able to read it and copy into the custom header. Even if the csrf-token cookie is sent with the rogue request, the server will still be expecting a valid X-Csrf-Token header.

This technique is widely implemented in recent frameworks like Angular and Django.

Cross site scripting Attacks

Cross-site Scripting (XSS) refers to client-side code injection attack where an attacker executes malicious scripts into a legitimate web app.

XSS is one of the most prevalent web application vulnerabilities and occurs when a web application uses un-validated or un-encoded user input within the output it generates.

By leveraging XSS, an attacker doesn’t target a victim directly. Instead, when a victim visits a website which has some vulnerabilities, an attacker exploits that as a vehicle to deliver a malicious script to the victim’s browser.

cross-site-scripting

Solution

We validated & cleaned up all the data before applying any business logic on it.We created filters in java so that we could clean Query strings, Headers, Cookies, Parameters etc.

We leveraged OWASP ESAPI libraray and Jsoup library for cleaning the input that we recevive from the client browser. These libraries encode and clean up script and html tags.

We also used techniques like escaping or encoding script tags in the client side.

SQL Injection Attacks

A SQL injection attack as the name suggests is where a hacker tries to “inject” his harmful/malicious SQL code into someone else’s database, and force that database to run his SQL. Injected SQL commands can alter SQL statement and compromise the security of a web application.SQL injection is used to attack any type of SQL database and it can also be used to add, modify and delete records in a database, affecting data integrity.

User login pages are among the most targeted areas because of their direct link to the database since credentials are often checked against a user table of some sort.

By injecting a SQL statement, `like` ‘ ) `OR` 1=1′ an attacker could gain access to information stored in the web application’s database.

The example used in the above given SQL statement represents a relatively simple SQL statement. Ones used by attackers are often much more sophisticated, especially if they know the database schema and the names of tables in the database.

sql-injection-attacks

Solution

Using Prepared/Parametrized statements in the Data Access Layer of a web application is the most prevalent approach to prevent SQL injection attacks.

A PreparedStatement represents a precompiled SQL statement that can be executed multiple times without having to recompile for every execution.

Example of a prepared statement in PHP using PDO:

$oDB=new PDO('... your connection details... ');
$hStmt=$oDB->prepare("select name, age from users where userid=:userid");
$hStmt->execute(array(':userid',$nUserID));

This code is not vulnerable to SQL injection because it correctly uses parameterized queries. By utilizing the PHP PDO module and binding variables to the prepared statements, SQL injection can easily be prevented.

Prepared statements are more secure because they convert the parameters to their specified types. For example, stmt.setString(1, user); will convert the user parameter to a String.

How prepared statements are effective against SQL injection?

The reason why prepared statements help so much in preventing SQL injection is because of the fact that, the values that are inserted into a SQL query are sent to the SQL server after the actual query is sent to the server.

In other words, the data input by a potential hacker is sent separately from the prepared query statement. This clearly means that there is absolutely no way that the data input by a hacker can be interpreted as SQL, so there is no way a hacker could run his own SQL on your application.

Any input that comes in will only be interpreted as data, and can not be interpreted as part of your own application’s SQL code – which is exactly why prepared statements prevent SQL injection attacks.