Blaming someone else for a transport request (using RDDIT076)

Greetings to everybody!

In this post, we’ll examine a way to doctor transport requests, which can be used with malicious intent, but potentially also as a “quick fix” by admins. The goal is to identify the involved tools and related authorizations to secure your SAP systems against such manipulations… as far as possible!

Report RDDIT076

Let’s start with the offender itself:
Report RDDIT076 allows you to select an existing transport request (or transport task) and edit many of its attributes.

As an example, we assume an unreleased workbench request (type “K”). That request contains a single task, which in turn consists of a repair… e.g. a changed report.

To make it interesting, we assume that the modified report copies the profile SAP_ALL to our user’s authorization buffer once we start it (that gives us all authorizations without any traces). As the assumed code checks for SY-UNAME, it only works for one user (in the example that’s me: DBERLIN). There’s only a very shallow code-check during transport… so the chance of being caught is small! 🥳

But wait… we absolutely don’t want to be caught. Really not! So just in case our malicious code change is detected, let’s blame someone else!

Let’s see what RDDIT076 can do for us:

First, select the request.
You then get an overview of the request with its task.

Okay – the title of the transport request is a bit too honest and we could easily have chosen a better one. The problem is: my user DBERLIN is the owner of both the request and the task and will be blamed for its contents. Fortunately, we can simply edit both entries:

We can change all fields, except for the request/task ID and the “Last changed” timestamp.

We adjust the description and set a new owner: our estimated colleague Frank Grimes (FGRIMES).
Save and repeat for the task!

The doctored request and task look harmless and we’re not the owner anymore! 🎉

The scenarios

In our example we assumed a malicious, internal developer… but that’s not the only situation, in which the report might be (mis-)used. We have to differentiate between three scenarios:

  • justified usage (e.g. by a developer, who needs to cope with a particular situation)
  • sloppy usage (e.g. an admin, who favors “shortcuts” instead of the longer standard process)
  • malicious usage (e.g. to hide the origin of manipulative code in a transport request)

The first case is generally acceptable, but it must be ensured that the possibility to use RDDIT076 is not misused. That will turn out to be challenging and I doubt that such cases exist.

The second “sloppy” case is not easy to prove for an auditor, because there’s always a “good” reason, why a change had to be fast and the usual process would’ve been too slow… so people might try to sell the second case for the first one.

Lastly, the third case is what our example is based on – an intentional attempt to maliciously exploit the SAP system. That’s the most obvious case, but when cleaning up your system, always keep in mind that the other two cases exist as well (and are probably more likely 🤔).

How to prevent it


RDDIT076 is a report without an assigned authorization group and there is no associated transaction code – so to block access, you should take care of program execution rights, for example:

  • SA38: only S_PROGRAM is checked with P_ACTION = SUBMIT
  • SE38: first, S_DEVELOP with ACTVT = 03 and 16, OBJNAME = RDDIT076 and OBJTYPE = PROG is checked, then additionally S_PROGRAM (see above)
  • START_REPORT: only S_TCODE with START_REPORT is checked… nothing else 🙄

Program execution rights should generally only be granted to few, carefully chosen users – especially because there is no way to do it in a granular way (i.e. without a program authorization group).


There are some, but not many authorizations necessary to run RDDIT076:

  • S_TRANSPRT with ACTVT = 03 to select the transport request and read its contents
  • S_CTS_ADMI with CTS_ADMFCT = TABL as a “general” protection
  • and S_DATASET with ACTVT = 34 (write), PROGRAM = SAPLSTRF and FILENAME = <DIR_TRANS>/actlog/<LOGFILE>

The first two authorizations are administrative rights that can be used to limit the usage of the report and which should only be granted to few users! The third authorization is checked, when a log file is written – so in case this right is not granted, no log would be written… which is counterproductive!

The hard truth

In the end, you’ll probably end up with a few users that have the necessary rights to use the report and can thus manipulate transport requests. The reason is that only a few generic authorizations are checked in RDDIT076 and all those rights are needed in other places as well… at least by SAP basis (on DEV and maybe also PROD) and developers (on DEV).

From an audit perspective, a residual risk remains after the first cleanup. You could further reduce it by additional measures… for example, you could assign the report to an authorization group (so that the S_PROGRAM check is more specific) and make sure that other ways to execute it, e.g. START_REPORT, are removed from all roles. That’s feasible, but difficult for a rather small gain in security… and most people will probably not want to change the attributes of an SAP standard report.

Another option would be an ex-post control – but then we’d need a good log of the actions performed in RDDIT076. In the next chapter “How to detect it” we’ll see that logging exists, but is far from being detailed enough. Other ways to trace such administrative activities, such as SAP UI Logging, are usually complex and expensive.

So, the hard truth is that RDDIT076 is a candidate for risk acceptance…

How to detect it

As stated above, changes performed in RDDIT076 lead to log files being written to <DIR_TRANS>/actlog/<LOGFILE>, if the S_DATASET authorizations allow it. One log file is used per transport request/task number.

Such a file, unfortunately, contains only minimal information… the example from the beginning of this article leads to two log files. One for the transport request and one for the contained task. Both files contain one line similar to the following:

1 ETR018 "05.04.2020 16:15:30" request/task "NSPK900042" was changed by user "DBERLIN"

No information about what was changed…
That’s not enough data for a sensible ex-post control!

The bottom line

I’d suggest removing the involved authorizations from all users that don’t need it – the remaining users should be administrative ones only.

Admins should have separate users (and rights) for “employee tasks”, e.g. time management, day-to-day administration and extended admin-tasks. At least the latter user should be logged extensively. Logs should be monitored for the usage of RDDIT076 and – in case of matches – the logfiles should be inspected.

That’s not bulletproof, but the best approach possible without disproportionate effort… at least IMHO…

Bye and see you soon!

+++ End of article +++
+++ Begin of article +++

How to fix critical SAP rights found in an audit


This article is intended for all the auditees out there, who struggle with SAP authorizations. I’ll try to provide you with a best-practice approach to tackle audit findings related to extensive/critical rights in SAP.

The situation

There is probably not a single SAP-related audit report out there that does not include a finding about extensive SAP authorizations…

Let’s be honest: SAP offers fantastic possibilities and tools to tailor user authorizations and restrict them to a proper minimum – but due to the range of possibilities it is extremely hard and time consuming to get close to roles that follow the need-to-know principle.

In an audit, it is thus likely that there will be at least one or two findings dealing with extensive authorizations… that’s probably the reason you read until here. 😉

The problem

Well… the problem is often that it is unclear how critical rights can be effectively reduced (without long deadlines or additional staff).

Audit findings that deal with SAP authorizations consist of a finding text that describes the “problem” (comprising a risk) and are usually accompanied by an evaluation of the critical rights and segregation of duties conflicts that led to the finding(s). Taking care of such findings can lead to time-consuming activities, as you need to take care of the listed rights (or users assigned to these rights) and additionally make sure that you don’t just slightly tidy up the system, but also solve the core problem of the finding.

A best-practice procedure can help you tackle the cleanup and distribute the individual tasks to the responsible people.

Some basics upfront

A critical right is a single authorization, which can be used to perform extensive actions in the system, such as broad read access or uncontrolled data modifications.

  • Debug with replace.
  • Modification of program code in production.
  • Display (or change) authorization for all tables in production.

A segregation of duties (“SoD”) conflict is a combination of at least two authorizations, which can be used by a single person to execute a whole process and which must usually be distributed among several persons.

  • Maintenance of vendor master data & maintenance of purchase orders.
  • Creation & approval of expense reports.

Risk management: there are several ways to deal with a risk: you can…

  • Ignore it – the worst choice (if a real choice at all)! The risk might lead to unforeseen damages and the extent is unclear. This usually results in the worst possible audit assessment… quite rightly.
  • Accept it – if the risk is either very unlikely and/or has a minor impact, you can choose to accept it. Maybe it’s a strategic risk, which is directly linked to your business model; then you may not be able to manage it without a negative impact on your ability to make profit (which you might consider unacceptable). The most important point when accepting a risk is: think about it and do it intentionally! The person, who decides on this must be in charge of the affected process and in a position to take the decision.
  • Avoid it – if a risk has a potentially large impact on your business (and is maybe even likely), an adequate way of risk management may be to completely avoid the risk.
  • Transfer it – essentially, you transfer the impact and management of the risk to someone else. You’ll have to pay for this in one way or another. Outsourcing is a common example.
  • Mitigate it – means that you reduce the potential impact or likelihood (or both) so that if the event occurs, it is easier to overcome – this means that a residual risk remains. It’s a common technique, as taking risks is inherent to running a business and mitigation provides a good balance between not managing a risk (at little cost) and avoiding or transferring it (at high cost).

A compensating control strives to control a residual risk, e.g. by a regular ex-post check. Personnel restrictions, for example, could prevent an effective segregation of duties between the creation and approval of expense reports. A daily review of the creations and approvals by a responsible manager would enable the detection of fraud cases and is, therefore, a compensatory control.

The proposed procedure

Before you start, you should ensure a common understanding and expectation concerning the remediation; thus:

  • Review all critical rights with the auditor to understand their impact/criticality.
  • Discuss with audit, which critical rights must be remediated and which may be accepted.

The flowchart below strives to provide you with a structured approach to tackle authorization-related findings.

The basic idea is that you loop through the procedure role by role (or right by right) and continue until every authorization in scope has been checked and either found to be good or cleaned up.

( click here for a PDF version )

Most steps in the flowchart are rather obvious and I will not explain them in detail… the green decisions boxes, on the other hand, are very important and need some explanation:

Assignment of roles to users justified by positions of the employee?

Each user ID should relate to exactly one natural person, which in turn holds a position. To fulfill the tasks associated with that position, specific authorizations are required. The roles assigned to a user should not include more authorizations than needed to fulfill their position.
In case users do not belong to one person but are rather (at least potentially) used by several people, please get in touch with the auditor. Depending on the authorization concept and possibly implemented controls this might or might not be valid.

Does the right fit to the purpose of the role(s)?

In case the user is properly assigned to the role(s), which are associated with his/her position and there are still critical rights listed, the role could contain too many authorizations.
You should check if the role purpose and the contained rights match. Can the critical rights be removed without impacting the user’s work? Keep in mind that some tasks occur only occasionally, e.g. when the annual financial statement is prepared.

Are there users with critical rights left?

After performing the two checks above for all critical right/user assignments, most rights should be either remediated or found to be justified.
Anyway, some questionable critical rights might be left, for which no remediation could be found – either due to special (known) situations or because of small team sizes, which do not allow proper segregation of duties. These remaining cases should be considered very carefully because they represent a risk and thus need to be controlled. To do this, we need to differentiate further…

Is it a (single) critical right or an SoD conflict?

The difference between these two has been described in the chapter “Some basics upfront“…

Single critical right – Define control or accept the risk?

For each remaining critical right, either a control must be implemented or the risk must be accepted by a person, who is accountable for the affected process or function and in a position to do so.
If acceptance is not an option and no efficient compensating control can be defined, the critical right must be remediated. If unsure, discuss the situation with your auditor!

SoD conflict – Does a compensating control for the conflict exist?

The situation is roughly the same for SoD conflicts: they must either be mitigated by a compensating control or cleaned up. It is inadequate to have SoD conflicts without any control. In case the conflict cannot be solved, e.g. due to staff shortages or small team sizes, a compensating control could be applied to reduce the risk to an acceptable level.

Your risk management department can usually provide you with best-practice approaches for such controls.

Can the chosen control be implemented?

In case a compensating control exists for the SoD conflict in question, you should decide with the affected persons if it can be implemented. In case the control is considered too complicated or not favorable at all, the SoD conflict must be cleaned up.
As such controls must be executed accurately, resources are required – and in the end, the conflict might be cleaned up, just because the additional effort for the control is considered too high… It is therefore very important to ensure that compensating controls are not defined without clear communication about the involved effort!

Final words

Hopefully, the above procedure helps you iron out SAP authorization findings!

I would be happy to receive your feedback, questions or suggestions – just send an email to .

Bye! 👋

+++ End of article +++
+++ Begin of article +++

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 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 the 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 one of the next posts).

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.

+++ End of article +++