Skip to main content
SAP Pentest Playbook
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

SOAP-RFC over HTTP

Description

The ICF service /sap/bc/soap/rfc is SAP’s documented SOAP-over-HTTP bridge into the RFC-enabled function-module surface: any FM reachable over binary RFC (see critical RFC-enabled function modules) is also callable by POSTing a urn:sap-com:document:sap:rfc:functions SOAP envelope to this endpoint. SAP’s own hardening literature lists /sap/bc/soap/rfc among services that “shouldn’t be enabled unless needed” - precisely because it exposes the same high-impact FM surface over plain HTTP(S), a channel far more likely to survive network segmentation and firewalling than the RFC Gateway ports (33XX/48XX).

Two authentication modes reach the same endpoint/namespace:

  • HTTP Basic auth - a real SAP username/password in the Authorization header. Requires no attacker-controlled credential material beyond a valid logon; the same S_RFC and FM-level authorization requirements apply as for binary RFC.
  • MYSAPSSO2 cookie replay - a captured or forged SAP Logon Ticket presented as Cookie: MYSAPSSO2=<base64>, with no username/password ever sent. A forged ticket requires prior OS-command-execution access to the issuing system to steal its STRUSTSSO2 PSE and PIN (out of scope here - see the SecStore/trust-key material discussion under secure store decryption); a captured ticket is a straightforward replay attack.

SAP’s SOAP-RFC serializer only returns a TABLES parameter if the request declared it, even as an empty placeholder - omitting one can silently hide server-side data (e.g. a SAP_ALL grant returned in BAPI_USER_GET_DETAIL’s PROFILES/ACTIVITYGROUPS tables) from the caller’s view without indicating any error.

Risk

An attacker who can reach only the ICM HTTP(S) port - not the RFC Gateway port, and without the NW RFC SDK/pyrfc installed - gets the full binary-RFC capability set: privileged user creation, OS command execution, arbitrary ABAP, generic table reads, and RFC destination pivoting (see critical RFC-enabled function modules). Where a forged or captured MYSAPSSO2 ticket is available, this becomes a passwordless path entirely independent of the target’s credential hygiene.

Options

  • Reachability/credential check - POST an RFC_PING envelope with Content-Type: text/xml; charset=utf-8 and an empty, quoted SOAPAction: "" header (SAP’s ICM rejects a non-empty SOAPAction as “invalid action”); a distinguishing HTTP 500 SOAP-fault body means invalid credentials/no S_RFC for the function group, a clean 200 means a live session.
  • Privilege escalation - chain BAPI_USER_CREATE1 -> BAPI_USER_PROFILES_ASSIGN(["SAP_ALL"]) -> BAPI_TRANSACTION_COMMIT(wait=True) over the same envelope shape as the binary-RFC path; see critical RFC-enabled function modules for the FM-level detail.
  • OS command execution over HTTP - SXPG_STEP_XPG_START; retry without MXROW on older kernels (RFC_INVALID_PARAMETER). See OS command execution.
  • Table read / arbitrary ABAP / destination pivot - RFC_READ_TABLE, RFC_ABAP_INSTALL_AND_RUN, DEST_RFC_TCPIP_CREATE/DEST_CHECK_CONNECTION - same envelope shape, same authorization requirements as binary RFC.
  • Ticket-replay path (post-compromise) - instantiate a client with Cookie: MYSAPSSO2=<ticket> instead of Basic auth; SAP’s ICM authenticates the cookie identically to a browser-issued Logon Ticket and executes as the user encoded in it. Fetch a CSRF token first (X-CSRF-Token: fetch GET) - some kernels enforce it even for this class of client.
  • Tooling: SAPMAP modules/protocols/sap_soap_envelopes.py (envelope build/parse), modules/protocols/sap_soap_basic.py (Basic-auth transport), modules/exploitation/sap_soap_rfc.py (MYSAPSSO2-cookie transport, generic call(fm_name, params)); manual equivalent: curl/Postman/SoapUI against the FM’s generated WSDL (/sap/bc/soap/wsdl11?services=<FM>).
Note
When building requests by hand, declare every expected TABLES parameter as an empty placeholder tag even when you expect no rows - omitting it can cause the kernel to silently drop populated response tables rather than return them empty.

Mitigation

  • Deactivate the /sap/bc/soap/rfc ICF node in SICF unless a documented business scenario requires it.
  • If required, restrict by network/S_ICF to known integration source IPs, and enforce TLS/SNC.
  • Apply the same FM-level authorization hygiene as binary RFC (see critical RFC-enabled function modules) - transport choice does not change S_RFC/object-level requirements.
  • Protect the trust chain a forged ticket depends on: restrict access to STRUSTSSO2 PSEs and any SecStore/SSFS material that could yield a signing key (see secure store decryption); rotate trust certificates if compromise is suspected.
  • Keep login/accept_sso2_ticket/login/create_sso2_ticket and ticket validity windows tightly scoped; bind tickets to expected domains.

Detection and Monitoring

  • Security Audit Log (SM20): FM calls over SOAP-RFC generate the same audit events as binary RFC provided the RFC/CPIC-logon and dangerous-FM-call audit classes are active - verify class coverage, not just dialog logon.
  • ICM/web access logs: POSTs to /sap/bc/soap/rfc?sap-client=... with the fixed empty SOAPAction: "" header are a distinguishing fingerprint of this class of client versus a generated WSDL client.
  • Cookie: MYSAPSSO2=... present with no Authorization: Basic header, combined with repeated X-CSRF-Token: fetch GETs, distinguishes the ticket-replay transport from the Basic-auth transport.
  • SXPG_STEP_XPG_START/RFC_ABAP_INSTALL_AND_RUN/DEST_RFC_TCPIP_CREATE/BAPI_USER_CREATE1/BAPI_USER_PROFILES_ASSIGN arriving via the SOAP-RFC ICF service (rather than a known integration RFC destination) is high-confidence malicious activity.
  • Any successful MYSAPSSO2 logon for a user with no active browser/portal session at the claimed source, or from a source inconsistent with the ticket-issuing system’s trust boundary.

References