If you do SAP pentesting, you probably know pysap. It's the only open-source library that lets you talk to SAP systems at the protocol level - Diag, Message Server, Router, HANA, RFC, the whole stack. The problem? It only worked on Python 2.7, which has been dead since 2020. We fixed that.
We ported the entire library to Python 3, tested it against a live SAP S/4HANA 2025 system, and submitted the changes back to the OWASP repository (PR #84). Here's what we did and how you can use pysap in your SAP security work.
9
4
33
67
3
Why pysap matters
Most SAP security tools work at the application layer - they call RFC functions, hit HTTP endpoints, or parse ABAP code. pysap works one level below that. It implements the actual wire protocols that SAP GUI, sapRouter, and the message server use. You can craft raw Diag packets, forge message server registrations, or parse HANA auth handshakes byte by byte.
This matters because a lot of SAP attack surface sits at the protocol layer. Default credentials, exposed message servers, misconfigured router ACLs, weak HANA authentication - you can't test any of this with a web scanner. You need something that speaks SAP.
What's in the box
| Protocol | Module | What you can do with it |
|---|---|---|
| SAP Diag | SAPDiag | Automate SAP GUI login, grab login screens, brute force credentials |
| Message Server | SAPMS | Dump system config, read kernel params, enumerate app servers |
| SAP Router | SAPRouter | Fingerprint routers, scan through them, test ACLs |
| Gateway / RFC | SAPRFC | Monitor gateway connections, send RFC packets |
| HANA | SAPHDB | Test HANA auth (SCRAM, JWT, SAML, Kerberos), find tenants |
| Enqueue | SAPEnqueue | Monitor lock server, test for DoS conditions |
| IGS | SAPIGS | Test image conversion service exploits |
| SSFS / Credv2 / PSE | SAPSSFS etc. | Decrypt credential files, certificates, secure storage offline |
What the migration actually involved
Running 2to3 on pysap gets you about 10% of the way there. The real work is in the binary protocol handling. In Python 2, str and bytes were the same thing. In Python 3, they're not, and every packet field, every socket read, every comparison breaks if you get it wrong.
C extension rewrite
SAP's LZH/LZC compression is implemented as a C++ extension. The Python 2 module init (Py_InitModule3) doesn't exist in Python 3. We rewrote it with PyModuleDef, changed the format codes from "s#" to "y#", and added PY_SSIZE_T_CLEAN. That last one was fun to debug - without it, Py_BuildValue("y#", buf, len) reads 8 bytes off the stack on 64-bit Windows instead of 4, because Py_ssize_t != int. Looked like a MemoryError but was actually stack corruption.
str vs bytes across 14 modules
Every StrFixedLenField default, every protocol constant, every socket comparison. String literals like "\x1f\x9d" that worked fine in Python 2 need a b prefix in Python 3. Constants like SAPROUTER_PONG = "NI_PONG" need to be bytes because Scapy field values come back as bytes now. We also hit issues with Scapy 2.7 being stricter about duplicate field names in ConditionalField patterns - had to rename or restructure fields in SAPMS, SAPRFC, SAPRouter, and SAPCAR.
Crypto that actually works
SAP stores credentials in files encrypted with custom schemes (RSEC cipher, PKCS12 PBKDF1, SCRAM-SHA256). These had Python 2 patterns everywhere - chr() on integers, ord() on bytes, value.encode("hex"), integer division with / instead of //. One subtle bug: the original code had digest.update("" * 0x20) which in Python 2 is an empty string (because "" * 32 == ""). We initially "fixed" it to b"\x00" * 0x20 (32 null bytes), which broke all credential decryption. The correct fix is b"".
CI/CD on three platforms
The old pipeline ran Python 2.7 on Ubuntu 18.04. We replaced it with a matrix of Python 3.9 through 3.12 on Ubuntu, macOS, and Windows. 14 jobs, all green. The Windows build was the last to pass because of the Py_ssize_t issue mentioned above.
SAP pentest: where pysap fits in
When we do SAP security assessments, the first thing we want to know is what's exposed on the network. SAP systems typically have 10-20 open ports per instance. Here's how we use pysap at each stage.
Reconnaissance: Message Server (port 39xx)
If the internal message server port is reachable, you get everything. System name, kernel version, all connected application servers with their IPs and ports, active clients, HTTP/RFC/SMTP endpoints. One command gives you the full landscape.
We tested this against a live S/4HANA 2025 system. Got the full system dump including kernel version (916.9160.75), all registered protocols (Diag:3200, RFC:3300, HTTP:50000, HTTPS:44300, SMTP:25000), gateway ACL settings, and patch level info.
Authentication testing: Diag protocol (port 32xx)
pysap simulates what SAP GUI does - connects to the dispatcher, gets the login screen, sends credentials, and checks the response. You can automate credential testing across multiple clients without installing SAP GUI anywhere.
The brute force script handles client discovery, detects expired passwords, duplicate logins, and distinguishes between "valid user, wrong password" vs "user doesn't exist". We verified it finds SAP* with correct credentials on client 000.
Network pivoting: SAP Router (port 3299)
SAP Router sits between the internet and internal SAP systems. If the ACL is misconfigured (and it often is), you can route through it to reach internal hosts. pysap can fingerprint the router, test routes, and set up port forwarding.
Database layer: HANA (port 3xx13/3xx15)
pysap implements the HANA SQL Command Network Protocol with support for SCRAM-SHA256, SCRAM-PBKDF2-SHA256, JWT, SAML, and Kerberos auth. You can test HANA authentication and enumerate tenants without the HANA client.
Post-exploitation: credential files
SAP stores database passwords, RFC credentials, and SSO certificates in encrypted files on the filesystem (SSFS, Credv2, PSE). If you get read access to /usr/sap/<SID>/SYS/global/security/, pysap can decrypt them. The encryption keys are either embedded in the binary or stored in a key file next to the data.
Supports 3DES, AES256, and LPS-encrypted credentials. Also handles encrypted PSE files (PKCS12/PBES1) and SAP CAR archives.
Typical assessment workflow
1. Port scan - find SAP services (32xx, 33xx, 36xx, 39xx, 3xx13)
2. Message server recon - ms_dump_info.py + ms_dump_param.py to map the landscape and check config
3. Default credentials - diag_login_brute_force.py with default_sap_credentials file across all clients
4. Router testing - if 3299 is open, check ACLs and try internal routing
5. HANA auth - test database-level authentication on tenant and system databases
6. File-level - if you have filesystem access, decrypt SSFS/Credv2/PSE for stored passwords
Get started
Needs Python 3.9+ and a C compiler (gcc/clang/MSVC) for the compression extension. Works on Linux, macOS, and Windows.
Links
redrays-io/pysap - Python 3 fork, 14/14 CI jobs green
OWASP/pysap PR #84 - migration PR, under review
OWASP/pysap - original repo
redrays.io - SAP security tools and research




