API Attacks
Information Disclosure (with a twist of SQLi)
Information Disclosure through Fuzzing
Suppose we are assessing an API residing in http://<TARGET IP>:3003.
Maybe there is a parameter that will reveal the API's functionality. Let us perform parameter fuzzing using ffuf and the burp-parameter-names.txt list, as follows.
We notice a similar response size in every request. This is because supplying any parameter will return the same text, not an error like 404.
Let us filter out any responses having a size of 19, as follows.
Information Disclosure (with a twist of SQLi)
eldeim@htb[/htb]$ ffuf -w "/home/htb-acxxxxx/Desktop/Useful Repos/SecLists/Discovery/Web-Content/burp-parameter-names.txt" -u 'http://<TARGET IP>:3003/?FUZZ=test_value' -fs 19
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v1.3.1 Kali Exclusive <3
________________________________________________
:: Method : GET
:: URL : http://<TARGET IP>:3003/?FUZZ=test_value
:: Wordlist : FUZZ: /home/htb-acxxxxx/Desktop/Useful Repos/SecLists/Discovery/Web-Content/burp-parameter-names.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,204,301,302,307,401,403,405
:: Filter : Response size: 19
________________________________________________
:: Progress: [40/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 id [Status: 200, Size: 38, Words: 7, Lines: 1]
:: Progress: [57/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [187/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [375/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [567/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [755/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [952/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0
:: Progress: [1160/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors:
:: Progress: [1368/2588] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors:
:: Progress: [1573/2588] :: Job [1/1] :: 1720 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [1752/2588] :: Job [1/1] :: 1437 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [1947/2588] :: Job [1/1] :: 1625 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [2170/2588] :: Job [1/1] :: 1777 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [2356/2588] :: Job [1/1] :: 1435 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [2567/2588] :: Job [1/1] :: 2103 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [2588/2588] :: Job [1/1] :: 2120 req/sec :: Duration: [0:00:01] :: Error
:: Progress: [2588/2588] :: Job [1/1] :: 2120 req/sec :: Duration: [0:00:02] :: Errors: 0 ::It looks like id is a valid parameter. Let us check the response when specifying id as a parameter and a test value.
Information Disclosure (with a twist of SQLi)
Find below a Python script that could automate retrieving all information that the API returns (save it as brute_api.py).
We import two modules requests and sys. requests allows us to make HTTP requests (GET, POST, etc.), and sys allows us to parse system arguments.
We define a function called brute, and then we define a variable called value which has a range of 10000. try and except help in exception handling.
url = sys.argv[1] receives the first argument.
r = requests.get(url + '/?id='+str(val)) creates a response object called r which will allow us to get the response of our GET request. We are just appending /?id= to our request and then val follows, which will have a value in the specified range.
if "position" in r.text: looks for the position string in the response. If we enter a valid ID, it will return the position and other information. If we don't, it will return [].
The above script can be run, as follows.
PoCs - Questions
What is the username of the third user (id=3)?


Identify the username of the user that has a position of 736373 through SQLi. Submit it as your answer.

Arbitrary File Upload
Suppose we are assessing an application residing in http://<TARGET IP>:3001.
When we browse the application, an anonymous file uploading functionality sticks out.

Let us create the below file (save it as backdoor.php) and try to upload it via the available functionality.
The above allows us to append the parameter cmd to our request (to backdoor.php), which will be executed using system(). This is if we can determine backdoor.php's location, if backdoor.php will be rendered successfully and if no PHP function restrictions exist.

We can use the below Python script (save it as web_shell.py) to obtain a shell, leveraging the uploaded backdoor.php file.
Use the script as follows.
Arbitrary File Upload
To obtain a more functional (reverse) shell, execute the below inside the shell gained through the Python script above. Ensure that an active listener (such as Netcat) is in place before executing the below.
Arbitrary File Upload
Local File Inclusion (LFI)
Suppose we are assessing such an API residing in http://<TARGET IP>:3000/api.
Let us first interact with it.
We don't see anything helpful except the indication that the API is up and running. Let us perform API endpoint fuzzing using ffuf and the common-api-endpoints-mazen160.txt list, as follows.
It looks like /api/download is a valid API endpoint. Let us interact with it.
We need to specify a file, but we do not have any knowledge of stored files or their naming scheme. We can try mounting a Local File Inclusion (LFI) attack, though.
The API is indeed vulnerable to Local File Inclusion!
Cross-Site Scripting (XSS)

test_value is reflected in the response.
Let us see what happens when we enter a payload such as the below (instead of test_value).
Code: javascript

It looks like the application is encoding the submitted payload. We can try URL-encoding our payload once and submitting it again, as follows.

Server-Side Request Forgery (SSRF)
Suppose we are assessing such an API residing in http://<TARGET IP>:3000/api/userinfo.
Let us first interact with it.
Server-Side Request Forgery (SSRF)
The API is expecting a parameter called id. Since we are interested in identifying SSRF vulnerabilities in this section, let us set up a Netcat listener first.
Then, let us specify http://<VPN/TUN Adapter IP>:<LISTENER PORT> as the value of the id parameter and make an API call.
We notice an error about the id parameter being invalid, and we also notice no connection being made to our listener.
In many cases, APIs expect parameter values in a specific format/encoding. Let us try Base64-encoding http://<VPN/TUN Adapter IP>:<LISTENER PORT> and making an API call again.
When you make the API call, you will notice a connection being made to your Netcat listener. The API is vulnerable to SSRF
As time allows, try to provide APIs with input in various formats/encodings.
Regular Expression Denial of Service (ReDoS)
The API resides in http://<TARGET IP>:3000/api/check-email and accepts a parameter called email.
Let's interact with it as follows.
Regular Expression Denial of Service (ReDoS)
Submit the above regex to regex101.com for an in-depth explanation. Then, submit the above regex to https://jex.im/regulex/ for a visualization.

The second and third groups are doing bad iterative checks.
Let's submit the following valid value and see how long the API takes to respond.
Regular Expression Denial of Service (ReDoS)
You will notice that the API takes several seconds to respond and that longer payloads increase the evaluation time.
The difference in response time between the first cURL command above and the second is significant.
The API is undoubtedly vulnerable to ReDoS attacks.
XML External Entity (XXE) Injection
By the time we browse http://<TARGET IP>:3001, we come across an authentication page.
Run Burp Suite as follows.
Activate burp suite's proxy (Intercept On) and configure your browser to go through it.
Now let us try authenticating. We should see the below inside Burp Suite's proxy.

We notice that an API is handling the user authentication functionality of the application.
User authentication is generating XML data.
Let us try crafting an exploit to read internal files such as /etc/passwd on the server.
First, we will need to append a DOCTYPE to this request.
What is a DOCTYPE? == DTD stands for Document Type Definition. A DTD defines the structure and the legal elements and attributes of an XML document. A DOCTYPE declaration can also be used to define special characters or strings used in the document. The DTD is declared within the optional DOCTYPE element at the start of the XML document. Internal DTDs exist, but DTDs can be loaded from an external resource (external DTD).
Our current payload is:
We defined a DTD called pwn, and inside of that, we have an ENTITY. We may also define custom entities (i.e., XML variables) in XML DTDs to allow refactoring of variables and reduce repetitive data. This can be done using the ENTITY keyword, followed by the ENTITY name and its value.
We have called our external entity somename, and it will use the SYSTEM keyword, which must have the value of a URL, or we can try using a URI scheme/protocol such as file:// to call internal files.
Let us set up a Netcat listener as follows.
eldeim@htb[/htb]$ nc -nlvp 4444
Now let us make an API call containing the payload we crafted above.
We notice no connection being made to our listener. This is because we have defined our external entity, but we haven't tried to use it. We can do that as follows.
After the call to the API, you will notice a connection being made to the listener.
Last updated