Web Application Penetration Testing

Web application security entails a unique set of challenges, not least that complex applications containing sensitive information are routinely exposed to a wide and untrusted user base. In addition, many web applications involve the integration of disparate, sometimes legacy, data sources that have no single authentication or authorisation mechanism. For this reason, web application security remains a key area of research, with a recent study by F5 Networks revealing that 72% of attacks take place at the application level.

Sec-Tec provides a comprehensive yet cost effective web application penetration testing service that utilises a combination of the very best automated and manual assessment methods to provide a thorough, objective review of your business-critical systems. Our qualified consultants adhere to a number of internationally recognised web application penetration testing standards and guidelines from organisations such as OWASP to ensure that all major vulnerability categories are tested as appropriate.

What We Test For

The following presents a general overview of the types of vulnerabilities we test for. Details of the initial scoping and reporting stages can be found on our general penetration testing page.

Injection vulnerabilities

Whenever a web application utilises user supplied input to connect to a backend data source, the potential for an injection vulnerability exists. Although injection vulnerabilities are most often associated with SQL databases, other data sources such as LDAP directories can be equally vulnerable.

A login page such as this will often generate a backend SQL query that looks something like:

SELECT * FROM Users WHERE Name =‘INPUT’ AND Pass =‘INPUT’

The single quote characters are delimiters that indicate the boundary between user supplied input and SQL syntax. In order to ensure the application remains secure, it is vital that the user cannot modify the SQL syntax by entering delimiters into the application input.

Consider the following input into the same login form:

The user has entered a SQL delimiter character to “break out” of the user input space and into the SQL syntax. The generated SQL syntax now looks like this:

SELECT * FROM Users WHERE Name =‘’ OR ‘1’=‘1’ AND Pass =‘’ OR ‘1’=‘1’

The SQL server evaluates the SQL query, finds it doesn’t match the apparently blank user input, but concedes that 1 does indeed equal 1, and logs the user into the application with the privileges of the first user in the SQL table – often the user with administrative privileges.

The above is a simplified example of a “classic” SQL injection attack, the type we find during penetration testing projects on an almost daily basis. A number of lesser known variants exist, however:

Numeric Injection

If a web application uses numeric parameters, then SQL injection can be just as easy to identify. This is because even if the application filters the SQL delimiters in the example above, it may be vulnerable to numeric SQL injection. This can also be a problem in applications developed in weakly typed languages.

Consider the following URL:

https://targetsite.co.uk/viewProduct.php?ID=7

If the ID variable above is cast as a numeric parameter, then discovering a numeric SQL injection vulnerability may be as simple as modifying the URL to:

https://targetsite.co.uk/viewProduct.php?ID=7 OR 1=1

Blind SQL injection

Historically, the simplest way to identify SQL injection vulnerabilities within web applications was to enter one or more ‘ strings within each application variable, and check for the presence of an SQL syntax error message being returned. As time went on, web applications increasingly began to follow best practice and conceal error messages from end users. This can mask the presence of an SQL injection vulnerability that would normally be identified through the deliberate generation and review of SQL syntax error messages, but is in no way a root-cause fix. A number of methods have subsequently been developed to identify SQL injection vulnerabilities, even when they are masked in this way. One of the most common is using SLEEP, WAIT FOR DELAY and DBMS_LOCK.SLEEP requests, and monitoring the time delay on the page being returned.

LDAP injection

As previously stated, injection vulnerabilities are not limited to SQL. Authentication pages that perform an LDAP backend lookup can often be bypassed by entering an asterisk (*) in the username and password fields.

Insecure Authentication and Session Management

Once a user has logged into a web application, they are no longer identified by their username/password/two-factor authentication token. Almost all modern web applications track users via their session token: that random string of text temporarily stored in the browser, often referred to as a cookie. As a result, no matter how good your password or other authentication mechanism may be, if the way in which session tokens are generated, transferred or stored is flawed, potential impersonation vulnerabilities may occur.

This is the way in which a typical web application authenticates a user:

Many web applications make apparently innocuous deviations from the above process, sometimes introducing vulnerabilities. Take for example the following authentication process:

On the surface, this is largely similar to the previous example, with only a couple of small changes. Firstly, the user visits the unencrypted HTTP:// version of the site, because, as a typical end-user, typing HTTPS:// specifically into the address bar isn’t a familiar habit. Secondly, the server sets the cookie immediately, so that pre-authentication user activity can also be tracked, and then “upgrades” the cookie’s status to authenticated when the user successfully authenticates. Perhaps surprisingly, these two apparently minor changes have considerably reduced the security of the authentication mechanism:

  1. Even though the user authenticates over an encrypted connection, the session token used for the transaction is originally set over an unencrypted connection. This makes the authentication process vulnerable to network sniffing, despite the use of an encrypted connection for the transmission of user credentials. The attacker simply sniffs the initial session token, waits a reasonable amount of time for the user to authenticate (which cannot be monitored due to the use of the subsequently encrypted connection) and then attempts to access the web application with the sniffed session token.
  2. Because the session token is set over an unencrypted connection, depending on its expiry settings, it may be re-sent over an unencrypted connection if the user revisits the unencrypted HTTP:// section of the site. This could happen, for example, in the case of a browser crash, or after a lunch break. Protections such as the use of the SECURE flag when setting session tokens can prevent this.

The above is one example of a number of pitfalls with authentication and session management that we frequently encounter during penetration tests. Other vulnerabilities include:

Session fixation

Similar to the above attack, session fixation vulnerabilities exploit web applications that allow malicious users to influence the entropy of session tokens. If a potential victim can be coerced into authenticating to the website with a session token predetermined by the attacker, the attacker can impersonate that user.

Insufficient session timeout

Often a web application will not teardown an expired session from the state pool properly, but simply forward the user onto, for example, the login page to re-authenticate. If a user simply presses the back button within the browser, then access to the web application is regained. Design errors such as this can also lead to audit disparities, as the session has officially expired, but users are still able to access the application.

A good penetration test will look at session management in detail, and make recommendations as to how the authentication process overall may be improved.

Cross-site Scripting vulnerabilities (aka XSS)

Cross site scripting (XSS) vulnerabilities occur when a web application echoes user supplied data back to the browser, but does not escape the user supplied data for script tags. As a result, an attacker can bury malicious script code such as JavaScript within the application, which will execute within the user’s browser upon retrieval.

Let’s take a look at a fictitious medical application. The application is used for patient management. Patients’ details are entered into the system and monitored, patients’ records are updated, etc.

A patient’s entry may look something like this

And listing patients within the system may look something like this:

But imagine that, instead of entering “Suzie Franklin”, we entered some JavaScript into the field where the the patient’s name would normally be:

Later, when another user of the system lists the patients, the JavaScript patient name will be executed within the browser, because that’s what browsers do with JavaScript, they execute it:

The JavaScript could attempt to perform a number of malicious actions, from stealing session tokens to stealing keystrokes; the actual attacks possible are determined by technical factors.

Types of XSS vulnerability

XSS vulnerabilities effectively allow attackers to embed malicious JavaScript within an application, which will be executed within some unsuspecting user’s browser. They are often exploited in one of three ways:

Reflected XSS

This is where the application immediately reflects the user’s input. Perhaps the application echoes back the user’s name as part of a welcome message. Or a search function returns the result along with a “You searched for: XYZ” message. An attacker will often exploit these by creating a URL containing the malicious JavaScript

www.targetsite.co.uk/search.asp?search=<script>maliciousJavaScript</script>

and sending it to potential victims.

Stored XSS

This is the medical patient example above. The malicious JavaScript payload is not reflected immediately, but is stored within the application’s data. It may be days, weeks, months or years until someone views, and hence executes, the malicious payload within their browser.

DOM based XSS

XSS vulnerabilities do not have to exist within the server-side code, but can also exist within the browser-side DOM. If the DOM environment is modified within the browser, then the client-side code can be made to execute in an unanticipated manner, resulting in execution of the malicious code.

Insecure Direct Object Access

This type of vulnerability occurs when one of more parts of a web application, perhaps even a single page, do not enforce the authentication mechanism used by the rest of the application. As a result, it can often be possible to access specific pages without valid credentials.

Let’s look at an example web application. Typical user behaviour within the application is as follows:

Almost all penetration testing is based around causing systems, applications or even people to behave in unexpected ways. This is done by putting the target in a scenario not envisaged by the application designers or developers, and one way we might do that is not to follow the normal user flow, but simply to go straight to: www.site.com/report.aspx in a web browser.

If the /report.aspx script does not check for a valid authentication token, then it will facilitate access without any authentication credentials. The developer’s thinking was that the only way a user would access /report.aspx was by clicking on a link in /main.aspx, and the only way you could get to /main.aspx was by successfully authenticating. This may seem unlikely in the real world, but our penetration testing service finds dozens of such flaws every year in web application penetration tests.

Insecure Direct Object Access vulnerabilities are particularly common in applications that have had new functionality grafted on and hardware devices that utilise web management front-ends.

Misconfiguration vulnerabilities

This category of testing covers a myriad of potential security issues including:

Default Accounts

Many middleware solutions, content management systems (CMS) and off-the-shelf web applications ship with default or guest accounts that can easily be left enabled if no formal hardening procedure exists within the organisation. Attackers will often search for such accounts using automated scripts.

Superfluous attack surface

If it isn’t there, it can’t be hacked. This simple premise cannot be overstated. Web applications often ship with publicly accessible administrator pages, plugins and other superfluous attack surfaces that can make an otherwise secure web application vulnerable. For example, a popular CMS in use worldwide has over 43,000 plugins available, each of which can introduce unexpected vulnerabilities. Even apparently innocuous JavaScript libraries such as JQuery have had numerous vulnerabilities in the past. For each component within the web application, we need to ask:

  • Is it needed? Can we disable it?
  • Are there any known vulnerabilities present in the extensions used?
  • Can we restrict it to trusted entities only?
  • How will we update and manage the necessary extensions?

Insufficient Encryption

Encryption, when properly implemented, can be your last defence. It can be the difference between an exfiltrated database containing thousands of user records being sold on the Dark Web, or being completely useless. Unfortunately, many organisations still subscribe to the concept that any encryption is good encryption, but like many technical security matters, the truth is slightly more complex. In addition, utilising insufficient encryption can lull organisations into a false sense of security, overemphasising the level of protection in place.

Penetration testing can help organisations identify common encryption flaws such as:

Use of deprecated encryption protocols

Older and flawed encryption mechanisms such as SSLv2, SSLv3 and TLS 1.0 contain well documented weaknesses that can, in certain circumstances, yield a capable attacker access to normally encrypted data. These protocols can normally be disabled with minimal impact, as newer encryption protocols such as TLS 1.1 and TLS 1.2 have been supported by browsers for some time. Supporting deprecated protocols can also mean an automatic failure of internationally recognised security standards such a4 PCIDSS

Inadequate encryption coverage

As mentioned above, sites that switch between unencrypted and encrypted services for the protection of sensitive data must do so properly in order to ensure session tokens are not transmitted in plaintext.

Inadequate backend encryption

Sensitive data within backend databases should be encrypted, hashed and salted as appropriate to limit the damage from a wide range of both online and physical attacks, such as the loss of backup tapes. Clues obtained during penetration testing of a web application, such as the ability to retrieve one’s password, indicate that the backend encryption is insufficient and requires improvement.

Self-signed certificates

Self-signed certificates can seem like an easy and cheap alternative to those signed by an appropriate certificate authority. A major issue with self-signed digital certificates is that they do not adequately guard against man-in-the-middle attacks, which can often be trivially exploited over local area networks via ARP poisoning attacks, with freely available penetration testing tools such as Cain & Abel. This facilitates access to the normally encrypted network traffic, and causes no readily identifiable behaviour change to the end user, as self-signed digital certificates generate the same browser warning upon connection as the attacker does.

Insufficient authorisation enforcement

Authentication is the process of identifying who a user is. Authorisation is the process of ascertaining what the user can do within the application. Many software specifications are written in a very enabling manner, with little thought to what a user should not be able to do. This can often lead to an insufficient authorisation model, in which a user can perform one or more actions within a web application that should only be possible for more privileged user accounts.

Let’s take an example:

The following is a simple authorisation model for a web application which consists of five levels of user:

This will often be implemented (incorrectly, as shown below) by providing each level of user with an interface with missing buttons:

Each button will map to an action within the application.

Now if we look at the Consultant’s user interface, we can see an extra button for changing drug dosages:

This extra button will normally generate a GET or POST request to the web application, just as the other buttons do. For example, the extra “change dosage” functionality may generate the following GET request:

https://www.webapp.com/action?dosagechange&patient=Susan%20Jacobs&Newdosage=20mg

If the application has been created without a proper authorisation model, then it will rely solely on the fact that the button is not present within the user interface. But if, for example, a Doctor knows the URL structure, and makes the above request directly within a browser, the dosage change will happen. This is because the application’s authentication and authorisation asks only two questions:

  1. Is the request syntactically valid?
  2. Is the user authenticated?

If both these conditions are met, then the request is processed. The application should check:

  1. Is the request syntactically valid?
  2. Is the user authenticated?
  3. Is the level of user making the request allowed to perform that function?

This all-important third question is the difference between a flat authentication model, which relies solely on a user’s knowledge – or lack of knowledge – of an application’s URL structure, and a properly enforced user authorisation model.

During a web application penetration test, Sec-Tec consultants will often utilise multiple sets of test credentials to identify this type of vulnerability, and make recommendations for a properly implemented authorisation model.

Cross-site request forgery

Web applications that do not utilise CSRF tokens within generated pages can be vulnerable to cross site request forgery attacks, which involve tricking an authenticated user of a web application into clicking on a link within, for example, an email. Because the user is already authenticated to the application at the point of clicking on the link, the action requested by the link in the email is performed.

Let’s take the example of a banking web application:

www.hackmebank.com/action?=transfer&source=28774211&dest=88117323&amount=110.00

The above is an (over) simplified example of a banking application that uses the above URL to transfer £110.00 from account no. 28774211 to account no. 88117323. This is intended, normal user activity.

However, the attacker, as a fellow customer of the bank, has learnt the URL structure and sends a large number of potential bank customers an email containing the following link:

www.hackmebank.com/action?=transfer&source=28774211&dest=55447642&amount=110.00

Account no. 55447642 is the attacker’s account. If one or more users of the online banking application click on the above link in an email, while they are logged in to the application, then they will make a valid request to the web application, which will transfer the money. In fact, the attacker doesn’t really need to convince a user to click on an email, it may well be sufficient to embed an image or IFRAME tag within the email that the client will attempt to retrieve:

<img src="www.hackmebank.com/action?=transfer&source=28774211&dest=55447642&amount=110.00" width="5" height="15" border="20">

It doesn’t matter that the image is nonexistent, the request will be made and the action performed.

CSRF vulnerabilities can be prevented in a number of ways, and thorough penetration testing will recommend the best remedial action to adopt, considering the technologies and skillsets available.

Insecure Redirects

Web applications frequently use redirects and forwarding to guide users to different sections, pages or even entirely different websites. While these forwarders are often transparent to the end user, if not implemented correctly, they can expose a web application to impersonation attacks.

Let’s consider an example web application:

www.targetsite.co.uk/login.php?success=https://www.targetsite.co.uk/main.php

This login page uses a variable called “success” to tell the application where to redirect a user upon a successful login. In this case, the web application will forward the user’s browser to that URL upon a successful authentication.

This type of redirect will grab the attention of any penetration tester, due to the fact that if an attacker builds a fake login page which looks identical to the legitimate application, and creates a link to the legitimate application that redirects to the malicious site, then an impersonation attack may be possible:

www.targetsite.co.uk/login.php?success=http://www.nastysite.co.uk/main.php

If legitimate users of the site can be convinced to click on the above link, they will be forwarded to the legitimate site. But, upon successful authentication, the user will then be silently forwarded to the identical looking malicious site, which will look to the user like a failed authentication attempt. A second authentication attempt (this time to the malicious site) will yield the attacker the legitimate authentication credentials.

Not all redirects are inherently insecure, but, as with many aspects of web application security, they take a little planning and forethought to prevent an unnecessary increase in risk.

Web application logic flaws

Of all the categories of vulnerability in web applications, logic flaws are amongst the most interesting. This is because they have two distinctive features:

  1. They are unique to each specific application’s context
  2. They cannot be readily identified using automated technology

In order to understand logic flaws in applications, we’ll take the case of a fictitious shopping cart. The shopping cart accepts requests as follows:

www.vulnerablecart.co.uk/order.asp?quantity=1&productid=17

Behind the scenes, the server-side code calculates the amount owed via:

amount owed = quantity = 1 x price of product id 17 = £23.99

1 x 23.99 = 23.99

This would seem logical, and indeed it is. But the quantity value is an integer, and integers can sometimes be cast as signed, which means that it can be negative. If the developer has made the simple oversight of casting an unsigned integer, an attacker can make the following request:

www.vulnerablecart.co.uk/order.asp?quantity=-1&productid=17

The server-side code performs the same calculation:

-1 x 23.99 = -23.99

The attacker owes -23.99, which equals a refund of 23.99. The attacker completes the purchasing process, and is £23.99 richer for its purchase.

In summary

Web application penetration testing is a huge subject, which we could write a lot more about, but it need not be deemed as an impossible burden. Security goals and objectives can often be met if basic best practice is adopted throughout the project lifecycle, and regular security assessments form part of that project lifecycle. Whatever the size or complexity of your application security requirements, Sec-Tec can provide an assessment service to fit.

For more information :

Sec-Tec Penetration Testing Services Page