Lateral Movement Across SAP Landscapes
SAP landscapes are rarely a single isolated system. They are graphs of trust: SM59 RFC destinations carrying stored credentials or trusted-system flags, MYSAPSSO2/STRUSTSSO2 ticket-issuer trust, SAProuter route permissions, shared <sid>adm/DB-user OS credentials across DEV->QAS->PRD tiers, and - in hybrid landscapes - Cloud Connector/SM59 Type-G bridges into SAP BTP. A foothold on any one node of this graph routinely reaches others, often systems of a higher security classification than the one first compromised (sandbox/DEV RFC destinations pointing into PRD is the classic case). This page catalogs the SAP-specific trust-graph pivots; generic OS-level lateral movement (Windows credential reuse, general SSH tradecraft) is referenced out to standard sources rather than reproduced.
An attacker who compromises one low-classification system inherits reach across every system that system’s stored RFC credentials, trusted-system relationships, SSO-ticket trust, or shared OS credentials extend to - frequently including production. Because most of these pivots require no new exploit (only an already-configured trust relationship), lateral movement across an SAP landscape is typically the highest-leverage, lowest-effort step in an engagement once any single system is owned. Impact spans confidentiality, integrity, and availability of every system reached, compounding with each hop (see post-exploitation for end-state business impact once a hop lands).
- Stored dialog/technical-user credentials - an
SM59Type-3 destination carrying a stored user (dialog or technical) grants direct Remote Logon or RFC-call access to the target system under that user’s authorizations. Especially critical when the source system has a lower security classification than the target (sandbox->PRD, DEV->PRD, QAS->PRD). - Trusted-system relationship (
SMT1/RFCTRUST/RFCSYSACL, authorization objectS_RFCACL) - a passwordless pivot: any user holdingS_RFCACLin the trusting system can log on as themselves in the trusted system with no password check at all. Distinct from and not to be confused with the Message Server/Gateway “betrusted” trust described below - SAP’s own naming overlaps but the mechanisms are unrelated. S_RFCfield granularity - inbound RFC execution is gated byS_RFCon fieldsRFC_TYPE(function group vs. single module),RFC_NAME, andACTVT = 16(execute). SAP deliberately withholdsRFC_READ_TABLEfrom standard technical-user roles (e.g. Solution Manager READ/TMW users) precisely because it can read almost any table - so a stored technical RFC user that does carry it, or a wildcardS_RFC, is an outsized find on the far side of a hop.- Graph analysis / chain discovery - SAPMAP
modules/postex/sapmap_chain.py: bounded BFS over every RFC destination + STRUSTSSO2 trust pair a session has already discovered, ranking reachable targets by severity and rendering a human headline (e.g. “S4H -> BTP:a1b2c3d4 -> ECP - Production reached in 2 hops [trusted RFC]”). Traversal only continues past a hop that isSAP_ALL-bearing, trusted-RFC, or a forged-ticket edge - a plain tested logon proves reachability but not onward pivot. - Discovery of the destination table itself - schedule report
RSRFCCHKover the XBP background-job interface to enumerate everySM59destination with a stored password, or readRFCDESdirectly viaRFC_READ_TABLE. - Payload once a hop lands - the critical RFC-enabled function modules page (
RFC_READ_TABLE,SXPG_*,RFC_ABAP_INSTALL_AND_RUN,BAPI_USER_CREATE1) is the standard payload set on the far side of any RFC pivot. - Manual equivalent:
SM59destination review + Remote Logon;SE16/SE16NonRFCDES/RFCTRUST/RFCSYSACL. - Cross-ref: Message Server Trust Injection into Gateway ACL (10KBLAZE “betrusted”) is a network-level trust bypass unrelated to
S_RFCACLdespite similar terminology.
- Prerequisite: a forged ticket - see Forging SAP Logon Tickets (MYSAPSSO2) for the PSE-theft/forge primitive.
- Replay across the trust graph - SAPMAP
modules/exploitation/sap_ticket_propagate.py: replays the forged ticket over the HTTP cookie channel (Cookie: MYSAPSSO2=<base64>against ICF/WebGUI endpoints, classified by login-form/Set-Cookieheuristics) and the RFC channel (pyrfc.Connection(mysapsso2=<cookie>)+RFC_PING). Candidate-receiver set = every node sharing the issuer’s SID (self-trust - always works, a system trusts its own signing cert) plus an operator-supplied list drawn from the issuer’sSTRUSTSSO2/TWPSSO2ACL(the tool does not itself enumerate that table). A ticket forged as a pinned assertion ticket (RecipientSID/RecipientClient) collapses the candidate set to just that one receiver. - Manual equivalent:
curl -b "MYSAPSSO2=<b64>" https://host:port/sap/bc/...per candidate system;pyrfc.Connection(mysapsso2=<b64>)+RFC_PING. - Blast radius beyond self-SID is entirely bounded by how well the
STRUSTSSO2trust graph is scoped - review it per target as part of any assessment.
- See SAProuter Route-Permission Table Abuse (Open Proxy / niroute Pivot) for the full technique:
NI_ROUTEtunneling through a permissivesaprouttab, an ACL-aware port-probe side channel that maps internal reachability without completing a tunnel, and the “Trusted Router Hack” (daisy-chaining a second attacker-controlled SAProuter through the target’s own permissive route table when hop limits aren’t configured). - Once a tunnel is established, any other SAP protocol runs over it unmodified - chain into RFC Gateway 10KBLAZE / SAPXPG or Message Server Trust Injection against systems behind the SAProuter that are not otherwise externally reachable.
- Generic or shared dialog/technical users configured identically (same password, same RFC destination pattern) across development, quality-assurance, and production tiers turn a single compromised credential into landscape-wide access, independent of any RFC-destination trust - the credential itself is the pivot.
- Where the shared account holds excessive
S_RFCscope, chain intoBAPI_USER_CREATE1->BAPI_USER_PROFILES_ASSIGNto mint a persistentSAP_ALLuser in the higher-tier target. - Manual equivalent:
SM59/SU01cross-system user/credential comparison; review of RFC destinations whose stored user is identical across tiers.
- On-prem -> BTP (credential harvest + token mint) - SAPMAP
modules/exploitation/sap_onprem_to_btp.py: mines already-captured on-prem credential material -SM59HTTP destinations with a decrypted SecStore password,OA2C_CLIENT/OA2C_CLIENT_EXTOAuth2 client profiles joined against their SecStore secret, rawRSECTAB, and Java SecStoreFS - for anything resolving to a*.hana.ondemand.comhost, then mints a live BTP token three ways: (1)mint_btp_token()- plain HTTP Basic-Authclient_credentialsgrant against XSUAA/oauth/token; (2)mint_btp_token_via_cert()- mTLS/RFC 8705client_credentials, kernel-proxied through the on-prem system’s ownSM59destination viaRFC_ABAP_INSTALL_AND_RUN(a generated ABAP report opens the destination withCL_HTTP_CLIENT=>CREATE_BY_DESTINATION, so the on-prem kernel performs the mTLS handshake using its ownSTRUSTPSE - the private key never leaves the kernel); (3)mint_btp_token_via_local_cert()- the same RFC 8705 flow issued directly from the operator host with a local cert/key pair (a documented workaround for a kernel 7.53 HTTP/2->1.1 chunked-response body-loss bug). - BTP -> on-prem (Destination-service credential hijack) - see Destination Service Abuse and SM59 Destination SSRF: the Destination service returns on-prem technical-user credentials in clear text to any caller holding a token scoped to read destination configuration, letting a BTP-side foothold pivot back down into the on-prem backend the destination points at.
- Principal propagation abuse - see SAP Cloud Connector Principal Propagation Impersonation for identity-forwarding abuse specific to the Cloud Connector bridge, and SAP Cloud Connector Admin Access & Keystore/SSFS Extraction for extracting the Connector’s own credential material.
- Prerequisite for the harvest step: prior on-prem Secure Store decryption (RSECTAB/SSFS) to recover cleartext secrets.
- Manual equivalent:
SE16/SE16NonRSECTAB,SM59destination inspection,SU01/SOA_MANAGERreview ofOA2C_CLIENT;curl -u client_id:client_secret <uaa_url> -d grant_type=client_credentialsfor the basic-auth mint.
- SAPMAP
modules/postex/sap_ssh_lateral.py: from an existing OS command-execution foothold, harvests/etc/passwdplus~/.ssh/{id_*,config,known_hosts,authorized_keys}from every home directory, tests harvested keys againstknown_hosts/already-discovered nodes to map new SSH pivots, and (optionally) plants a persistent public key intoauthorized_keys- a hardcoded, deterministic ed25519 key commentedsapmap@pentest, a clean IOC by design. - The SAP-specific value is the entry point:
<sid>admand DB-user accounts frequently have broad, shared SSH reach across a landscape’s host estate, so a single SAP OS-exec foothold (OS command execution, RFC Gateway 10KBLAZE, virtual SAP*) often unlocks the whole host estate. The SSH mechanics themselves are generic OS-level tradecraft - reference standard SSH pentest guidance for execution detail rather than reproducing it here.
- Do not create RFC connections from lower-classification systems (sandbox, DEV, QAS) to higher-classification systems (PRD) without a documented business requirement and compensating controls.
- Regularly review
SM59destinations for stored credentials; do not store dialog-user credentials in RFC destinations at all. - Restrict
S_RFCper RFC user to the minimal function-group set required; never grantSAP_ALLto a stored RFC-destination user. - Review and minimize trusted-system relationships (
SMT1) andS_RFCACLgrants separately from ordinaryS_RFCreview; avoid trust from lower- to higher-classified systems. - Apply the message-server/gateway hardening set (SAP Notes 1421005, 821875, 1408081, 1444282) so the unrelated “betrusted” network-level trust bypass cannot seed an RFC-trust chain in the first place.
- Restrict OS-level access to
$SECUDIR(SAPSYS.pse,cred_v2) so ticket-signing keys cannot be stolen in the first place - see MYSAPSSO2 ticket forgery mitigation. - Keep
STRUSTSSO2pruned to only necessary trusted-issuer certificates; remove stale entries. - Prefer SNC/X.509 client-certificate SSO over cookie tickets for high-value systems; use short ticket validity.
- See SAProuter Route-Permission Table Abuse mitigation - harden
saprouttabwith narrowly-scoped, explicitP/Srules terminated byD * * *, limit route hop counts, require route passwords.
- Use dedicated, per-tier technical users - never reuse the same account/password across DEV/QAS/PRD.
- Rotate stored technical-user passwords on a schedule; restrict such users to minimum required authorizations.
- Treat every
SM59HTTP destination,OA2C_CLIENTprofile, and SecStore entry pointing at*.hana.ondemand.comas Tier-0 material - rotate on any suspected on-prem compromise. - Prefer x509/PSE-bound destinations over static client-secret Basic-Auth OA2C bindings; a stolen PSE still requires the on-prem kernel (or a stolen private-key file) to exercise.
- Apply least-privilege scoping to every OAuth2 client registered against a subaccount so a harvested credential grants minimum blast radius.
- See Destination Service Abuse mitigation for the BTP->on-prem direction.
- Harden the upstream SAP OS-exec channels (Gateway ACLs,
SXPGrestriction) to deny the initial foothold this pivot depends on. - Do not share SSH keys across the landscape; scope
<sid>adm/DB-user SSH reach per host; use bastions. - Monitor
authorized_keysfor unexpected entries.
- RFC trust graph: an attacker who can read/test
SM59destinations across many systems in quick succession, or replay a forged ticket across multiple trusting systems in sequence, produces a distinctive multi-system access pattern - correlateSM59/STRUSTSSO2reads and RFC logon attempts across systems in a SIEM rather than per-system only. - SSO replay: Security Audit Log (
SM20/RSAU) SSO-ticket logons from unusual source IPs, especiallySAP*/DDICor production clients; ICM/ICF access logs forCookie: MYSAPSSO2=...on unexpected endpoint/client combinations. - SAProuter:
dev_rout/saprouter -Glog - high volume of distinct destination host/port combinations from one source in a short window; see route_string_abuse.md Detection. - On-prem->BTP:
RFC_ABAP_INSTALL_AND_RUNexecution and dynamic report compilation (e.g. a generatedZHTTPDEST-style report) where ad-hoc report generation via RFC is not an expected admin workflow - audit via Security Audit Log; outboundCL_HTTP_CLIENTcalls to*.hana.ondemand.comfrom anSM59destination not normally exercised at that frequency. - BTP/XSUAA: anomalous
client_credentialstoken-mint volume perclient_id, especially x509-bound clients whose certificate thumbprint doesn’t match the expected calling system; repeated basic-auth failures followed by success (credential-iteration signature). - SAP->OS->SSH:
authorized_keyscontaining the stringsapmap@pentestis a direct tool IOC; more generally, anomalous reads of~/.ssh/private keys by an SAP work-process/<sid>admcontext, or SSH logins originating from a SAP host to atypical targets.
- SAP Note 2253549 - SAP Security Baseline Template
- SAP Note 821875 - Security settings in the message server
- SAP Note 1421005 - Secure configuration of the message server
- SAP Note 1408081 - Basic settings for reg_info and sec_info
- SAP Note 1444282 - gw/reg_no_conn_info settings
- SAP Note 30289 - SAProuter documentation
- RFC 8705 - OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
- SAP Help Portal - Authorization Object
S_RFCACL - SAP Help Portal - Authorization Object
S_RFC(RFC_TYPE/RFC_NAME/ACTVTfields) - SAP Help Portal - Technical Users for RFC Connections (READ/TMW) (
RFC_READ_TABLEwithheld from technical roles) - SAP Help Portal - RFC/ICF Security Guide
- SAP Help Portal - Security Audit Log
- SAP Help - Calling the Destination Service REST API
- pysap (OWASP CBAS)
- Critical RFC-Enabled Function Modules
- Forging SAP Logon Tickets (MYSAPSSO2)
- SM59 Destination SSRF
- Secure Store decryption
- Post-Exploitation
