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.

<sorted-set>
<string>foo</string>
  <dynamic-proxy>
    <interface>java.lang.Comparable</interface>
    <handler class='java.beans.EventHandler'>
      <target class='java.lang.ProcessBuilder'>
        <command>
          <string>touch</string><string>/tmp/here</string>
        </command>
      </target>
      <action>start</action>
    </handler>
  </dynamic-proxy>
</sorted-set>

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:
    pickle.loads(f.read())

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 
#Result will be rO0ABXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

As usual, here is the video tutorial.

OWASP Webgoat download and installation – OWASP Top 10 training

Welcome back to the OWASP Top 10 training series. Today, you are going to learn how to install OWASP WebGoat and OWASP WebWolf using both java and Docker. We are slowly but surely building out our OWASP Top 10 lab to start practicing how to exploit the OWASP Top 10 vulnerabilities. If you haven’t been following along from the beginning, it’s not too late. All you have to do is follow the instructions on OWASP Zap or Burp Suite setup blog posts. Or, if you prefer videos, I created the OWASP Top 10 video training series just for you. I will be adding more episodes to it as we progress on this training.

What is OWASP Webgoat and why using it for this OWASP Top 10 training?

OWASP WebGoat is a deliberately insecure web application to test Java-based applications against common web application vulnerabilities. It is well maintained and contains most of the OWASP Top 10 vulnerabilities. 

OWASP WebGoat comes with another web application called OWASP WebWolf, which makes it easy for you to host malicious files, receive emails and HTTP requests. It is really handy for testing things like out-of-band attacks.

Both OWASP WebGoat and WebWolf are released as jar files, Docker images and, of course, source code. So it is very convenient for our OWASP Top 10 training. In fact, this is a great opportunity to learn how Docker can be used to setup a lab and learn web application hacking.

Disclaimer: this is a deliberately vulnerable Web application. I strongly discourage running it on your host machine. For this reason, I a m going to start on a fresh Debian 9 VM on Virtualbox. I explain how to setup one in my video on Youtube. For now, I’ll assume that you already have a Debian 9 VM running on your favorite Virtualization software. I am using VirtualBox.

How to install OWASP Webgoat  and WebWolf using the JAR

Feel free to skip this part if you’d like to use Docker in your OWASP Top 10 training. I’ve included it here so that you know how to install Java on your machine. Knowing how to install packages is a good skill to have in your learning journey. It allows you to discover and experiment with new tools, especially with the increasing number of open-source tools published everyday.

Installing Java

Once you’ve connected to your Debian 9 guest machine, run the following commands. Again, make sure to watch the video if you are blocked.

# Download JDK 11
cd /tmp && wget https://download.java.net/java/ga/jdk11/openjdk-11_linux-x64_bin.tar.gz

# Switch to the root user, type root password
su

# Create the folder /usr/lib/jvm
mkdir /usr/lib/jvm

# Extract the downloaded archive
tar xzvf /tmp/openjdk-11_linux-x64_bin.tar.gz --directory /usr/lib/jvm

# Create a symlink to the java binary 
ln -s  /usr/lib/jvm/jdk-11/bin/java /usr/bin/java

# exit from root user
exit

# Verify that you have the right version running
java -version

# Remove the downloaded archive
rm /tmp/openjdk-11_linux-x64_bin.tar.gz

OWASP WebGoat download and run

# Download the latest WebGoat release jar
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M26/webgoat-server-8.0.0.M26.jar

# Run WebGoat using java
java -jar webgoat-server-8.0.0.M26.jar --server.address=0.0.0.0

Note that you have to set the server.address option to 0.0.0.0. In fact, by default, WebGoat listens on localhost only.

OWASP WebWolf download and run

# Download the OWASP WebWolf jar
wget https://github.com/WebGoat/WebGoat/releases/download/v8.0.0.M26/webwolf-8.0.0.M26.jar

# Run it while setting the server’s address to 0.0.0.0
java -jar webwolf-8.0.0.M26.jar --server.address=0.0.0.0

How to install OWASP Webgoat in Docker

Docker has many advantages over using plain Java. I can’t recommend it enough, not only in this OWASP Top 10 training series, but also in your overall hacking journey. In fact, you don’t need to install and configure any dependencies. Plus, Webgoat and webwolf are all run using one command. Finally, Docker will help you to easily setup other applications in the future.

Install Docker

The docker documentation includes a one-time script installation, but I wouldn’t recommend it. You need to develop the habit of understanding what a code does before running it on your own machines. Most of the following steps are inspired by the official Docker documentation for Debian.

# Switch to the root user, type root password
su

# Remove any previous installations of Docker
apt-get remove docker docker-engine docker.io

# Update your repository
apt-get update

# Install required packages
apt-get install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common

# Download Docker’s apt-key
curl -fsSL https://download.docker.com/linux/$(. /etc/os-release; echo "$ID")/gpg | apt-key add -

# Verify that the key belongs to Docker
apt-key fingerprint 0EBFCD88

# Add docker to the repository
add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/$(. /etc/os-release; echo "$ID") \
   $(lsb_release -cs) \
   stable"

# Update the repository
apt-get update

# Install Docker
apt-get install docker-ce

# Add your user to the docker group
/sbin/usermod -aG docker thehackerish
# or
usermod -aG docker thehackerish

# Login with your user again on SSH and run: 
docker run hello-world

You should have a response similar to this oneOWASP Top 10 training: Docker setup

Download and run OWASP WebGoat for docker

Run WebGoat and WebWolf all in one go. Notice that you have to set the timezone variable TZ for JWT challenges to work properly. Here is a list of timezones that you can use according to your host machine location.

docker run -d -p 8080:8080 -p 9090:9090 -e TZ=Europe/Amsterdam webgoat/goatandwolf

Testing our OWASP WebGoat setup

Now that OWASP WebGoat and WebWolf are running, let’s test if they work with OWASP ZAP or Burp Suite as intended.

  1. Launch OWASP Zap or BurpSuite.
  2. Choose your proxy from the FoxyProxy add-on. If you haven’t followed from the beginning, here is the link for installing and configuring FoxyProxy.
  3. Go to http://your-machine-ip:8080/WebGoat, where your-machine-ip is the IP address of the Debian 9 VM.
  4. If everything went well, you should have a login screen like the following screenshot.OWASP Top 10 training: Webgoat login page

Testing our OWASP WebWolf setup

  1. Launch OWASP Zap or BurpSuite.
  2. Choose your proxy from the FoxyProxy add-on. If you haven’t followed from the beginning, here is the link for installing and configuring FoxyProxy.
  3. Go to http://your-machine-ip:9090/WebWolf, where your-machine-ip is the IP address of the Debian 9 VM.
  4. If everything went well, you should have a login screen.OWASP Top 10 training: WebWolf login page

Congratulations! You’ve made another step towards practicing OWASP Top 10 vulnerabilities! In the next episode of this OWASP Top 10 training series, we will set up and configure OWASP Juice Shop.

If you enjoyed this tutorial, consider subscribing to the Newsletter below to be notified when there is news on thehackerish.com. Until then, stay curious, crave for learning, be ethical and share with the world!

If you enjoy learning on Youtube, I prepared the Owasp Top 10 training videos series just for you. Here is the OWASP WebGoat setup video.