Security Testing With JMeter - Learn How
A professional security tester shows us how to use the open source tool JMeter to perform security tests on our web applications.
Join the DZone community and get the full member experience.
Join For FreeWhile the main purpose of Apache JMeter™ is load testing, its functionality enables it to be used for security and automation testing as well. Security testing intends to uncover vulnerabilities in the system and determine that its data and resources are protected from possible intruders. In this article, we will explore the different areas of security testing where the tool can be applied. We will cover three different types of security testing: Site Spidering, Fuzzing, and Distributed Denial of Service (DDoS), and how they can be implemented in JMeter. We will finish with things to notice when security testing your APIs.
Why JMeter? There is specialized security testing software, like, Burp Suite or Acunetix. But most of them are commercial and cost hundreds or thousands of dollars. Compared to them, JMeter seems like a more accessible and attractive option.
When testing the security of your software, the most important phase is information gathering. Site Spider allows you to draw a map of the site's visible places (places that you can access using only the interface of the website). The data is shown per each website URL. You can use the information to draw conclusions about the size of the tested space, its functionality and, possibly, the tools used in development. This information enables us to determine the most obvious attack vectors and choose the appropriate test data.
Let's look briefly at the order of actions that the Spider carries out, which the JMeter script should perform too:
- Go to the start page.
- Read all the URLs on the page.
- Follow each link and analyze the responses.
- Repeat steps 2 and 3 for each URL.
While we can build a JMeter script that will perform this function, it's important to understand that JMeter is not a browser, but rather works at the protocol level. Therefore, JMeter does not perform all the actions supported by browsers. In particular, JMeter does not execute JavaScript found in HTML pages. So JavaScript and unusual objects, such as Flash, will be skipped. A similar problem occurs with most Spiders. Just keep these drawbacks in mind.
Let's build our JMeter script. You can learn more from this blog post "How to Spider a Site with JMeter - A Tutorial."
1. After adding a Thread Group, you can use the HTTP Request Sampler (Right Click on Thread Group -> Add -> Sampler -> HTTP Request), which allows you to send various HTTP Requests.
2. To extract URL links, we can use several elements.
The Regular Expression Extractor
Right Click on HTTP Request Sampler -> Add -> Post Processors -> Regular Expression Extractor
The Regular Expression Extractor enables applying a regular expression to the response body of the HTTP Request Sampler. For example, a regular expression for extracting a link from a tag looks as follows: ]*?\s+)?href=(["'])(.*?)\1
. The configuration of the element for this case is shown below. You can use this, or create your own.
XPath Extractor
Right Click on HTTP Request Sampler -> Add -> Post Processors -> XPath Extractor
You can also extract the URL using the XPath query. To do this, we will use the XPath Extractor element. The XPath query for this case looks as follows: //a/@href
, and the configuration of the element for this case is shown below. You can use this, or create your own.
CSS/jQuery Extractor
Right Click on HTTP Request Sampler -> Add -> Post Processors -> CSS/jQuery Extractor
CSS/jQuery is more convenient and readable than Regex and XPath. It allows you to easily select HTML DOM elements that might otherwise have been difficult to write a regular expression for. For example, in the screenshot below, there is this configuration to extract a link from a tag. You can use this, or create your own.
HTML Link Parser
This post-processor does not have any settings. It extracts absolutely all the links, which makes it somewhat unsuitable for our task, because it does not distinguish between GET links and POST links, but we only need GET requests for creating a website map.
A great JMeter advantage when building a spider is the wide configuration variability. With the help of the elements covered above, we can gather additional information from the pages viewed. For example, you can check a page for input forms, and then write the page data into a separate file.
3. Now, you can write to the file and work with the URL by using the BeanShell PostProcessor. Below is the code for the BeanShell PostProcessor, which writes all the received URLs to a file and performs the initial processing of the URL. For example, some internal URLs have a dot and no slash at the beginning of the line. The script addresses the issue.
Fuzzing is a way of testing applications, which is based on the transfer of incorrect, random, or unforeseen program logic data and seeing how the system responds. Fuzzing is connected to the phase of information gathering and is an integral part of black box security testing, which means we just focus on inputs and output of the software system, without bothering about internal knowledge of the software program. By using Fuzzing, you can find coding errors and security gaps. For example, you might find web application directories that are inaccessible from its interface or untypical errors when processing the input data. Fuzzing can also be easily automated, because, for instance, with the help of JMeter, we can generate various types of requests with different test data.
Fuzz testing is similar to functional testing, with the main difference being the test data. If you need ideas, this repository contains a lot of test data for fuzzing (both field validation and directory fuzzing). For fuzz testing, we need an element that sends requests. For a website, that would be an HTTP Request Sampler.
Click here to see an example of data that we can pass as parameters.
Let's look at this case example, aimed at identifying SQL injections allowing you to bypass the login phase. Below is the POST authorization request for this example. You should always check POST requests when Fuzz testing. The csv_line is a variable from the CSV Data Config, where there is a file with injections. You can also use CSV files for other kinds of bad data that can lead to unexpected consequences, like here.
Now, responses can be analyzed with the help of the Response Assertion. This element analyzes the response according to the pattern that you can specify in the configuration of the sampler and ends successfully if the response matches the pattern. Since we need to check whether the login will be performed or not, Assertion settings should be such that it checks for a successful login. Below is a screenshot with an example of the settings.
It is also important to check access to obvious directories and files. This is called Directory Traversal. As we wrote above, with certain tools used during development, a project can contain obvious paths and files and we can try to find them.
The Internet contains a lot of information about such paths. Let us take the following document and connect it to the script and run it. This document contains obvious paths common to the PHP language. The script goes through all these paths.
As you can see, we have found some interesting paths and files. For example, the first link is a page with information about the version of PHP that is used on the server. This is a huge source of information about the services used on the server. This is not very good for the owner of the resource, whose sensitive data is exposed. The second link is the panel to work with the resource database, a real catch.
As you might have noticed, fuzzing files are specifically focused. For example, in the first case, we used injections for the MySQL DB, and the paths for PHP. Our spider helped us select the information for fuzzing, as well as draw conclusions about the environment under testing. We were also able to find the page for the POST request using it.
DDoS is a type of network attack based on the limited resources of the service under attack. Multiple requests are sent to the service, which it will obviously not cope with, and then it will have to refuse to service this request (or will make them wait unacceptably long). As a rule, requests are sent from different points. Otherwise, if you want to call DoS with mass requests using only one machine, it must have an extremely wide Internet channel and large processing power. DDoS is possible at each level of the OSI model. We will look at DDoS at level 7 using HTTP requests. Arranging such an attack during the testing phase allows you to check how much the server can resist such attacks.
Almost DDoS: just add one HTTP Request Sampler that will access the main application page. After that set, a large number of users in the thread.
Now we can launch it. This is still not DDoS, rather it is just an attempt to call DoS while loading the website with regular GET requests to the main page. But even such a simple attempt is sufficient to ensure the inaccessibility of the resource.
Besides, if you look at the results of the script, you will notice that some of the requests failed.
This, unfortunately, will be enough for some sites on the Internet. So, please, do not check this on the site where you usually watch films or read articles.
But what if our application server has high performance and is able to process the load from one machine? Then, JMeter enables distributing load generation between several machines.
The logic of load distribution is quite simple: the client (the machine where we run the script) sends the specified set of tests to each of the servers (machines running JMeter as a server), the servers, in their turn, perform these tests and send the collected results back to the client.
The Apache website has a comprehensive step-by-step guide for setting up the distributed load, where all the pitfalls are described, as well as the advantages and disadvantages of this technique.
Some More Use Cases
If the server prohibits sending more than 1 request per second from one IP address, use IP spoofing. For example, if you press F5 several times on the website vk.com, you will receive a notification that the request will not be processed. Learn more from this blog post: IP Spoofing and JMeter.
To simulate attacks at multiple selected addresses, and not just one, use the file that was obtained with the help of the spider. Connect it using CSV Data Config and then send requests at the addresses specified in the CSV.
Does your server still process all requests? Try out a slow HTTP POST Attack! This attack involves sending a large HTTP POST request in small pieces to the server. According to its standards, the HTTP server must wait for the data to be fully transferred and can close the connection only by timeout. Thus, the attacked server opens a huge number of connections, catastrophically spending its resources.
To conduct this attack, you need to edit the users.properties file that is located in the /bin folder.
Open this file and add these strings:
httpclient.socket.http.cps=1
httpclient.socket.https.cps=1
This is necessary for emulating a slow Internet connection. This means that one character per second will be sent, it's slow enough.
What about the DDoS of the other levels? We can also do this, for example, to replace the HTTP Request sampler with the UDP Request server and send a lot of UDP packets to the server that is working with this protocol, whether it is a DNS server or some other server. Working with UDP Request Sampler has been covered in this article. This will be a level 4 DDoS attack of the OSI model.
As mentioned above, JMeter is also well suited for functional testing automation, making APIs one of the first clients to automate this kind of testing. To test REST/SOAP APIs, you can use the same HTTP Request sampler as shown above. You can also use various plugins from Plugin Manager, for example, the Custom SOAP Sampler or XML Plugins.
While we will not focus on API security in depth in this article, I just want to draw your attention to a few practical aspects.
- Have you noticed that some websites have a login attempt restriction? The account or IP is blocked for a while or forever. But sometimes there is no restriction when a request is sent through API. This is a very big omission, which was found even in the applications of famous banks.
- Underprotected API ranked 10th in the OWASP Top Ten. Even if you do not speak publicly about the general availability and openness of your API, it does not mean it is protected.
- Access control - You have a website and all the data is being perfectly processed. You provide an API for users, which allows them to carry out various actions, like writing messages on your website. But suddenly John writes a message on behalf of Mary. Where is the problem? John replaced the author's id in the message sent through the API. Something similar happened once on Facebook.
That's it! You now have tools to run security tests on your website, app or API, with JMeter.
Published at DZone with permission of , DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments