Daniel Berlin on Security IT Audit, SAP security, development… and all the rest

13Mar 19

Customer name ranges for SAP objects

Dear readers,
a long time passed since my last post and even more things changed in my life.
My "blue team" perspective has changed to the viewpoint of an internal auditor - and upcoming posts will probably reflect this… life remains exciting. 😎

In the following, we'll take a look at customer name ranges in SAP and how to use them to move things like malicious code out of the sight of security people and… well… auditors.

First of all:
Customer-created objects in SAP do not always start with Y* and Z*.
There are many more possibilities.

Let's start with some obvious things: Workbench objects in SAP (custom reports, tables, transaction codes, function modules, and many more) may not be named arbitrarily. They are bound to name ranges, which SAP designated for customer developments.
SAP Note 16466 - "Customer name range for SAP objects" gives a list of allowed name ranges per object type (yes: different types have different allowed name ranges).

In this post, we'll focus on some of the types, which are interesting for an attacker and allow data manipulation or implementing backdoors, etc.: ABAP reports (obvious!), tables (just because), and transaction codes (e.g. to bypass S_PROGRAM checks).
Let's see what the above-mentioned SAP note 16466 says about the allowed customer name ranges for these objects:

Excerpt from SAP note 16466
[excerpt from the SAP note]

SAP adds in a strict but benevolent tone:
"It is essential that you always adhere to the SAP naming conventions. Serious problems may otherwise result during the next upgrade (the upgrade overwrites customer objects)."
We'll come back to that later.

It's time to dive deeper: when you try to create - for example - a new report in the ABAP workbench, a function module is called in the background that checks the specified name for its compliance with the allowed name ranges.
The relevant FM is TRINT_GET_NAMESPACE and it differentiates between 3 types of object names:

  • Customer,
  • Partner, and
  • SAP-reserved

For objects in the partner and SAP-reserved name ranges, you need an object key to create them - we won't discuss them here.
The actually allowed names can be found in the FM's source code (which is pasta code long and has grown for many years).
I'll quickly summarize it for our 3 examples (reports, tables, and transaction codes) here:

→ Reports

Name starts with...Name rangeRemarks by SAP
CustomerOld customer namespace
MP9CustomerInfotype-dialog module



CustomerModifiable MC programs
Customer MCOBs
Customer MCOBs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
Customer MCIDs
CustomerModifiable help view program
PartnerOld partner namespace
PartnerOld partner namespace
( all others )SAP-reserved
→ Tables
Name starts with...Name rangeRemarks by SAPMy remarks
CustomerOld customer namespace


(with exceptions)
Table names in this range are checked against the exception
table TDKZ. If no entry is found, the name belongs to the
customer name range.
Table TDKZ usually contains the entries listed in the second
last line of this table.
PartnerOld partner namespace;
TJ-tables only for 2.2-compatibility
SAP-reservedThese table names are SAP-reserved as per the exception table TDKZ.
( all others )SAP-reserved
→ Transaction codes
Name starts with...Name rangeRemarks by SAP
CustomerOld customer namespace
JPartnerOld partner namespace
( all others )SAP-reserved

So, we have a whopping 47 name ranges to choose from for our next malicious report! … and hardly any auditor will ever identify a program called MSTHRP9INT as a customer-developed one.
To be even more sure, you could also fake the report's "creator" easily (more on this in my next post).

Now back to SAP's stern statement on what happens, when you're not nice and use name ranges not listed in Note 16466:
First, I doubt it - but didn't check it myself. Since the FM TRINT_GET_NAMESPACE is used by every workbench-related functionality in the ABAP-stack, I would assume that all ABAP code, which is called during an update also uses the same logic. The command-line tools (tp, R3trans …) are usually synced with their ABAP pendants, so they'll probably perform very similar checks as well.
And secondly, it doesn't matter. Most attackers would probably do, what they intended to do, once they have compromised an SAP system in such a way. There's no need to wait a long time and then come back… and persistence inside a victim's network can be achieved in more reliable ways and with fewer traces to cover.

Happy hunting and see you! 😀

PS: Just to prevent confusion - this post is about "name ranges", not "namespaces" like /SNAKEOIL.

25Apr 16

Protection of the Security Audit Log against deletion

Hi SAP security enthusiasts,How to prevent erasure of log data
the Security Audit Log [SAL] contains -obviously- information about important system events and should, therefore, better not get lost unintentionally!
Let's see, how the Audit Log can be erased and what we can do to prevent this and maximize its protection.

The Audit Log is stored in log-files that are located in the file system (see parameter DIR_AUDIT) and is either rotated daily or when the current file is full (see parameter rsau/max_diskspace/per_file).

Access to these files is possible via kernel functionality (from within the SAP system) or on operating system level (e.g. via an external OS command). We’ll focus on access via the SAP application server and won’t take a deeper look at manipulations directly from OS level (i.e. from the command line).

Ways to delete the Security Audit Log

From inside the SAP system, three variants of deleting the SAL files exist.
Below we'll check them and see, which measures exist to protect the logs.

Variant 1: SM18 (or function module RSAU_CLEAR_AUDIT_LOG or system function C_REMOVE)

SM18 is the SAP standard way of removing old SAL files.
The transaction is protected by an authorization check for S_ADMI_FCD with value AUDA (AUDit log Administration). The minimum age of files to be erased is 3 days − a nice feature because an attacker cannot remove fresh logs and hide what he/she did moments ago.

SM18 is not really problematic… S_ADMI_FCD with value AUDA is a critical authorization, which nobody should be assigned to on production.

Diving a bit deeper…
A clever developer might try to copy the code that is responsible for the deletion to a customer report − fortunately, this does not work... see below:

DATA: errno  TYPE rsautypes-errno
    , errmsg TYPE rsautypes-errmsg.
CALL 'C_REMOVE' ID 'DIR'    FIELD '/usr/sap/<SID>/DVEBMGS00/log'
                ID 'FILE'   FIELD 'audit_20160425'
                ID 'GROUP'  FIELD 'AUDIT'
                ID 'ERRNO'  FIELD errno
                ID 'ERRMSG' FIELD errmsg.
IF sy-subrc = 0. WRITE: 'successful'.
ELSE.            WRITE: 'failed;', errmsg. " caller not registered

⇒ This report always runs into an error, because the SAP kernel checks the program name that calls the C_REMOVE function against an internal whitelist; we'll always get a "failed; caller not registered" message…


A more sophisticated way of getting rid of audit log files is to simply delete them via the DELETE DATASET statement from within an ABAP report.

A simple example:

    DELETE DATASET '/usr/sap/<SID>/DVEBMGS00/log/audit_20160425'.
    IF sy-subrc = 0. WRITE 'successful'.
    ELSE.            WRITE 'failed / not found'.
  CATCH cx_sy_file_authority.
    WRITE 'missing authorization'.

Basic protection
The kernel checks for S_DATASET authorizations each time a DELETE DATASET statement is executed (this cannot be prevented since the check takes place in the kernel).
The field ACTVT is checked for value 06 (delete) and the FILENAME field for the path of the file to be deleted.

Better protection
A check for authorization object S_PATH can be activated to implement additional protection for file system accesses. It is then evaluated after a successful S_DATASET check.

Alternatively, we can also prevent unauthorized log file deletion completely… even if a user has S_DATASET with all field values set to "*"!

For the additional check, the logic is as follows (see SAP Note 177702):

  • first, the system checks whether the SPTH table contains a PATH, which matches the start of the pathname of the log file that we want to delete
  • if an authorization group is set in the FS_BRGRU field, the system then performs an authorization check on S_PATH with ACTVT = 02 (write or delete)

Additionally, the table SPTH has two flags, which can further limit file access and overwrite the authorization checks on S_PATH and S_DATASET:

  • if FS_NOREAD has the value "X", neither read nor write access is possible
  • and FS_NOWRITE = "X" prevents write access

SPTH Log File Protection

To effectively prevent Security Audit Log deletion, you can add the following entry to SPTH:

PATH = /usr/sap/<SID>/DVEBMGS00/log/audit_

Afterwards, no user will be able to read or modify the SAL log files – disregarding their authorizations!
Anyway, SM20 will continue to work, as the access takes place in the kernel.

Variant 3: External operating system command

The third variant does not use the SAP kernel to delete the file, but rather an OS command (in the following example we’ll use the Unix/Linux rm command).

The following report creates a new external command, executes it to delete the same audit log file as above and finally deletes the command.

The creation and deletion of the command is logged via table logging for table SXPGCOSTAB… but at least at a first glance, we can hide what we did by deleting the command after execution…

WRITE 'External command (SM69):'.
DATA command TYPE sxpgcolist.
command-NAME      = 'Z_DEL_AUDITLOG'.
command-opsystem  = sy-opsys.
command-opcommand = 'rm'.
command-addpar    = 'X'.
CALL FUNCTION 'SXPG_COMMAND_INSERT'         " --- Create command
    command = command
    OTHERS  = 1.
IF sy-subrc = 0. WRITE 'creation successful;'.
ELSE.            WRITE 'creation failed.'.
                 LEAVE PROGRAM.
DATA exitcode TYPE extcmdexex-exitcode.
CALL FUNCTION 'SXPG_COMMAND_EXECUTE'        " --- Execute command
    commandname           = command-NAME
    additional_parameters = '/usr/sap/&lt;SID&gt;/DVEBMGS00/log/audit_20160425'
    exitcode              = exitcode
    OTHERS                = 1.
IF sy-subrc = 0 AND exitcode = 0. WRITE 'execution successful;'.
ELSE.                             WRITE 'execution failed;'.
DATA: BEGIN OF command_del.
        INCLUDE STRUCTURE sxpgcostab.
DATA:   sapcommand   TYPE sxpgcolist-sapcommand
    ,   TYPE(8)      TYPE c
    , END   OF command_del
    , rc             TYPE i.
command_del-NAME     = command-NAME.
command_del-opsystem = command-opsystem.
PERFORM command_delete(saplsxpt)            " --- Delete command
        USING    SPACE
        CHANGING command_del rc.
IF sy-subrc = 0 AND rc = 0. WRITE 'deletion successful.'.
ELSE.                       WRITE 'deletion failed.'.

Of course, you could also create, execute and delete the command via transaction SM69.

The above method works fine if you have S_RZL_ADM (ACTVT = 01) for the creation of the command and S_LOG_COM authorizations for execution.
Unfortunately, the SPTH-protection from variant 2 does not work here.

If table logging is enabled (profile parameter rec/client), changes are recorded in table DBTABLOG and can be evaluated via transaction SCU3 (for table SXPGCOSTAB).

Bottom line

All three variants can be protected quite well via authorizations, so log deletion can be prevented by strictly controlling these authorizations.

Anyway high-privileged users – e.g. emergency users – still have access, so I suggest also implementing the SPTH-protection described in variant 2. 💡 It provides a good additional line of defense around the log files.

Please keep in mind that you should also take care of protecting table SPTH itself… 💡

Apart from the "access"-perspective, organizational measures should be implemented to make sure that malicious code - like to one above is - checked (and rejected) before a transport to production takes place!

So long!

4Oct 15

A note on SECPOL behavior

Howdy!SECPOL pitfall
Currently, a lack of time prevents me from finishing a post, which is in the pipeline for weeks now. Nevertheless, I'd like to point out a behavior of Security Policies, which might lead to an unexpected situation, if you're not aware of it (fortunately you will be).


Let us assume that you have hardened your system and set the password-related profile parameters login/min_password_lowercase = 1 and login/min_password_uppercase = 1. This forces users to include at least one lower- and one uppercase character in new passwords. The kernel default for both parameters is 0.
Additionally, you set the parameter login/min_password_lng = 10 to enforce a minimum password length of 10 characters.

Unfortunately, there is an RFC user on your system, which must – for whatever technical reason – not have a password longer than 8 characters. As you don't want to lower the system setting, you choose to create a new SECPOL with just the attribute MIN_PASSWORD_LENGTH = 8 and leave the profile parameter as it is (= 10). The desired result is obviously to override the minimum password length with a lower value for just the one RFC user and stay with the more secure value for all other users.

(Possible) expectation

The SAP Help Portal says:
you create security policies with attributes, for which you explicitly do not want to use the default value.

So my initial expectation was, that a SECPOL attribute overrides the corresponding profile parameter (in our example MIN_PASSWORD_LENGTH overrides login/min_password_lng)… and all other profile parameters, for which SECPOL attributes exist, stay as they are set in the profile.
So login/min_password_lowercase could potentially be overridden by MIN_PASSWORD_LOWERCASE – but since we did not add it to our SECPOL, one could assume that the profile value stays intact.


Security Policies do not override profile parameters - rather they replace them! All of them.
All profile parameters, for which a SECPOL attribute exists, are replaced – so if an attribute is not explicitly set in a SECPOL, the kernel default value is used! Not the profile parameter value.

SECPOL vs. Profile Parameters

The bottom line

If you've set any of the profile parameter values, which can be influenced by a Security Policy, you have to make sure that all those profile parameters are explicitly set again in all of your SECPOLs!
So once you choose to make use of SECPOLs, you have to maintain all values at least twice: in RZ10 and in your Security Policy/ies… otherwise, you end up using default values by mistake.

Yep... unspectacular... but still interesting 🙂


14Nov 14

Weak parameter transactions in SAP

Hi there.Weak parameter transactions
In this article, we'll take a look at a potential weakness that is often considered minor and thus underrated – but might still be used to lever out important security measures: parameter transactions.
They basically execute another tcode… along with pre-defined screen input – the "parameters".

For example, the transaction code SM30_PRGN_CUST is a shortcut to SM30 for the maintenance view PRGN_CUST:
When you call it, SM30 is executed and table PRGN_CUST is opened in maintenance mode. Since the option "Skip initial screen" is enabled, it jumps directly into the table maintenance view itself – if it was disabled, one would be able to override the given screen options in the SM30 dynpro… including the table name! That's the point where the weakness starts.

Now let's select some more parameter transactions from table TSTCP.
They start with either "/*" or "/N" — the first one skips the called tcode's initial screen, the latter one doesn't.
Below you can find the selection options for all SE38 parameter transactions:

Selection for table TSTCP

Now let's have a look at the lines marked red and green in our result:

Table TSTCP: Result

The first one – SE38L – is unsafe, because the "/N" indicates that the SE38 selection screen is just filled out – but the report name can be overridden easily.

This means that SE38L is equivalent to SE38

Well… for SE38L, -M, -N this might not be a big surprise, but what about RBDCPCLR? … I never would have guessed!

Transaction SE38L

The second sample – SE38N – calls SE38 and executes report RDELALOG immediately: nothing to see here, move along.

Lessons learned

  • When you limit access to a transaction, always keep in mind that insecure parameter transactions might represent a backdoor.
  • Customer parameter transactions should always use the "Skip initial screen" option.

See you soon!

16Sep 14

Authorization trace with comfort function: STAUTHTRACE

Hey everybody.
Recently I wrote an article for a magazine published by the German-language SAP users group (DSAG).
In this post, I’d like to share an English translation with you (the original German version is available here: http://blaupause.dsag.de/berechtigungstrace-mit-komfort-funktion).

Have fun:

Authorization trace with comfort function:

One of the numerous new features of Enhancement Package 6 is the authorization trace via transaction STAUTHTRACE. In principle, it works like the system trace ST01, but is limited to authorization checks. This makes it a valuable tool for authorization admins and provides comfortable functions.

So far, it was necessary to start an authorization trace on all application servers of a system separately, unless the relevant server was known beforehand. Transaction STAUTHTRACE simplifies this and allows starting a trace on one or more servers in a single step:

Start STAUTHTRACE (system-wide)
Without an explicit selection, the system-wide trace is automatically started on all available servers:

STAUTHTRACE is running on all servers
The evaluation section in the lower half of the screen offers detailed options to analyze the result and is much advanced in comparison to ST01.
In a system-wide trace, the selection of the application server in the topmost section is also taken into account.

STAUTHTRACE evaluation options
The option "Evaluate Extended Passport" is extremely handy, as it enriches the trace result with data from the system's kernel statistics (transaction STAD).
This additional information is helpful when it comes to RFC calls from other systems and consists of the following fields:

  • "Initial Component" — the calling system, instance and client
  • "Action Type" — e.g. a batch job run or a transaction call
  • "Initial Action" — e.g. the name of the job or transaction code

The result is finally displayed in a nice, filterable ALV grid and not in that ugly ST01 list view.

Additionally, it is possible to dive into each line and jump to the affected user, the authorization object and its documentation as well as the line in the source code that triggered the authorization check. Simply double-click in the list or use the menu:
Further options in STAUTHTRACE result

How to use the trace result in PFCG

The result of an authorization trace can be used in PFCG directly now - no matter, whether it comes from STAUTHTRACE or the traditional ST01.

This can be achieved in two ways:

  • Maintenance via the role menu

The "Import from Trace" option in a role's "Menu" tab allows importing the called applications from the trace: Transactions (S_TCODE), External- or Web-Services (S_SERVICE) and RFC Function Modules (S_RFC).

Unfortunately, if you import a transaction call, only the tcode is adopted from the trace - the other values that are checked during transaction start and execution are ignored; instead, the suggested values from SU24 are used.

Import STAUTHTRACE result in role menu

  • Maintenance of authorization values

In the role's authorization data maintenance screen, the new button "Trace" can be used to import the values that were checked from the result into the role.
Trace button in PFCG authorization data screen
In the below example, the role already contains the object S_USER_GRP – but no values yet. The actual check in this case used 02 for the field ACTVT and the user group (CLASS) was "SUPER" – these values can easily be imported from the trace data with some clicks.

Import STAUTHTRACE result in role authorization data

Bottom line
💡 The new trace functionality of EhP 6 is a great feature for the analysis of authorization needs and problems - a neat enhancement of the existing toolbox!