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
Edit page

SAProuter Route-Permission Table Abuse (Open Proxy / niroute Pivot)

Description

SAProuter is an application-level proxy purpose-built for SAP’s own protocols (DIAG, RFC) that sits at the DMZ boundary between an untrusted network and the internal SAP landscape. Every access decision it makes is governed by a single text file, saprouttab (the route-permission table), evaluated top-down, first-match-wins: each line is [D|P|S] <source> <dest> <service> [<password>], where D=deny, P=permit (any protocol), S=permit SAP-protocol-only.

A client requests a route by sending a binary NI_ROUTE packet - the same thing SAP GUI builds internally from a route string typed into its “SAProuter” field, /H/<host>/S/<port>/W/<password>/H/<target>/S/<port>. If the route matches a P/S line before it matches any D line, the SAProuter accepts (NI_PONG) and becomes a transparent TCP tunnel to the target - any protocol (DIAG, RFC/gateway, HTTP) can then be spoken over it unmodified.

The classic, still-common misconfiguration is a trailing catch-all P * * * (or simply no D * * * deny-all at all) left at the end of saprouttab - “for convenience” during setup and never removed. Because evaluation stops at the first match, this one line silently defeats every narrower rule written above it and turns the SAProuter into an open proxy: any external client can request a route to any internal host/port the SAProuter can reach. The tunnel-establishment mechanism (NI_ROUTE) is not itself a vulnerability - it is SAProuter’s documented function - the entire attack surface is saprouttab policy.

A companion technique probes for the SAProuter’s route-classification behavior without completing a full tunnel: sending one NI_ROUTE packet per candidate port and reading the NI_RTERR denial text distinguishes ACL-denied (“PERM DENIED”) from network-unreachable/filtered/closed/unknown-host - an information-disclosure side channel that maps the SAProuter’s internal routing policy (and reachable internal hosts) even against routes that ultimately get denied.

A separate, unauthenticated ROUTER_ADM admin-info request (also on port 3299, no credentials) can additionally dump the SAProuter’s live connection table (every currently-routed source/destination/service) plus the on-disk path to saprouttab itself, when the SAProuter has not been hardened to refuse admin requests from untrusted sources - a natural recon step before attempting route abuse.

Where hop-count limits are not configured, a second attacker-controlled SAProuter can be chained through a target’s permissive saprouttab - the “Trusted Router Hack” - daisy-chaining from an external laptop through the production SAProuter deep into the internal network, completely bypassing the firewall’s segmentation intent.

Note

This is a configuration weakness, not a patchable vulnerability. NI_ROUTE tunneling is SAProuter’s designed behavior; the fix is exclusively saprouttab hardening.

SAP has adjusted the default bezhaviour in some of the recent versions but due to configuration migration the defaults getr overwritten and ignored which causes the misconfigurations to be persitent.

Risk

Any attacker who can reach the SAProuter’s listening port (3299 by default) and whose desired route matches a permit rule - even partially, enough to distinguish ACL-denied from closed/filtered - gains a transparent TCP tunnel into the internal SAP network segment the SAProuter exists to protect, or at minimum a reachability/policy map of that segment.

Because the tunnel is a plain TCP pipe, any subsequent protocol attack (RFC Gateway sapxpg OS command execution, message-server trust injection, unauthenticated DIAG logon) can be run through it exactly as if the attacker were already inside the network - the SAProuter misconfiguration alone eliminates the network segmentation the rest of the security architecture assumes is in place.

Options

  • Tunnel establishment - SAPMAP modules/protocols/sap_saprouter.py: parse_route_string() parses a /H/host/S/port/W/password route string into hops; build_ni_route_packet() serializes the binary NI_ROUTE request; connect_through_saprouter() connects, sends it, and returns a connected socket transparently proxying to the final hop once NI_PONG is received. build_route_for_port() builds one-off routes per target port.
  • ACL-aware port probe (no full tunnel) - probe_port_via_saprouter() in the same module: sends one NI_ROUTE packet per port and classifies the NI_RTERR text (refused→closed, denied→ACL-denied, timed out/not reached→filtered, unknown/gethostbyname→unknown host) - cheaper than a full handshake and reveals the SAProuter’s own routing policy as a side effect, including for hosts otherwise unreachable to the attacker.
  • Recon prerequisite - unauthenticated ROUTER_ADM admin-info request against port 3299 (SAPMAP modules/protocols/sap_router_info.py) dumps the live connection table (every routed source/dest/service, 137-byte fixed-width entries) plus total client count and the on-disk saprouttab path, when the SAProuter answers admin requests from external sources - equivalent to the official saprouter -l -H <target_ip> flag issued from an untrusted position.
  • Manual equivalent: the official saprouter binary (saprouter -R) or SAP GUI’s SAProuter-string field for tunneling; saprouter -l -H <target_ip> for the admin-info probe.
  • Manual/Metasploit equivalent: auxiliary/scanner/sap/sap_router_portscanner (tunneled port scanning) and auxiliary/scanner/sap/sap_router_info_request (admin-info disclosure).
  • Trusted Router Hack - run a second, attacker-controlled SAProuter (a small, no-special-privilege-required executable) and chain through the target’s permissive saprouttab when hop limits (P<v,n> syntax) are not configured, pivoting arbitrarily deep into the internal network - documented as reproducible from an ordinary attacker laptop.
  • Once a tunnel is established, any other protocol module runs over it unmodified - chain into RFC Gateway 10KBLAZE / SAPXPG or Message Server Trust Injection against systems behind the SAProuter that were never otherwise externally reachable.
  • Precondition: network reachability to the SAProuter’s port (3299 default); the requested route must match a P/S saprouttab entry before any D entry (route password /W/ required only if the matching entry mandates one); no SAP application-layer credential is needed for the tunnel/probe itself.

Mitigation

  • Harden saprouttab: explicit, narrowly-scoped P/S entries per source/destination/port, always terminated by an explicit D * * * deny-all as the last-evaluated rule - remember first-match-wins means a preceding catch-all silently defeats it.
  • Never leave P * * * (or an equivalent broad wildcard) anywhere in saprouttab, in any environment, production or otherwise.
  • Limit route hop counts (P<v,n> secure-with-hop-limit syntax) to prevent multi-SAProuter daisy-chaining (“Trusted Router Hack”) into deeper network segments.
  • Require route passwords (/W/) on all permitted entries; use SNC (KT/KP entries) for SAProuter-to-SAProuter links.
  • Ensure saprouttab denies ROUTER_ADM admin/info requests from untrusted sources so the companion recon primitive is closed as well.
  • Restrict which external source IPs can reach the SAProuter’s listening port at the network layer, in addition to saprouttab controls - the SAProuter should be the sole DMZ-facing component.
  • Keep the SAProuter binary current; enable logging (saprouter -G <logfile>) and review it regularly.

Detection and Monitoring

  • SAProuter’s own log (dev_rout / saprouter -G output) records every NI_ROUTE request, ROUTER_ADM admin request, and its accept/deny outcome (CONNECT FROM/TO, PERM DENIED, READ ROUTTAB) - a high volume of distinct destination host/port combinations from a single source in a short window is a strong internal-scan signature matching the probe function’s one-packet-per-port pattern.
  • Network/SIEM: many short-lived TCP sessions to the SAProuter’s port with small NI_ROUTE/ROUTER_ADM payloads and immediate close, from a source not otherwise seen making application-layer SAP traffic.
  • Compare observed accepted-route destinations against the documented/expected internal topology to catch drift from intended saprouttab policy.

References