When it comes to web application testing, there’s arguably no better reference guide than the OWASP Top 10. Based on a larger number of data sets and opinions surveyed from a plethora of industry professionals, it ranks the ten most severe security weaknesses in web applications. This format makes it invaluable in both red and blue team engagements, as well as helping to improve internet security on a large scale by offering mitigation steps for each identified vulnerability.
Given the huge amount of time invested into producing the OWASP Top 10, it isn’t an annual document. There have been three released in this decade — 2010, 2013 and 2017 — and this breathing time between releases also helps to highlight how the prevalence of different web app vulnerabilities dynamically evolves over time (as shown by the frequent re-working of the Top 10).
In this first article in a two-part series, we’ll give a simple overview of the first 5 vulnerabilities listed in the OWASP Top 10, how to mitigate them, as well as featuring real-world examples from disclosed bug reports to show the exploits in action. Let’s get into it!
What is it?
Topping the list for the third time in a row, an injection vulnerability is when an attacker sends malicious data as part of a command or query to an interpreter. If successful, this malicious input will be executed as code, causing the interpreter to execute unintended commands or reveal data which should otherwise be inaccessible.
When Does it Happen?
Ultimately, the most common cause of injection vulnerabilities results from a website’s failure to filter, validate or sanitise a user’s input. Web apps will always be presented with the following predicament: enabling user input is required for the application to function as intended, but there will always be malicious users who attempt to exploit this reality by sending unexpected or unintended data.
The other major cause of injection attacks is due to a failure to implement parameterisation (we’ll talk more about this in the following section). Particularly vulnerable queries or commands are those which concatenate user input directly into the call, allowing an attacker to alter the intended function with malicious data.
How to Mitigate Injection Attacks
Filtering, Validating, Encoding and Escaping
Blacklisting: the process of rejecting/stripping known ‘bad’ input. However, this has limitations, since you’re essentially always fighting an uphill battle against attackers with this method of mitigation. Let’s say a developer strips any user input containing " or ' as a means of preventing query alteration. An attacker could encode these characters — say with URL encoding — to %22 or %27 in order to circumvent the blacklisting. For this reason, blacklisting is never going to be an effective mitigation method when used alone.
Whitelisting: the process of only accepting desired input. In the case of an e-mail address, this may have certain restrictions such as requiring an @symbol, . as well as potentially limiting length. In practice though, this can become difficult to implement in web apps where the intended function by design should allow the user to input a broad range of characters — such as a job posting website.
Encoding: the process of encoding ‘bad’ characters after they have been submitted by the user to make them harmless. The most common example of this is by using HTML entity encoding, whereby characters such as 'and " would become ' and " respectively.
Escaping: the process of ‘escaping’ specalised characters (such as "’%)to make them be interpreted as string literals rather than functioning in their intended way. Typically this is done with backslashes but varies depending upon the language at play.
A combination of some or all of the above would be a recommended starting step to preventing injection attacks.
2. Query Parameterisation
As recommended by OWASP, using parameterised queries is the best — and cleanest — way to mitigate SQL injection attacks (in combination with the aforementioned mitigation steps). Also known as a prepared statement, it is a query whereby only the parameters are supplied at execution, heavily reducing the ability for a determined attacker to alter or ‘break’ the query itself. Below is a simple example of a parameterised query from W3’s page on SQLi:
SQL injection due to controllable $conversationID parameter (exploit is described in detail with relevant source code via the public disclosure on HackerOne).
Another SQL injection — this time in a WordPress plugin called Formidable Pro which was used by tech company Grab. Earning a $4,500 payout, the initial report posted by the security researcher was extremely detailed and worth looking at for getting a closer look at advanced sqlmap.py usage.
2. Broken Authentication
What is it?
This class of vulnerability covers any weaknesses in the authentication/session management methodology. These are often poorly implemented in web apps, giving attackers access to account(s) and/or data that they otherwise shouldn’t be authorised to view.
When Does it Happen?
There are a variety of contributing factors to Broken Authentication, including:
Failure to deny automated attacks (brute-forcing, credential stuffing etc).
Allows users to have weak or well-known passwords such as password123.
Exposes username/password information based on error messages/response times.
Implements weak credential recovery and forgotten-password measures. (An interesting article on the weak nature of security questions was published by the NCSC here).
Exposes Session IDs in URLs.
Fails to implement Session ID switching after a user logs in.
Sessions remain active for too long — after a session has exited and remained inactive for a significant period of time.
How to Mitigate Broken Authentication
The good news regarding Broken Authentication is that it can be significantly improved with just a couple of changes. The biggest of these are:
Two-factor authentication (or 2FA) for all logins. This prevents accounts from being brute-forced so easily.
Ensuring users have sufficiently-strong passwords by implementing validation on password creation. Things like minimum password length and required special characters is a good way to increase protection. If any of you have ever signed up for an account at BugCrowd, then you’ll know exactly what it’s like to use a site that implements rigorous validation checks on passwords!
There are numerous other steps that can be taken to further reduce the likelihood of Broken Authentication exploits:
Rate-limit login attempts. While this is usually done via tracking cookies or IP addresses which a determined attacker can spoof (or simply acquire an entire VPS for an alarmingly affordable price), it is still another hurdle which will help prevent exploitation.
In the same way, a response delay (with PHP using sleep()) can be implemented to further slow an attacker’s brute-force attempts.
Blacklist IPs from which suspicious activity has been detected.
Cross-reference user passwords against recent/common password leaks from other data breaches, and notify any users which are making use of passwords which are frequently applied in brute-force attempts.
Make use of a server-side, built-in session manager which generates a random, high-entropy Session ID after a user has logged in. don’t ever include this ID in URLs and ensure that it is invalidated after a period of inactivity.
Uber failed to rate-limit the https://biz.uber.com/confirm endpoint, which would allow an attacker to brute-force business accounts and take rides on behalf of them. This vulnerability was identified and reported on HackerOne — the public disclosure can be viewed here.
Erroneous logic in Shopify’s web app meant that an attacker could be granted ‘collaborator’ access to any shop without authentication. This could be exploited by creating two partner accounts which shared the same business e-mail, giving an attacker login access to any store with full permissions. Deservedly paying a large reward ($20,000), the public disclosure can be viewed here.
3. Sensitive Data Exposure
What is it?
As the name indicates, this vulnerability is when a web application fails to sufficiently protect sensitive data — namely personally identifiable information — which includes (but is not limited to) data points like e-mail addresses, postal addresses, banking information, dates of birth and telephone numbers.
When Does it Happen?
While recent legal changes such as GDPR and the longstanding PCI DSSshould ensure that sensitive data is not exposed, a significant percentage of web applications fail to meet these requirements. Sites are particularly at risk if:
Data is transmitted in clear text (over protocols such as HTTP, FTP and SMTP).
Sensitive data is stored server-side in clear text.
Known-to-be weak cryptographic algorithms such as MD5 or SHA-1 are used for encryption.
Default/weak cryptographic keys are used.
How to Mitigate Sensitive Data Exposure Attacks
It’s worth stressing that when it comes to sensitive data, the following mitigation steps should be followed at a minimum. After all, most attackers are prioritising sensitive data as a target when it comes to exploiting vulnerabilities given how lucrative of a market it is on the dark web.
Identify all data which could be considered ‘sensitive’. Note where and how it is stored, as well as if and how it is transferred.
Do not store sensitive data which is no longer needed.
Use tokenisation for sensitive financial data (you can read more about this and its relation to PCI DSS compliance here).
Make sure that all stored sensitive data is encrypted with strong algorithms using cryptographic keys which have not been generated using standard/default passwords.
Ensure data which is transmitted uses TLS, perfect forward secrecy (PFS) ciphers, as well as implementing directives like HTTP Strict Transport Security.
Store passwords using strong salted hashing functions (Argon2, scrypt, bcrypt and PBKDF2 are all secure).
Login form on non-HTTP page in one of Chaturbate’s assets allows for a Man-in-the-Middle (MITM) attack where user credentials can be intercepted by an eavesdropping user. The publicly disclosed report can be viewed on HackerOne here.
Secure flag is not included for Session Cookie at git.edoverflow.com, meaning that the browser will send it via an unencrypted channel (HTTP) if such a request is made which in turn can be intercepted and used by an attacker. More info about securing cookies can be found in this good blog post, while the original report can be viewed on HackerOne here.
4. XML External Entities (XXE)
What is it?
Annoyingly named XXE instead of XEE (but that’s besides the point here), XML External Entity attacks leverage badly-configured XML processors to read internal files (as portrayed above), file shares and can even be leveraged for remote code execution and DoS attacks. In the context of XML, an Entity is a mechanism to define replacement values; think of it like a variable which you define in a script. They can either be internally declared, like so:
Since XXE exploits external Entities only, the syntax you should be most aware of is the second example provided.
When Does it Happen?
Web apps and XML-based web services can be vulnerable to an attack when if one or more of the conditions are present:
The web app accepts XML or allows for XML uploads — particularly with no validation for the source of the request — which is then parsed by an XML processor.
If DTDs (document type definitions) are enabled.
If the app uses SAML, since this relies upon XML for identity assertions.
SOAP version <1.2 are likely vulnerable if XML entities are passed directly to the framework.
How to Mitigate XXE Exploitation
As the OWASP Top 10 affirms, ‘developer training is essential to identify and mitigate XXE’. Ensuring that web developers write security-conscious code is obviously the ideal way to prevent vulnerable apps, but this isn’t going to happen in practice. For this reason, other mitigation methods are suggested, including:
Disable XML external entity and DTD processing in XML parser(s).
Use another data format such as JSON instead of XML.
Avoid serialisation of sensitive data.
Don’t run old XML processors or libraries — and the same applies for SOAP. Ensure all versions are upgraded to the latest stable release.
Impose appropriate server-side filtering on XML documents to remove the presence of malicious code (using methods described in the ‘Injection’ section of this article).
Run Static Application Security Testing programs over relevant code to identify potential vulnerabilities.
Proving its prevalence as number 4 on the OWASP Top 10, an XXE vulnerability was discovered in Twitter of all sites. The exploit was remarkably simple — but paid out a whopping $10,080 due to its severity in allowing an attacker to read local files on the target system. Below is the POST request sent by the attacker, containing an XML payload which then returns the contents of the /etc/passwd file on the system:
POST /api/sxmp/1.0 HTTP/1.1 Host: sms-be-vip.twitter.com Connection: close Content-Type: text/xml Content-Length: 481
<?xml version="1.0"?> <operation type="deliver"> <error code="1010" message="Unable to convert [root:x:0:0:root:/root:/bin/bash...[truncated by researcher] to an integer for [operatorId]"/> </operation>
You can view the full publicised report on HackerOne here.
2. Disclosed back in 2018, an XXE vulnerability led to an exploit in Rockstar Games’ emblem editor. The publicly disclosed report includes code snippets and explanations from the researcher himself, so would thoroughly recommend checking it out. The basic XXE usage for the exploit can be seen below:
<!ENTITY % data SYSTEM "file:///C:/Windows/system32/drivers/etc/hosts"> <!ENTITY exfil "%data;">
5. Broken Access Control
What is it?
Not to be confused with the similar-sounding Broken Authentication, Broken Access Control is when permission misconfigurations allow attackers to access or modify data/files/accounts that they should otherwise be unable to access.
When Does it Happen?
In a web application where proper access control is enforced, users will have different access permissions based upon their granted privileges. However, these controls can be mistakenly misconfigured. Common vulnerabilities in this area can sprout from:
The ability to bypass access control checks via URL or HTML tampering, modification of the internal application’s state or by using a custom API attack tool.
A privilege escalation vulnerability, which allows a low-privileged user to perform actions that should be reserved for users with higher privileges.
Metadata manipulation (this includes vectors such as tampering with access control tokens such as JWTs or cookies).
CORS misconfigurations (you can learn more about these types of vulnerabilities in this blog post).
How to Mitigate Broken Access Control
There is one simple rule to keep in mind when managing access control: unless the resources must be publicly accessible, deny users from accessing them. Obviously this is easier said than done, particularly given the list of various attack vectors presented above. For this reason, there are some other pointers to mitigate any potential issues:
Minimise CORS implementation.
Prevent web server directory listing and ensure file metadata (such as .git) and backed-up files are not accessible via the server’s root directory. The .git vulnerability is particularly worth mentioning, since there are some scraping tools out there which identify exposed .git directories on inputted sites and download the source code. These tools can be viewed at internetwache’s GitTools repository here.
Log activity for the access of relevant files to document and identify any potential vulnerabilities in your own server.
Impose rate-limiting on API and controller access to reduce the potential harm from automated attack tools.
All relevant access tokens should be invalidated server-side when a user logs out.
We’ve got two critical ones here — both related to the video game industry!
Improper access control led to a security researcher being able to get the CD keys for any game on Steam. Definitely not intended privileges there. Valve summarised the exploit:
‘Using the /partnercdkeys/assignkeys/ endpoint on partner.steamgames.com with specific parameters, an authenticated user could download previously-generated CD keys for a game which they would not normally have access.’
2. An exposed .bash_history file on http://drivers.razersupport.com meant that any visitor to this endpoint could publicly view the file (see the report summary here). According to Razer:
‘When a DB admin eventually executed a command involving clear text credentials for the database, this exposed the password for that database.’
In the second article of this two-part series, we’ll give a simple overview of the final 5 vulnerabilities listed in the most recent OWASP Top 10, how to mitigate them, as well as featuring real-world examples from disclosed bug reports to show the exploits in action. Let’s go!
(If you haven’t checked out the first article, you can see it here).
6. Security Misconfiguration
What is it?
Covering a broad range of potential weaknesses, this category of vulnerabilities is actually the most prevalent in web apps today (OWASP Top 10 isn’t ranked on prevalence but rather seriousness, hence why it occupies the number 6 spot here). This can include insecure default configurations, incomplete configurations, misconfigured HTTP headers or exposed error messages which guide attackers in their search for vulnerabilities.
When Does it Happen?
A number of different features can constitute misconfigurations, including:
Failure to sufficiently harden the application (a lack of firewall, or a misconfigured one).
Unnecessary exposure, whether it be in the form of web pages, unused accounts or unrequired services.
Error messages are outputted on the web server. This can be particularly dangerous if they are overly verbose, potentially revealing file paths, configuration details and version information.
The server does not send security headers (things like Strict-Transport-Security, Content-Security-Policy, X-Content-Type-Options, X-XSS-Protection, Referrer-Policy etc), or fails to appropriately set their values.
How to Mitigate Security Misconfigurations
Take a minimalist approach to your web app — if a feature, framework or function is not required, remove it.
Ensure that all available updates and patches are applied as soon as possible. Conduct routine checks to ensure this requirement is met.
Introduce an automated process to routinely check misconfigurations (using Selenium or an equivalent framework).
Misconfigured HTTP headers in U.S. Department of Defense web page (https://www.sfl-tap.army.mil/). While the security-conscious X-XSS-Protection header was included, it was configured with the value DENYwhich is to be used for the X-Frame Option. The researcher correctly recommended that this should be changed to 1; mode=block. The original report can be viewed here.
Another HTTP headers example — this time in ReddAPI. An HTTPS page was missing the Strict-Transport-Policy header which is required to ensure that a browser always uses secure protocol when accessing said page. Full information about the report can be reviewed here.
7. Cross-Site Scripting (XSS)
What is it?
One of the better-known vulnerabilities due to its high ranking in OWASP’s Top 10 in years gone by (#3 in 2013 and #2 in 2010), XXS may have dropped down to #7 in 2017 as a result of better knowledge and protection against it. Put simply, Cross-Site Scripting allows an attacker to execute script(s) in a victim’s browser. This can be used to hijack user sessions (by getting cookies, session ID’s and so on), alter the contents of a web page or redirect a user to an evil site. There are two common types:
Stored XSS: this is when an injected script is stored on the server in a fixed location. The classic example is a forum post, where every user which requests the post from the server will subsequently be affected by the XSS attack. Also referred to as Persistent or Type-I XSS. For this reason, it is usually classified as the most severe since it will typically impact the highest number of users.
Reflected XSS: this is when an injected script within a request is reflected back in the server’s response. A common example is a search feature which responds by printing (or reflecting) the user’s malicious search input as well as outputting the search information. Given this format, a reflected XSS attack must involve targeting a victim through another method such as social engineering in order to get them to send the request which elicits a reflected response. Also referred to as non-persistent or Type-II XSS.
There is also a third, lesser-known XSS attack vector:
DOM-based XSS: as the name suggests, this type of XSS differs from the other two types in that it appears in the DOM (Document Object Model) rather than the HTML document. This means that the latter is not modified, and so the payload will not be found in the server’s response — it can instead be identified by investigating the DOM of the page. A trivial DOM-based XSS payload could look like this:
Employ a combination of validating, filtering, encoding and escaping methods to prevent untrusted user input from executing on the web app. The first OWASP cheat sheet listed above goes into extended detail about methods you can use to prevent malicious input executing as intended.
Move to frameworks which automatically escape XSS by design (recent Ruby on Rails version, React JS).
Enforce secure headers (such as X-XSS-Protection: 1; mode=block and Content-Security-Policy).
The list could be pretty extensive for this one, so I’ve shortlisted a prolific example for each type:
Stored XSS: A stored XSS vulnerability was discovered in Steam’s react-built chat client. The informative report and steps taken to exploiting it can be viewed on HackerOne here.
Due to a lack of input validation from the search field on lert.uber.com, it was possible to obtain a Reflected XSS from the URL path, e.g. https://lert.uber.com/s/search/All/Home">PAYLOAD.
3. DOM-based XXS: a vulnerability in the DuckDuckGo search engine was identified and explained in this report. With responsible source code identified and screenshot proof of the exploit, it’s worth checking out. Ultimately, the effective payload can be seen below:
To get a better sense of what Insecure Deserialisation is, we need to talk about the verb here: to serialise.
Serialisation: the process of translating an object into a format which can be persisted to disk (as a file for example), sent through streams or sent over a network. It can either be binary or structured text (such as XML, JSON etc).
Deserialisation: Well… the opposite; transforming serialised data from a file, stream or network socket into an object.
Throw insecure into the mix, and we can start to see how this can become a vulnerability. If an attacker can alter the content of what is to be deserialised, then they can leverage this to achieve remote code execution (RCE). While it is arguably the most technically complex vulnerability to exploit on the OWASP Top 10, it is usually also the most damaging when it is successful.
So…what do applications use serialisation for? There are a variety of use-cases:
Remote-process communication (RPC) and inter-process communication (IPC).
Wire protocols, web services and message brokers.
Databases, cache servers and file systems.
HTTP cookies, HTML form parameters and API authentication tokens.
When Does it Happen?
Fundamentally, an application is likely vulnerable to this type of attack if it deserialises untrusted or tampered data inputted from a malicious source. If these conditions exist, it can lead to two different types of exploits:
Object/data structure-related attacks where an attacker modifies application logic or achieves RCE if there are classes available within the application that can change behaviour during or after serialisation.
Data tampering attacks — such as access control-related exploits where existing data structures are used but the content is modified.
How to Mitigate Insecure Deserialisation Attacks
As is written in OWASP’s guide, ‘the only safe architectural pattern is not to accept serialised objects from untrusted sources or to use serialisation mediums that only permit primitive data types’. Other mitigative steps include:
Enforce integrity checks (i.e. digital signatures) on serialised objects to prevent hostile objects from being created or data being tampered with.
Isolating deserialisation processes into low-privilege environments when possible.
Restricting or monitoring incoming and outgoing network connectivity from containers or servers that deserialise.
Logging, monitoring, and alerting when a user repetitively deserialises. Given the trial-and-error nature with this type of exploit, it’s not unusual for a malicious user to be fairly noisy when attempting this style of attack.
In September 2018, a researcher on HackerOne identified an insecure deserialisation vulnerability in Vanilla Forums which allowed a determined attacker to achieve remote code execution. The report is extremely detailed and includes source code analysis and a PoC.
The same researcher (going by mr_me on HackerOne) went on to find a total of 4 exploits which all led to RCE in the Vanilla web app. The most complex of these — again with a well-written report — can be seen here.
9. Using Components with Known Vulnerabilities
What is it?
This one’s pretty straightforward and is exactly what it says on the tin: it is when a web app actively includes components which have publicly-known vulnerabilities. Given that a web application’s components will share the privileges assigned to the app, an already-weak link can lead to severe data loss or even an entire takeover of the server.
When Does it Happen?
If administrators are not aware of all the version info and components running on the web application.
If software is vulnerable, unsupported or out of date.
If routine checks are not carried out for updates and patches (whether automated or manual).
How to Avoid it
Similarly to dealing with security misconfigurations, mitigating this issue requires due diligence on behalf of those responsible for the web application. Responsibilities include:
Keep an up-to-date inventory which documents every component that is used on the web application. This can then be cross-referenced against vulnerability databases (such as CVE and NVD) to identify if you have any affected components.
Subscribe to security bulletins and e-mail notifications for relevant components that the app uses.
You might assume that only small-scale web apps are susceptible to this type of vulnerability. However, that’s most definitely not true — and frequently-used, large-scale apps will typically have more involved components, which can increase the likelihood that one of them is vulnerable. For this first example, a fitting report was disclosed back in 2016 which affected Uber. Not only was it using an out-of-date version of WordPress, but it also ran a plugin q-and-a which had since been removed from WordPress due to having a Full Path Disclosure vulnerability. The reporter ended up identifying another vulnerability in the plugin, but was only led to it by Uber’s initial running of components with known vulnerabilities in the first place. The original report can be viewed here.
10. Insufficient Logging & Monitoring
What is it?
Like the previous security weakness, this one is also very straightforward. Any effective cyber security operation center (SOC) relies extensively upon logging and monitoring to evaluate the state of the network and identify any potential threats. Failure to keep sufficient records in these areas can subsequently slow incident response, accentuating the potential damage of an intrusion. According to the OWASP Top 10, ‘most breach studies show time to detect a breach is over 200 days, typically detected by external parties rather than internal processes or monitoring’.
What Constitutes Insufficient Logging & Monitoring?
When important events such as logins, login attempts, and significant transactions are not logged.
Warnings and errors generate no or inadequate log messages.
Logs of applications/APIs are not kept for suspicious behaviour (i.e. enumerating for sensitive files on the server).
Logs are only stored locally.
Alerts and response escalation processes either don’t exist or are ineffective.
How to Avoid Insufficient Logging & Monitoring
Ensure important events, significant transactions and server-side input validation failures are logged — with enough context to identify suspicious users and the ability to suspend their activity while forensic analysis takes place.
Make sure proper access controls are enforced (such as append-only for log documents) to prevent them from being tampered with.
Create an effective alerting system and policy which allows for potential threats to be dealt with before they escalate.
November 2018 Marriott International Data Breach
Reportedly affecting more than 500 million customers, this data breach occurred following hackers gained entry to one of its 2016-acquired subsidiaries — Starwood. The vulnerable network was reported to be the guest reservation service, which attackers had been accessing since 2014. This meant that their presence went unnoticed for over four years with reports emerging in November of 2018 of the data breach. There’s no doubt that this was one of the more significant logging and monitoring failures in the history of the internet.