| name | performing-soap-web-service-security-testing |
| description | Perform security testing of SOAP web services by analyzing WSDL definitions and testing for XML injection, XXE, WS-Security bypass, and SOAPAction spoofing. |
| domain | cybersecurity |
| subdomain | api-security |
| tags | ["soap","web-services","wsdl","xml-injection","xxe","ws-security","penetration-testing","soapaction-spoofing","xpath-injection"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
| nist_csf | ["PR.PS-01","ID.RA-01","PR.DS-10","DE.CM-01"] |
| mitre_attack | ["T1190","T1059.007","T1552.001","T1055","T1059"] |
Performing SOAP Web Service Security Testing
Overview
SOAP (Simple Object Access Protocol) web services remain widely deployed in enterprise environments, financial systems, healthcare, and government integrations. Security testing of SOAP services involves analyzing WSDL (Web Services Description Language) definitions to understand available methods, testing for XML-based injection attacks (XXE, XPath injection, XML bombs), evaluating WS-Security implementation correctness, SOAPAction header spoofing, and assessing authentication and authorization controls. Unlike REST APIs, SOAP services use XML envelopes and often implement complex security standards that can be misconfigured.
When to Use
- When conducting security assessments that involve performing soap web service security testing
- When following incident response procedures for related security events
- When performing scheduled security testing or auditing activities
- When validating security controls through hands-on testing
Prerequisites
- Target SOAP web service endpoint URL
- WSDL file or URL access for the service
- SoapUI or ReadyAPI for structured testing
- Burp Suite with SOAP extensions for interception
- Python 3.8+ with zeep and lxml libraries
- Authorization to perform security testing
Testing Methodology
Phase 1: WSDL Reconnaissance
"""SOAP Web Service Security Testing Tool
Analyzes WSDL definitions and tests SOAP endpoints for
common vulnerabilities including XXE, injection, and
WS-Security misconfigurations.
"""
import requests
import xml.etree.ElementTree as ET
from lxml import etree
import sys
import re
from typing import List, Dict, Optional
from dataclasses import dataclass
@dataclass
class SOAPOperation:
name: str
action: str
input_message:
output_message:
parameters: []
:
NAMESPACES = {
: ,
: ,
: ,
: ,
: ,
}
():
.wsdl_url = wsdl_url
.endpoint_url = endpoint_url
.operations: [SOAPOperation] = []
.findings: [] = []
() -> [SOAPOperation]:
response = requests.get(.wsdl_url, timeout=)
root = etree.fromstring(response.content)
.endpoint_url:
address = root.find(, .NAMESPACES)
address :
.endpoint_url = address.get()
binding_op root.findall(, .NAMESPACES):
name = binding_op.get()
soap_op = binding_op.find(, .NAMESPACES)
action = soap_op.get(, ) soap_op
operation = SOAPOperation(name=name, action=action, input_message=, output_message=, parameters=[])
.operations.append(operation)
()
op .operations:
()
.operations
() -> :
xxe_payloads = [
{
: ,
: .(operation=operation.name),
},
{
: ,
: .(operation=operation.name),
},
{
: ,
: .(operation=operation.name),
},
]
results = []
xxe xxe_payloads:
:
response = requests.post(
.endpoint_url,
data=xxe[],
headers={
: ,
: operation.action,
},
timeout=,
)
vulnerable =
indicators = []
response.text response.text:
vulnerable =
indicators.append()
response.status_code == response.text:
indicators.append()
response.elapsed.total_seconds() > :
indicators.append()
vulnerable =
result = {
: xxe[],
: vulnerable,
: response.status_code,
: response.elapsed.total_seconds(),
: indicators,
}
results.append(result)
vulnerable:
.findings.append(
{: , : , : operation.name, : xxe[]}
)
requests.exceptions.Timeout:
results.append(
{
: xxe[],
: ,
: [],
}
)
{: operation.name, : results}
() -> :
sqli_payloads = [
,
,
,
,
,
]
results = []
payload sqli_payloads:
soap_body =
:
response = requests.post(
.endpoint_url,
data=soap_body,
headers={
: ,
: operation.action,
},
timeout=,
)
sql_errors = [
,
,
,
,
,
,
,
,
]
error_found = (err response.text err sql_errors)
error_found:
.findings.append(
{
: ,
: ,
: operation.name,
: ,
}
)
results.append(
{
: payload,
: response.status_code,
: error_found,
: response.elapsed.total_seconds(),
}
)
requests.exceptions.RequestException:
{: operation.name, : results}
() -> :
results = []
i, operation (.operations):
j, other_op (.operations):
i == j:
soap_body =
:
response = requests.post(
.endpoint_url,
data=soap_body,
headers={
: ,
: other_op.action,
},
timeout=,
)
response.status_code == response.text:
.findings.append(
{
: ,
: ,
: operation.name,
: ,
}
)
results.append(
{: operation.name, : other_op.action, : }
)
requests.exceptions.RequestException:
{: results}
() -> :
test_cases = [
{: , : },
{
: ,
: ,
},
{
: ,
: ,
},
]
results = []
test test_cases:
.operations:
operation = .operations[]
soap_body =
:
response = requests.post(
.endpoint_url,
data=soap_body,
headers={: },
timeout=,
)
accepted = response.status_code == response.text
accepted:
.findings.append(
{
: ,
: ,
: operation.name,
: test[],
}
)
results.append({: test[], : accepted, : response.status_code})
requests.exceptions.RequestException:
{: results}
() -> :
{
: .endpoint_url,
: .wsdl_url,
: (.operations),
: (.findings),
: ([f f .findings f[] == ]),
: ([f f .findings f[] == ]),
: .findings,
}
():
wsdl_url = sys.argv[] (sys.argv) >
tester = SOAPSecurityTester(wsdl_url)
()
operations = tester.parse_wsdl()
op operations:
()
tester.test_xxe_vulnerability(op)
tester.test_sql_injection(op)
tester.test_soapaction_spoofing()
tester.test_ws_security_bypass()
report = tester.generate_report()
()
()
()
()
()
()
finding report[]:
()
()
()
__name__ == :
main()