Web application security guidelines and checklist

A highly secured Web application?

From the diagram above, it appears that the e-business application is very secure with all the layering and firewalls. But in reality, this is just one aspect of security, specifically network security. If the application itself is vulnerable, the above structure doesn’t give any security to the system.

I will explain this with a metaphor. Let us assume that we have a bank and the bank is protected by 3 checkpoints. The checkpoints in this case are the firewalls pictured. At the checkpoint guards verify that only authorized vehicles(http protocol) can enter the bank. However, they do not look at the passengers in the vehicle. They are ok if the vehicle itself is authorized. Now it is up to the people sitting inside the bank (application running on the application servers) to verify that only authorized people(valid requests) who came via the authorized vehicles(http) can enter the bank and do something that they are authorized(authorization, validation). In this metaphor, the vehicle stands for http protocol and the passengers are the request data that passes inside http.

Introduction

Web applications are now everywhere. These range from Web sites that provide mark list/exam results to online banking sites. Nowadays a large number of individuals and bloggers are also hosting full fledged Web applications such as WordPress or Joomla. Proliferation  of Web applications is also leading to increased security issues. Many of these applications are built or rolled out by people who doesn’t have a solid understanding of the security issues and the ways in which attackers can get hold of sensitive data. Even in the popular applications such as WordPress or Drupal, it is not unusual to come across a serious security vulnerability. The situation becomes scary when they are complimented by a large number of substandard components known affectionately as "plugins".

Since most enterprise Web applications directly access sensitive databases holding an entire corporate’s data, it is very essential to protect it as strongly as possible. The weakest link usually is the Web application itself.  Your company’s network may be using bullet proof security systems including firewalls and other mechanisms, but if the Web application itself is vulnerable all these are useless.

Following is a simple security checklist against which all Web application features must be evaluated. I have tried to keep the list to a maximum of 10 items since that is the only way to ensure that a checklist will be followed in practice. This list is good enough to tackle 80% of serious Web application security issues.

Web application security checklist

1. Are all the user input data validated at server side?

Improper user input data validation is one of the biggest security issues with Web applications. In many cases, proper validation will be done only on the client side. Usually JavaScript is used for client side validation. However, any script kiddie can easily bypass JavaScript validation using simple proxy tools(for example, WebScarab tool or TamperIE). These tools sit between the browser and the server and can selectively remove or modify the JavaScript inserted by the server application.

It is very important to have client side validation from a usability standpoint. But at the same time all validations must be replicated on the server side. There is no guarantee that client validations will be executed. Also the following things must be kept in mind,

  • Hidden fields can be easily modified by the application user(using tools). So if you don’t want someone to change it, it must be either validated or protected by encryption.
  • Disabled fields also can be changed by application user. You should never assume that they will not change.
  • If you want to maintain application state on the client side (for application scalability) ensure that it is encrypted using a strong algorithm. Using weak schemes like base64 encoding is lame.
  • In some applications to improve usability the server side validation is done using Ajax. However it is of no use if the same is not applied again during form submission.
  • For more robust behavior, replicate validation at each layer of the application. See Design by Contract.

2. Is the authentication mechanism robust & reliable?

The problem with Web application security is that a single weak link is enough to compromise the entire application. You might have the strongest security implementation, but if the user password is same as the user name, it could be brute forced in the first attempt itself! Here are some important considerations for authentication mechanism,

  • Never allow weak passwords. A password should contain characters, numbers and special characters.
  • Never allow more than 5 failed logins since such a thing will encourage a simple brute force attack. Introduce a temporary lock for the user id for the same IP.
  • Ensure that authentication error messages are not verbose.  Never indicate whether a user id is valid as it will facilitate the attacker in enumerating valid user ids in the system.
  • For critical administrative authentication, you can validate that the user is logging in from a select set of internal IP addresses.
  • Ensure that the authentication is always done using HTTPS. You should also ensure that the login screen itself is rendered using HTTPS. It is easy to intercept user id/password transmitted over HTTP.
  • Review change password, forgot password features for any security vulnerabilities. If the forgot password allows a user to change or view a password just by entering his date of birth, it is not very secure!
  • Review the authentication code for any logical security loop holes. This requires line by line analysis.
  • And finally don’t use a GET request for login process. Even today I have seen many live applications(Globat Web hosting company, HostGator Web hosting etc.) sending user id and password in a GET request. This means that your password will be available in proxy logs, router logs, browser logs and in fact almost everywhere!
  • Ensure that the password is stored in the database using a digest algorithm such as MD5. Recently my land phone provider (BSNL) called me and told me my current password! Good god, it was my online banking password as well!

3. Are there any security vulnerabilities in third party components?

Web applications especially Java Web applications, tend to use a lot of third party components. These include MVC frameworks such as Struts2, Spring etc. or ORM mapping tools such as Hibernate, TopLink or other tools such as Log4J for application logging. Most of these are open source projects. It is quite possible that these components have inherent security vulnerabilities. This in turn makes your application vulnerable to hacking attacks.

It is very important to evaluate any third party component used in your Web application against security vulnerabilities. Also you need to monitor for any newly identified security vulnerability and if any are reported, should apply the patch or upgrade immediately. Sometimes fixing such vulnerabilities are not easy since the new version of the third party component might break your application functionality.

For example, Struts 2.0.11 version contains a directory traversal vulnerability and it is fixed in Struts 2.0.12. If you go to the Struts2 issues list and search for "security" you will come across security vulnerabilities affecting various versions of Struts2. The same approach can be taken for other third party components.

4. Are all the queries/parameters protected against SQL injection vulnerabilities?

This is one of the oldest tricks in Web application hacking, but is surprisingly effective even today. Usually this happens when the user input is not properly sanitized before passing it to an SQL query as a query parameter. This type of vulnerability can be very dangerous and can potentially lead to all types of application attacks. Here is a trivial yet interesting SQL injection example,

Assume that your insurance application displays a list of insurance agents given a state code. The state is selected from a combo box. Assume that the application URL used is,

http://servername/portal/showAgents.action?statecode=KL

The application sends the state code in the URL which is submitted to the server. Let us say that the state selected is "Kerala" and the code is "KL".

In the Java database access object, following query is executed,

String query = "SELECT name, address FROM AGENTS WHERE STATE=’"+stateCode+"’";

executeQuery(query);

So the actual SQL query is,

SELECT name, address FROM AGENTS WHERE STATE = ‘KL’

Now I change the URL manually and submit it as given below,

http://servername/portal/showAgents.action?statecode=KL’%20UNION%20SELECT%20USERNAME,PASSWORD%20FROM%20USERS

Note that the %20 is the URL encoded form of a space character. The resultant query is (if no sanitization of the request parameter statecode is done),

SELECT name, address FROM AGENTS WHERE STATE = ‘KL’ UNION SELECT USERNAME, PASSWORD FROM USERS

The "–" character at the end of the string causes the SQL processing engine to ignore the additional single quote added by the program.

Now in the agent listing screen, you will see all the agents in Kerala plus all the user id/passwords stored in the database! So if the password itself is not MD5 digested, this opens up access to all user accounts in the system!

This exploit assumes two things – That we know the table which contains user details is "USERS" and also that the retrieved parameter count from agents table is two and that they are strings. Let us see how we can find these!

For the return types and count, we can use a brute force approach. We will start with SELECT NULL FROM DUAL and then successively add NULL fields to the SELECT clause till those fields appear as an extra row in the results.

Step 1 : Injected code = ‘%20UNION%20SELECT%20NULL%20FROM%20DUAL–

Response = error. This means that agent query is expecting more than one return parameter in query.

Step 2: Injected code = ‘%20UNION%20SELECT%20NULL,NULL%20FROM%20DUAL–

Response = displays additional blank row. This means that we found the number of parameters for the agent is two! We can use the same error approach to find the return types also.

Now since we found the number of parameters and their types using brute force, we can easily find the table for users by querying the database meta data. For oracle, this is a simple query,

select object_name,object_type FROM user_objects

Now we use the same in our SQL injected code to see the the tables in the applications. It is fairly trivial then to identify that the table we are looking for is "USERS"!

Injected code = ‘%20UNION%20SELECT%20object_name,object_type%20FROM%20user_objects–

Response = the list of database tables are displayed in agent listing!

Here some thing that you can do to minimize SQL injection vulnerabilities,

  • Never construct SQL queries by concatenating strings. Use parameterized queries in which application API is used to set SQL parameters. For example, use prepared statement in Java.
  • Implement access controls in database.  In the above case, the agent listing feature is available for all users including non-authenticated users. In such cases, the database user id used for database access should have only read access and that too on the AGENTS table alone!
  • Even if a single oracle user id is used for all authenticated users, ensure that it has proper access restrictions. You don’t want an attacker to drop your database! You can also restrict access to database meta data.

5. Are all the application screens tested for XSS (cross site scripting) vulnerabilities?

Cross site scripting is another common method of attacking Web applications. Surprisingly a large number of Web applications are vulnerable to this.

Cross site scripting vulnerability occurs when a client supplied parameter is processed by the server and is output to the client again without any sanitization. For a clever attacker, this gives opportunities to inject behavior into the attacked application without the user realizing it. If cross site scripting vulnerability is present in a social Web site, it can quickly evolve into a distributed virus (see Samy XSS worm).

Clever cross site scripting attacks can lead to huge security issues.  Consider the following scenario,

Step 1: Attacker finds XSS vulnerability in application "X".

Step 2: Attacker devises an application "X" URL which can exploit the vulnerability.

Step 3. Attacker send the application "X" URL to a valid user of application "X", using a forged email.

Step 4: User clicks on the URL since the URL is legitimate. However due to the XSS vulnerability, this executes malicious code which sends user’s session cookie to attacker’s server.

Step 5: Attacker gets hold of user’s session cookie and uses it to log in to the application "X". Goes on to cause mayhem.

You can minimize cross site scripting vulnerabilities by,

  • Validate all input and sanitize them. If you capture client input and then display it back, always double check the sanitization done on the output string.  You should always remove browser scripts such as JavaScript fragments from output.
  • If your output can contain valid scripting (for example, when a user pastes a code listing to a forum) ensure that they are HTML character encoded.  Hence a character like < becomes &lt;

6. Are all the access controls enforced on server controller classes?

In many Web applications, access controls are only skin deep. Usually access controls are enforced by a disabled button or a missing button or a missing link/menu. However for a Web application hacker, this doesn’t pose any challenge at all.

Access controls are of two type. Either it is operation level access control (vertical access control) or data level access control (horizontal access control). Vertical access control means restricting access to a screen or a feature.  Horizontal access control means granting access to the screen, but limiting what data can be accessed through the screen. Usually a combination of this is applied.

For example, only an underwriter will have access to edit policy screen in an insurance application. This is vertical access control. However only a *Motor* underwriter can edit a motor policy. This is called horizontal access control.

In many cases, horizontal access control is usually applied only to the listing screen. This means that the *Motor* underwriter can view only the Motor policies in the policy listing. But the developer assumes that the edit screen is invoked only from listing and hence doesn’t put any horizontal access control in the edit screen. Assume that the URL for editing a policy is,

http://servername/portal/editPolicy.action?policyid=10

Now if the horizontal access is not properly implemented in the edit policy controller object, you can edit any policy by changing the "policyid" URL parameter!

In the case of vertical access control, usually the user who doesn’t have the access is not shown relevant the menu or link. However if he is able to guess the URL, he can get into the screen. For example, you had access to the URL till yesterday and today your privilege to that screen is revoked. However since you have the URL in favorites list of your browser, you can still access it!

Here are some guidelines for implementing vertical/horizontal access control properly,

  • Create a centralized access control unit and ensure that all controller classes are accessible only after going through it.
  • Never use client supplied parameter for access control. Always look for the user identity from the session and derive access controls from it.
  • Hiding links/menus or action buttons are only for usability. This itself cannot be used for access control.

7. Are all the upload/download application features secure enough?

File download and upload functionality in a Web application usually is a gold mine for hackers. There could be a number of vulnerabilities that can be used access privileged data or even bring down the server machine by invoking operating system commands.  This is achieved by a group of vulnerabilities collectively known as directory traversal vulnerabilities. Here is an example,

Assume that an application screen allows downloading a file. Assume that the URL used is,

http://servername/portal/downloadFile.action?file=a.txt

Typically this is mapped to a folder by prefixing a path such as "C:/downloads/". So the absolute path becomes

C:/downloads/a.txt

What happens if you invoke the following URL?

http://servername/portal/downloadFile.action?file=../windows/win.ini

If there is no validation or constraints applied on the server side, this will return the operating system file "win.ini" to the user! In fact any file on the server can be accessed using this mechanism!

The same vulnerability can exist in upload also. But it is more destructive since it can potentially overwrite operating system files!

Here are some tips to prevent directory traversal attacks,

  • Avoid passing file names directly to download component from the client side. Instead keep a mapping between identifiers and file names and only accept file identifiers from the client side. This means that the access is limited to a small set.
  • You can also use a virtual mapped drive to store files. This ensures that no other drives can be accessed using download or upload components. In Linux you can use the chrooted environment to emulate this.
  • File names if accessed should always be checked for path traversal characters or other invalid character. If invalid, reject the request immediately.

8. Are all the application logic modules reviewed for security vulnerabilities?

In many cases, Web application attackers utilize application logic flaws to get into the system. However it is very difficult to specifically point out a single logical flaw which can cause security vulnerabilities.  It is very essential that someone who has expertise in Web application security reviews each and every critical application component. Here are some critical areas to consider,

  • Double check areas dealing with user authentication and authorization (change password, forgot password etc.).
  • Check what happens when a multi-step process is executed out of step. For example, assume a scenario which includes sequential steps search, view and edit. What happens if edit is directly invoked from search (using hacking tools)?
  • Is the same code component (logic) used across multiple application screens?  What are the possible security loopholes in such scenarios?
  • How are the business rules enforced? Can an invalid input (a negative discount amount for example) break it?
  • Can any of the application features be abused using bulk requests?
  • Is any of the debug messages or error messages revealing useful information for a Web application hacker?

9. Does the application maintain audit logs?

Even after taking all the precautions, sometimes hackers do get into the system. The only way to track such attacks is to have a solid audit log for all critical user actions. This log must be kept in a secure location and must backed up periodically to a separate location.

10. Does the application has a facility for administrator alerts?

It is very critical to issue alerts to administrators whenever something unusual is detected in the Web application. This includes but is not limited to,

  • Unusually large number of requests from a user or an IP address.
  • Large number of access control errors from a single user id.
  • Attempt to pass invalid data programmatically. For example, changed hidden field value or changed disable field value. This clearly indicates use of hacking tools.

Conclusion

It is not easy to have a fool proof defense against a determined Web application hacker. But the above guidelines/checklist can help in getting rid of "get rich quick" type of hackers. In fact the only true defense is the fear that if someone breaks into a Web application, he may get prosecuted and put in jail 🙂

Further Reading & Resources

This article is intended only as an overview of the interesting field of Web application security. Each technique given above has a lot of subtle variations which can be used to exploit even highly protected Web applications. See the following resources for more pointers,


March 25, 2009 | Posted in Programming No Comments » | By Jayson

Leave a Comment