I. Preface
Fuzzy testing of JSON services is often an effective work (especially JSON services implemented by dynamic scripting languages, such as python, ruby and JavaScript). However, according to my observation, during the test process, few people can complete the work perfectly. In this article, I would like to share with you my personal experience on how to complete this task. In this article, I use some of my common tools. If you have a better choice, you can also choose your own tools. Now let's get to the point.
JSON web services refers to simple web services with JSON documents as input. Cloud architectures (such as AWS, azure and Google cloud) often have such interfaces, which can provide services for our mobile phones, watches, TVs and refrigerators. Now, almost everything is using JSON data communication, because JSON is different from other document formats (such as XML, yaml, ini, etc.), relatively simple, compact and not prone to strange errors. Because of the excellent properties and ease of use of JSON, all programming languages and environments now support this format natively.
2、 Test sample
In many programming languages (especially JavaScript, ruby and python), JSON is the preferred solution. This means that although JSON is an external object, it can handle the same as the native object, so it can have the same access way as the ordinary object. For example, let's look at the following request:
POST /path/to/service HTTP/1.1
Host: service
Content-Length: xxxx
Content-Type: application/json
{
"profile": {
"name": "Bob",
"age": 40
}
}
In order to access the "name" field in the "profile" attribute, JavaScript developers are likely to use the following methods:
// this is what you will normally see in ES5
updateProfile(body.profile.name, body.profile.age)
// ...or in modern ES6 may even look like this which looks a bit safer
const { profile={} } = body
const { name, age } = profile
updateProfile(name, age)
Note that the "name" and "age" fields are extracted directly from the "profile". It should also be noted that the above code neither validates the types of the two fields nor normalizes them. Although this example is quite simple, it exists in most public codes.
The utilization of this kind of code depends largely on the specific service and the real processing of the "updateprofile" function, so we can't follow the very standard utilization steps. We can't list the existing wrong characters. We hope to get results quickly. Instead, we need to analyze the behavior of the application, speculate on what might happen, and see if there is an opportunity to exploit the vulnerability. That's why we need to roll up our sleeves to refuel fuzz. So the question is, what do we need to fuzzy? How to fuzzy?
Obviously, we need to try different values for the name and age fields. In addition, we need to try other unexpected inputs, such as arrays or objects. For example, the updateprofile function might want to process an object (such as {first, last}) without receiving a string. When implementing the check process, the developer may not consider how the updateprofile function handles the deserialized JSON data, so when the name field is of string type, the corresponding code branch may contain some bugs. We need to use fuzzy technology to try this situation automatically.
updateProfile
{first, last}
updateProfile
In this scenario, I use AppBandit, but you can also choose to use Fuzzer, if you think that the modules you develop are more awesome, they can also be used. I have successfully completed this task with appbandit and HTTP view before, so I will not waste my time building wheels again.
First, we can launch appbandit and open a new fuzzer tab. We need to set some basic parameters, as shown in the figure below. The setting here is relatively simple, just to prepare for the next operation.
Now we need to configure the JSON document to generate different combinations. To achieve this, we need to use the JSON fuzzy generator. Go to the body page and select JSON fuzzy from the drop-down list. In the first field, we need to set up our own document. In the second field, we need to set the payload to be used.
If we just enter a simple string in the load field, the program will use it as a string. For example, if the load is "test", the JSON fuzzy generator will generate the following two documents:
{
"profile": {
"name": "test",
"age": 40
}
}
as well as
{
"profile": {
"name": "Bob",
"age": "test"
}
}
However, this is not helpful for us to find the vulnerability, so we need to use other generators to extract more values. We can select dictionary generator from the drop-down list, fuzzy dB from the drop-down list of dictionaries, and then "attack / JSON / json_fuzzy. TXT". Keep in mind that appbandit does not embed these dictionaries by default and can be downloaded at any time if we need to.
Now that we have loaded these lists, we can also edit and add our own test loads. As long as it is useful, we can add any data to them. More loads will bring better fuzzy effect. We can also use the arrow buttons to preview the load generation process. Note that we have now introduced the payload in the JSON format in the right way, that is, the payload will be interpreted as a string.
This is not the effect we want. What we want is to use the original JSON. To achieve this goal, we need to check the "parse payload" and "ignore payload parsing errors" options. Now the load can be generated correctly, as shown in the figure below.
At present, the data has been generated. Exit the generator and use the arrow button to cycle through the fuzzy load to see if everything is ready.
Before we click the "play" button, I'd like to configure it a little more. We can set the request timeout parameter, or increase the maximum number of connections to 60, so that the test can be faster.
In some cases, for some reason, the procedure may not work the way we envision it. Don't be discouraged at this time. If this happens, we can click the fork button, create a full copy of the current configuration, and then perform another test, which is very easy.
After the test, next we need to analyze the test results to see if there is any strange data in the target service. There is no profound science behind this process. We just need to simply browse the output results to find the abnormal behaviors. If we use appbandit's reset tool, we can confirm the abnormal behaviors, and then further mine or use the abnormal points.
Three, summary
I know this article can't cover all the content. It's an open-ended issue. You can discuss it well. Unlike SQL injection, cross site scripting, and local file inclusion, this is not a very standard predefined vulnerability. In other words, we can't inject some interesting characters to implement code execution. However, if we use the correct JSON payload, we can control the code and eventually find the vulnerabilities. Although I haven't mentioned any actual test scenarios in this article, it is certain that in many cases we can use this method to get interesting and exploitable vulnerability results.