Post

SOAP

SOAP

1. Basic Concepts of SOAP

Contrary to its name, SOAP (Simple Object Access Protocol) is not a simple protocol. It is platform and language independent, offering flexibility to operate over various protocols like HTTP, SMTP, and TCP. The core of SOAP is that it uses XML (eXtensible Markup Language) to define messages.

SOAP Message Structure

All SOAP messages follow a standardized XML structure:

  • Envelope (Required): The top-level element of a SOAP message, indicating the start and end of the message. It defines the XML namespace to identify the message as a SOAP message.
  • Header (Optional): Contains additional information not directly related to the message body. It’s primarily used for handling metadata such as authentication tokens, transaction IDs, and routing information. The header allows for adding various functionalities to the message processing, forming the basis for powerful security features when combined with standards like WS-Security.
  • Body (Required): Contains the actual data to be transmitted, namely the name and parameter information of the remote procedure call (RPC) to be invoked. The core content of the service request is located here.
  • Fault (Optional): An element used when an error occurs during message processing. It is included within the Body element and conveys detailed information such as the error code, description, and the location of the error to the client.

SOAP Message Example

The following is a hypothetical SOAP message example requesting the price of a specific stock. This example clearly shows how each component is used.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
xmlns:m="http://www.example.org/stock">
  <soap:Header>
    <m:TransactionID>5</m:TransactionID>
  </soap:Header>
  <soap:Body>
    <m:GetStockPrice>
      <m:StockName>GOOG</m:StockName>
    </m:GetStockPrice>
  </soap:Body>
</soap:Envelope>
  • soap:Envelope: The root element of the message, defining two namespaces, soap and m.
  • soap:Header: Contains metadata called TransactionID. This ID can be used for logging or transaction tracking.
  • soap:Body: Contains the actual content the client is requesting from the server. Here, it’s calling an operation named GetStockPrice and passing ‘GOOG’ as the StockName parameter.

As you can see, SOAP messages have a clear and standardized structure, allowing for the systematic representation of complex requests.

WSDL (Web Services Description Language)

When discussing SOAP, WSDL is indispensable. WSDL is an XML-based specification that describes everything about a web service. It details the functions (Operations) provided by the service, the message formats required for each function, data types, and the endpoint addresses for accessing the service. Clients can refer to this WSDL file to clearly understand how to communicate with the server, enabling strict contract-first development.


2. SOAP vs. REST: A Comparison of Key Differences

SOAP and REST are two different approaches to implementing web services, each with distinct advantages and disadvantages.

CategorySOAP (Simple Object Access Protocol)REST (Representational State Transfer)
ParadigmProtocolArchitectural Style
Data FormatXML onlySupports various formats like JSON, XML, TEXT, HTML
Transport ProtocolSupports various protocols like HTTP, SMTP, TCP (independent)Primarily relies on HTTP
State ManagementCan be stateful or statelessAdheres to the principle of being stateless
PerformanceRelatively heavy and slow due to XML parsing and strict structureFast performance due to lightweight messages and caching
SecurityProvides robust security features like message-level encryption and signatures through the WS-Security standardRelies on transport-layer security via HTTPS. Application-level security implemented with OAuth, JWT, etc.
ScalabilityHorizontal scaling can be difficult with stateful approachesHorizontal scaling is easy due to its stateless nature
SpecificationDefines strict contracts through an official specification called WSDLAPIs can be described using the OpenAPI Specification (Swagger), but it’s not mandatory

In summary, SOAP is suitable for enterprise environments such as finance, government, and healthcare, where a high level of security, reliability, and transaction integrity must be guaranteed through its standardized and strict structure. On the other hand, REST is widely used in mobile apps, public APIs, and microservices architectures, leveraging its flexibility, simplicity, and fast performance.


3. SOAP Security Vulnerabilities: Attack Vectors and Countermeasures

Despite SOAP’s strong security features, its XML-based nature and complexity can expose it to various security vulnerabilities. Red teams and security engineers should be familiar with the following attack vectors.

1. XML External Entity (XXE) Injection

This is one of the most critical SOAP vulnerabilities. It occurs when the XML parser is configured to process external entities. An attacker can send a SOAP request containing a maliciously crafted XML entity to read local files on the server, conduct Server-Side Request Forgery (SSRF) attacks on the internal network, or even lead to remote code execution.

Attack Example (File Exfiltration):

The attacker includes a request to load an external Document Type Definition (DTD) using the SYSTEM keyword. The example below is an attempt to read the contents of the /etc/passwd file.

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <m:GetUserDetails>
      <m:UserId>&xxe;</m:UserId>
    </m:GetUserDetails>
  </soap:Body>
</soap:Envelope>

If the server’s XML parser processes this request as is, the &xxe; entity will be replaced with the content of the /etc/passwd file, which could then be included in the response or exposed in some other way.

Countermeasures:

  • Disable External Entity Processing: The most effective solution is to disable the processing of external entities (including DTDs) in the XML parser you are using.
  • Input Validation: Always strictly validate and filter XML data received from untrusted sources.

2. XML Bomb (Billion Laughs Attack)

This is a type of Denial of Service (DoS) attack that utilizes recursive entity expansion. The attacker defines nested entities within a small XML request. As the parser expands these entities, memory usage increases exponentially, eventually exhausting the server’s resources and causing the service to crash.

Attack Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
  <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
  <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
  <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <message>&lol9;</message>
  </soap:Body>
</soap:Envelope>

The &lol9; in this request ultimately expands to one billion “lol” strings, occupying several gigabytes of memory.

Countermeasures:

  • Limit Entity Expansion: Limit the depth and number of entity expansions in the XML parser.
  • Resource Limiting: Limit the memory and CPU usage that individual requests can consume to minimize the impact of DoS attacks.
  • Use an API Gateway: Use an API gateway to validate message size, structure, etc., and block malicious requests beforehand.

3. WS-Security Misconfiguration

WS-Security is a powerful standard that provides message integrity (signing), confidentiality (encryption), and authentication. However, its complexity can easily lead to configuration errors. For example, a weak encryption algorithm might be used, signature verification might not be properly performed, or only certain headers might be encrypted while other important parts are left in plaintext.

Attack Vectors:

  • Replay Attack: An attacker intercepts a signed message and retransmits it to perform unauthorized actions. This occurs when elements like Timestamp or Nonce are not properly validated.
  • Signature Wrapping: The attacker leaves the signed Body part intact but adds a malicious Body. The original signed Body is moved elsewhere, causing the parser to validate the signature as valid but process the malicious Body.

Countermeasures:

  • Adhere to and Update Standards: Accurately understand and implement the WS-Security standard, and use up-to-date cryptographic suites with no known vulnerabilities.
  • Strict Validation: Thoroughly validate the uniqueness and validity period of messages using Timestamp, Nonce, etc., to prevent replay attacks.
  • Structural Validation: When verifying signatures, it’s crucial to confirm that the location and structure of the signed element match expectations to block signature wrapping attacks.

Python SOAP Client Example (Zeep library)

To help understand how a real SOAP request is made, here is a simple client code using Python’s zeep library.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import zeep

# Public calculator WSDL service URL
wsdl_url = 'http://www.dneonline.com/calculator.asmx?WSDL'

try:
    # 1. Create a client object using the WSDL URL
    client = zeep.Client(wsdl=wsdl_url)

    # 2. Call a service operation (Add)
    # Uses parameters intA and intB as per the WSDL specification
    result = client.service.Add(intA=10, intB=20)

    # 3. Print the result
    print(f"10 + 20 = {result}")

    # Call the Divide operation
    result_div = client.service.Divide(intA=20, intB=10)
    print(f"20 / 10 = {result_div}")

except Exception as e:
    print(f"An error occurred: {e}")

This code analyzes the WSDL to identify available services (like Add, Divide, etc.) and sends a request in the appropriate format to get the result. From a security testing perspective, one could intercept such a request with a proxy tool (e.g., Burp Suite) and inject payloads to test for the vulnerabilities mentioned above.


1. SOAP의 기본 개념

SOAP은 그 이름과 달리 그리 간단하지 않은 프로토콜입니다. 특정 플랫폼이나 언어에 종속되지 않고, 주로 HTTP, SMTP, TCP 등 다양한 프로토콜 위에서 동작할 수 있는 유연성을 가집니다. SOAP의 핵심은 XML(eXtensible Markup Language)을 사용하여 메시지를 정의한다는 점입니다.

SOAP 메시지 구조

모든 SOAP 메시지는 다음과 같은 표준화된 XML 구조를 따릅니다.

  • Envelope (필수): SOAP 메시지의 최상위 요소로, 메시지의 시작과 끝을 알립니다. XML 네임스페이스를 정의하여 메시지를 SOAP 메시지로 식별합니다.
  • Header (선택): 메시지 본문과 직접적인 관련이 없는 부가 정보를 담습니다. 주로 인증 토큰, 트랜잭션 ID, 라우팅 정보 등과 같은 메타데이터를 처리하는 데 사용됩니다. 헤더를 통해 메시지 처리 과정에 다양한 기능을 추가할 수 있으며, 이는 WS-Security와 같은 표준과 결합하여 강력한 보안 기능을 제공하는 기반이 됩니다.
  • Body (필수): 실제 전송될 데이터, 즉 호출하려는 원격 프로시저(RPC)의 이름과 매개변수 정보를 담고 있습니다. 서비스 요청의 핵심 내용이 바로 여기에 위치합니다.
  • Fault (선택): 메시지 처리 중 오류가 발생했을 때 사용되는 요소입니다. Body 요소 내에 포함되며, 오류 코드, 설명, 오류 발생 위치 등의 상세 정보를 클라이언트에게 전달합니다.

SOAP 메시지 예시

다음은 특정 주식의 가격을 요청하는 가상의 SOAP 메시지 예시입니다. 이 예시를 통해 각 구성요소가 어떻게 사용되는지 명확히 알 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0"?>
<soap:Envelope
xmlns:soap="http://www.w3.org/2003/05/soap-envelope/"
xmlns:m="http://www.example.org/stock">
  <soap:Header>
    <m:TransactionID>5</m:TransactionID>
  </soap:Header>
  <soap:Body>
    <m:GetStockPrice>
      <m:StockName>GOOG</m:StockName>
    </m:GetStockPrice>
  </soap:Body>
</soap:Envelope>
  • soap:Envelope: 메시지의 루트 요소로, soapm이라는 두 개의 네임스페이스를 정의합니다.
  • soap:Header: TransactionID라는 메타데이터를 포함합니다. 이 ID는 로깅이나 트랜잭션 추적에 사용될 수 있습니다.
  • soap:Body: 클라이언트가 서버에 요청하는 실제 내용을 담고 있습니다. 여기서는 GetStockPrice라는 작업을 호출하고 있으며, StockName이라는 매개변수로 ‘GOOG’를 전달하고 있습니다.

이처럼 SOAP 메시지는 그 구조가 명확하고 표준화되어 있어, 복잡한 요청도 체계적으로 표현할 수 있습니다.

WSDL (Web Services Description Language)

SOAP을 이야기할 때 WSDL을 빼놓을 수 없습니다. WSDL은 웹 서비스의 모든 것을 설명하는 XML 기반의 명세서입니다. 서비스가 제공하는 기능(Operations), 각 기능에 필요한 메시지 형식, 데이터 타입, 그리고 서비스에 접근할 수 있는 엔드포인트(Endpoint) 주소 등이 상세하게 정의되어 있습니다. 클라이언트는 이 WSDL 파일을 참조하여 서버와 어떻게 통신해야 하는지 명확하게 알 수 있으며, 이를 통해 엄격한 계약 기반(Contract-first) 개발이 가능해집니다.


2. SOAP vs. REST: 핵심 차이점 비교

SOAP과 REST는 웹 서비스를 구현하는 두 가지 다른 접근 방식이며, 각각의 장단점이 뚜렷합니다.

구분SOAP (Simple Object Access Protocol)REST (Representational State Transfer)
패러다임프로토콜(Protocol)아키텍처 스타일(Architectural Style)
데이터 형식XML만 사용JSON, XML, TEXT, HTML 등 다양한 형식 지원
전송 프로토콜HTTP, SMTP, TCP 등 다양한 프로토콜 지원 (독립적)주로 HTTP에 의존
상태 관리상태 유지(Stateful) 또는 상태 비유지(Stateless) 모두 가능상태 비유지(Stateless)를 원칙으로 함
성능XML 파싱, 엄격한 구조로 인해 상대적으로 무겁고 느림메시지가 가볍고 캐싱을 활용하여 빠른 성능
보안WS-Security라는 표준을 통해 메시지 레벨 암호화, 서명 등 강력한 보안 기능 제공HTTPS를 통한 전송 계층 보안에 의존. OAuth, JWT 등으로 애플리케이션 레벨 보안 구현
확장성상태 유지(Stateful) 방식으로 인해 수평적 확장이 어려울 수 있음상태 비유지(Stateless) 방식으로 인해 수평적 확장이 용이함
명세WSDL이라는 공식 명세를 통해 엄격한 계약 정의OpenAPI Specification (Swagger) 등으로 API를 기술하지만, 필수는 아님

요약하자면, SOAP은 표준화되고 엄격한 구조를 통해 높은 수준의 보안, 신뢰성, 트랜잭션이 보장되어야 하는 금융, 정부, 의료 등 엔터프라이즈 환경에 적합합니다. 반면 REST유연성, 단순함, 빠른 성능을 바탕으로 모바일 앱, 공개 API, 마이크로서비스 아키텍처 등에서 널리 사용됩니다.


3. SOAP 보안 취약점: 공격 벡터 및 대응 방안

SOAP의 강력한 보안 기능에도 불구하고, XML 기반이라는 특성과 복잡성으로 인해 다양한 보안 취약점에 노출될 수 있습니다. 레드팀 및 보안 엔지니어는 다음과 같은 공격 벡터를 숙지하고 있어야 합니다.

1. XML 외부 개체 주입 (XML External Entity - XXE)

가장 치명적인 SOAP 취약점 중 하나입니다. XML 파서가 외부 개체(External Entity)를 처리하도록 설정되어 있을 때 발생합니다. 공격자는 악의적으로 조작된 XML 개체를 포함하는 SOAP 요청을 보내 서버의 로컬 파일을 읽거나, 내부 네트워크로의 SSRF(Server-Side Request Forgery) 공격을 감행하거나, 심지어 원격 코드 실행으로까지 이어질 수 있습니다.

공격 예시 (파일 탈취):

공격자는 SYSTEM 키워드를 사용하여 외부 DTD(Document Type Definition)를 로드하도록 요청에 포함시킵니다. 아래 예시는 /etc/passwd 파일의 내용을 읽어오려는 시도입니다.

1
2
3
4
5
6
7
8
9
10
11
<?xml version="1.0"?>
<!DOCTYPE foo [
  <!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <m:GetUserDetails>
      <m:UserId>&xxe;</m:UserId>
    </m:GetUserDetails>
  </soap:Body>
</soap:Envelope>

만약 서버의 XML 파서가 이 요청을 그대로 처리한다면, &xxe; 엔티티는 /etc/passwd 파일의 내용으로 치환되어 응답에 포함되거나 다른 방식으로 노출될 수 있습니다.

대응 방안:

  • 외부 개체 처리 비활성화: 사용하는 XML 파서에서 외부 개체(DTD 포함) 처리를 비활성화하는 것이 가장 확실한 해결책입니다.
  • 입력 값 검증: 신뢰할 수 없는 소스로부터 받은 XML 데이터는 항상 엄격하게 검증하고 필터링해야 합니다.

2. XML 폭탄 (Billion Laughs Attack)

서비스 거부(Denial of Service - DoS) 공격의 일종으로, 재귀적인 엔티티 확장을 이용합니다. 공격자는 작은 크기의 XML 요청 내에 여러 단계로 중첩된 엔티티를 정의합니다. 파서가 이 엔티티들을 확장하는 과정에서 메모리 사용량이 기하급수적으로 증가하여 결국 서버의 리소스를 고갈시키고 서비스를 마비시킵니다.

공격 예시:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?xml version="1.0"?>
<!DOCTYPE lolz [
  <!ENTITY lol "lol">
  <!ENTITY lol1 "&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;&lol;">
  <!ENTITY lol2 "&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;&lol1;">
  <!ENTITY lol3 "&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;&lol2;">
  <!ENTITY lol4 "&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;&lol3;">
  <!ENTITY lol5 "&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;&lol4;">
  <!ENTITY lol6 "&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;&lol5;">
  <!ENTITY lol7 "&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;&lol6;">
  <!ENTITY lol8 "&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;&lol7;">
  <!ENTITY lol9 "&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;&lol8;">
]>
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
  <soap:Body>
    <message>&lol9;</message>
  </soap:Body>
</soap:Envelope>

이 요청의 &lol9;는 최종적으로 10억 개의 “lol” 문자열로 확장되어 수 기가바이트의 메모리를 점유하게 됩니다.

대응 방안:

  • 엔티티 확장 제한: XML 파서에서 엔티티 확장의 깊이와 개수를 제한합니다.
  • 리소스 제한: 개별 요청이 사용할 수 있는 메모리와 CPU 사용량을 제한하여 DoS 공격의 영향을 최소화합니다.
  • API 게이트웨이 활용: API 게이트웨이를 사용하여 메시지 크기, 구조 등을 사전에 검증하고 유해한 요청을 차단합니다.

3. WS-Security 설정 오류

WS-Security는 메시지 무결성(서명), 기밀성(암호화), 인증을 제공하는 강력한 표준이지만, 복잡성으로 인해 설정 오류가 발생하기 쉽습니다. 예를 들어, 암호화 알고리즘이 취약하거나, 서명 검증이 제대로 이루어지지 않거나, 특정 헤더만 암호화하고 중요한 다른 부분은 평문으로 두는 등의 실수가 발생할 수 있습니다.

공격 벡터:

  • 메시지 재전송 공격(Replay Attack): 서명된 메시지를 탈취하여 그대로 재전송함으로써 비인가된 작업을 수행합니다. TimestampNonce와 같은 요소가 제대로 검증되지 않을 때 발생합니다.
  • 서명 래핑(Signature Wrapping): 서명된 Body 부분을 그대로 둔 채, 악의적인 Body를 추가하고 원래의 서명된 Body는 다른 곳으로 옮겨 파서가 서명은 유효하다고 판단하지만 실제로는 악의적인 Body를 처리하게 만드는 공격입니다.

대응 방안:

  • 표준 준수 및 최신화: WS-Security 표준을 정확히 이해하고 구현하며, 알려진 취약점이 없는 최신 암호화 스위트를 사용합니다.
  • 엄격한 검증: Timestamp, Nonce 등을 사용하여 메시지의 유일성과 유효 기간을 철저히 검증하여 재전송 공격을 방지합니다.
  • 구조적 유효성 검사: 서명 검증 시, 서명된 요소의 위치와 구조가 예상과 일치하는지 반드시 확인하여 서명 래핑 공격을 차단해야 합니다.

Python SOAP 클라이언트 예시 (Zeep 라이브러리)

실제 SOAP 요청이 어떻게 이루어지는지 이해를 돕기 위해 Python의 zeep 라이브러리를 사용한 간단한 클라이언트 코드를 소개합니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import zeep

# 공개 계산기 WSDL 서비스 URL
wsdl_url = 'http://www.dneonline.com/calculator.asmx?WSDL'

try:
    # 1. WSDL URL을 사용하여 클라이언트 객체 생성
    client = zeep.Client(wsdl=wsdl_url)

    # 2. 서비스가 제공하는 오퍼레이션 호출 (Add)
    # WSDL 명세에 따라 intA와 intB라는 매개변수를 사용
    result = client.service.Add(intA=10, intB=20)

    # 3. 결과 출력
    print(f"10 + 20 = {result}")

    # Divide 오퍼레이션 호출
    result_div = client.service.Divide(intA=20, intB=10)
    print(f"20 / 10 = {result_div}")

except Exception as e:
    print(f"An error occurred: {e}")

이 코드는 WSDL을 분석하여 사용 가능한 서비스(Add, Divide 등)를 파악하고, 해당 서비스에 맞는 형식으로 요청을 보내 결과를 받아옵니다. 보안 테스팅 관점에서는 이러한 요청을 프록시 도구(예: Burp Suite)로 가로채 위에서 언급한 취약점을 테스트하기 위한 페이로드를 삽입하는 방식으로 접근할 수 있습니다.

This post is licensed under CC BY 4.0 by the author.