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

3Oct 12

Import user favorites into a role menu

Hi consultants,
did you ever wonder, what's behind the button "Import from file" in PFCG's Menu tab?

Well, it obviously allows you to upload a menu from a file, but expects a special file format: SAP Note 389675 has the details. You won't find this format anywhere in PFCG or elsewhere in your system, so it has to be created by you…

This usually makes the "Import from file" button hard to use and thus unpreferable!

The plan

Let's say, you're trying to revise (and minimize) the authorization in a SAP client ex post, i.e. when the system has been in use for some while and nobody took care of proper roles. Moreover some (key-) users might already have created their own favorites, which – hopefully – reflect their tasks in the system.

Wouldn't it be nice to be able to import those user favorites to a role and build adequate authorizations this way? Still there will be much to analyze and adjust — but it might be a good starting point!

Technical background

A user's favorites are stored in the table SMEN_BUFFC and SMEN_BUFFI (for the various kinds of link targets). So this is the place we'll get the menu data from.

The file format from the above mentioned SAP Note 389675 only supports a subset of all possible favorite types: folders, transaction codes, URLs, Knowledge Warehouse links and custom types (we won't deal with the last-mentioned one).
So in addition to reading and converting the favorites, we'll have to filter out all unsupported types of favorites.

Conversion report

Here's how to create the program that does the work:

  • Create a new report in SE38 and paste this source code (don't forget to set a program authorization group).
  • In the selection texts, tick "dictionary reference" for all parameters.
  • Activate & execute the program.

The selection screen allows you to select:

  • the user from whom to read the favorites and
  • an optional file to save the data to.

Once started, the report prints the converted favorites on screen and optionally saves it to the specified file.

Next steps

You might want to customize the report to download the favorites of several users at once — but be aware that you'll have to either save each user's favorites to its own file or deal with duplicate object IDs (and parent IDs and the sort order …)!

If you're interested in role menus, you might want to check the AGR_HIER* tables.

😀 Have fun!

15Sep 12

Extending S_GUI download authorisation checks

Hi all,
this week, a colleague pointed me to the possibility to hook your own code into SAP GUI downloads via a user-exit. Since downloads are always a big security - and data protection topic, I took a closer look.

Generic download authorization: S_GUI

When downloading data to the frontend, the authorization object S_GUI is checked (with ACTVT 61). This is a very unspecific check, as it does not take the affected data into account – if you have appropriate authorizations, you can download roles, the SFLIGHT table or your colleagues' salary. It's just a client-wide "switch", which either allows or disallows downloads. Many authorization admins don't pay much attention to S_GUI, but rather focus on data access authorization objects. Anyway this is not sufficient, as downloaded data may be passed to third-parties easily or analyzed inappropriately.

User-exits

SAP offers 2 user-exits to extend download authorization checks:

  • SGRPDL00 — User-exit for "normal" SAP GUI downloads
  • HRPC0001 — User-exit for HR-specific downloads; logical databases: PNP (HR master data) and PAP (recruitment data)

The first one is called by the GUI_DOWNLOAD function module – i.e. for each and every frontend download, while the second one is HCM-specific. To get started, I decided to inspect SGRPDL00, as this one has the best coverage.

User-exit SGRPDL00: Creation

First of all, we need to create an add-on project via tcode CMOD to implement the user-exit.
Enter the project name "SGRPDL00", click on "Create", enter the project attributes and then go for "Enhancement assignments". When you're prompted to save, say "Yes" (← hard decision) and choose a package ("Local object" is fine, if you're just playing around).
After that, enter "SGRPDL00" as the enhancement name, click on "Components" and double click on the function exit name:

Since you don't want to modify the SAP standard function module, double click on the include ZXFILU01. SAP tries to baffle you with a warning message:

… nice try, but just press Enter and you'll be prompted, whether you'd like to create the include. After ticking "Yes", you can start to implement the code, which will be called during every frontend download.

User-exit SGRPDL00: Implementation

The function module EXIT_SAPLGRAP_001, in which our code runs, provides 2 input parameters:

  • IS_LIST_DOWNLOAD — whether the user is downloading a list (Standard list or ALV)
  • NO_AUTH_CHECK — whether the GUI_DOWNLOAD function module was asked to not check S_GUI

and allows throwing the exception "NO_AUTHORITY" – which means that the download is forbidden.

Paste this code to get you started, activate it and don't forget to activate the user-exit itself.
The above code is a documented example… you'll for sure want to add your own code there; anyway it demonstrates a bunch of possibilities. One of the most interesting aspects is that it creates an Application Log entry for every download. Although the Security Audit Log provides similar functionality, it's possible to add additional information – the table name for SE16 in the above example code.

Unfortunately, you don't have access to all variables from the calling program… which makes it a bit difficult to add useful information (have a look at how the include gets the table name for SE16). If anybody has a better idea, please tell me.

User-exit HRPC0001

The user-exit HRPC0001 is specific to HR/HCM and works a bit different. The implementation in include ZXP04U02 does not perform any check itself, but is rather expected to return a report and form name. This form is responsible for the check and may be located within the calling report's context – thus enabling your code to access any global variable therein. This way you can take the HCM-specific context into account to determine whether the download is okay or not.

Copy-and-paste

When copying data to the clipboard, S_GUI is not triggered – SAP Note 997201 provides a solution at the cost of a modification.

Final words

  • Uploads are not covered.
  • Non-GUI downloads are not covered (BEx, Portal, …)
  • If you mainly need reliable logging for each and every client, you might want to check the SAP UI Logging solution.
24Jun 12

Decompress ABAP source code from table REPOSRC

Howdy!
If you ever wondered, where SAP stores your report source code, you probably came across table REPOSRC – but the source code is stored in a compressed format, so there's no way to get hold of it directly.
I've been trying to figure out, how this compression works for some time now… fortunately, several people dealt with the SAP DIAG protocol recently – which got me off the ground.

Algorithm

The DIAG protocol uses a form of the Lempel-Ziv (LZ) compression algorithm and a bold attempt confirmed that this is also true for the source code compression.

The code stored in REPOSRC-DATA is actually compressed using the LZH algorithm (Lempel-Ziv plus Huffman coding), which is used by the SAP DB MaxDB database too (thanks to Dennis Yurichev for the idea).

Knowing this, I wrote a decompression tool around a small portion of the MaxDB code, which also takes care of some SAP specialties:

  • The 1st byte of the compressed data seems to be junk (or might have a special meaning !?)
  • The first 2 bytes of the decompressed source are junk, too ?!
  • Lines are terminated with character code 0xFF, which has to be adjusted
  • The 1st, 3rd, 5th … decompressed byte contains NUL (not sure, why !)

The decompressed source code has a fixed line length of 255 characters (blank-padded).

Usage

  1. Download this archive (it contains the decompressor tool compiled for Win32 and an ABAP report to dump the binary source code). The source code is available here; you can easily compile it on Linux/BSD/Unix/Windows using the enclosed build script.
  2. To extract the compressed source code from SAP, use the report "ZS_REPOSRC_DOWNLOAD". It reads the DATA field from table REPOSRC for a given report and stores it in a binary file on your workstation.
  3. Decompress the file on the command line.

PS: Works for Kernel 7.x, no guarantee for older releases.
PS 2: The functionality on non-Unicode systems is unknown… I'll check this later.

Have a nice day!

16Jun 12

Authorization ranges for S_TCODE

G'day!
If you ever wondered about the physics of S_TCODE authorization ranges, this post is for you.
We'll take a look at the order of characters (which is essential for correct ranges) and the pitfalls to avoid.

Basics

To keep things easy and since most of us (?) are probably using a keyboard with Latin-1 characters on it, I'll focus on the ISO-8859-1 character set… though this is not exhaustive, as your system might use UTF-8 or some other charset.

Basically, the character code in the "From" value of a range serves as the start value and is incremented until the "To" code is reached. All characters between the low and high end of the range are covered; so AZ* includes AA, AAA, BBBB … ZZZZZ …

Concerning the order of characters, a range from / to Z is treated basically like this:

#!/usr/bin/env perl
 
$from = ord("/");    # Character code 47
$to   = ord("Z");    # Character code 90
 
for ( $from .. $to ) {
    print $_ . " == " . chr($_) . "\n";
}

Jump to Ideone.com to execute the code online or to Wikipedia for a table of ISO-8859-1 characters.

Btw.: some characters – e.g. backspace – are not printable and thus not usable.

Wildcards

Usually, SAP allows us to use 2 wildcard characters: * (match any number of characters) and + (match a single character), but for authorization values only the asterisk is valid; the plus sign is treated as a normal character (see SAP Note 136647).

At this point, I'd like to stress:

An asterisk at the end of a "From" value is never useful, but might be terribly wrong !

The reason for this is that the start value is the first character in the range and all "higher" character (combinations) have a "higher" value (i.e. A < AA < AAA).

Bad example:
The range SU* … SU21 includes SU24 as well, because the "From" value already covers all SU… transactions.

Transaction codes

To be able to create valid (and sensible) ranges for S_TCODE, we'll next look at the characters allowed in tcodes, because all others are of no interest (at least until we take a look at the tcodes SAP created itself).

In SE93 you'll get this error, when trying to use a disallowed character:

The function module responsible for this safety-belt is "RS_CHARACTER_CHECK" (called in the include LSEUKFWM), which gives us an idea of the set of allowed characters:

CONCATENATE 'ABCDEFGHIJKLNMOPQRSTUVWXYZ_0123456789/'
            allowed_special_characters    " Set to '+' in LSEUKFWM
            INTO allowed_characters.

This should be the full range one has to take into consideration when doing S_TCODE… which is only almost true… because SAP is not bound to the above restriction! When you look into table TSTC you'll find tcodes which contain characters not allowed by the above check. At least on a number of systems, I found quite some.

Here's a summary of the order of ASCII characters and corresponding notes (explanation below the table):

ISO-8859-1CharacterUsable in customer
tcodes ?
Used in any tcode ?First character of any tcode ?Note on general usage in authorization values
0 … 31( control characters )NoNoNoNot usable.
32( space )Spaces at the end of authorization values are automatically cut off.
33!YesCannot be used at the beginning of authorization values.
34"No
35#Yes
36$
37%
38&
39'No
40(YesCannot be used at the beginning of any authorization value.
41)
42*NoWildcard character.
If used in the middle of a value, all subsequent characters are ignored (see SAP Note 136647).
43+YesYesYesNot a wildcard, but treated as a normal character in authorization values
(see SAP Note 136647).
44,NoYesNo
45-No
46.Yes
47/Yes
(namespace delimiter)
Yes
(namespace delimiter)
Yes
48 … 570 … 9YesYes
58:NoYesNo
59;No
60<Yes
61=
62>
63?
64@No
65 … 90A … ZYesYesYes
91[NoNo
92\No
93]Yes
94^No
95_YesYesYesCannot be used as the only character in a value.
96`NoYesNo
97 … 122a … zNo
(only uppercase letters)
No
(only uppercase letters)
123{NoYes
124|No
125}Yes
126~No
127( delete )Not usable.
128 … 166€ … ¦No
(extended ASCII)
NoUsable, but won't make sense in the majority of cases.
167§Yes
168 … 255¨ … ÿNoUsable, but won't make sense in the majority of cases.
ISO-8859-1CharacterUsable in customer
tcodes ?
Used in any tcode ?First character of any tcode ?Note on general usage in authorization values

Explanation:

  • ISO-8859-1 … the character code
  • Character … self-explanatory
  • Usable in customer tcodes ? – see above (RS_CHARACTER_CHECK)
  • Used in any tcode ?red, if not consistent with 3rd column; green if so
  • First character of any tcode ?red, if not consistent with 3rd column; green otherwise
  • Note on general usage in authorization values … self-explanatory

Conclusion

If you want to obfuscate an asterisk in S_TCODE, just replace it with: + … _* — hardly anybody will ever notice 😉

27May 12

Find step users in SAP batch jobs

Hello all,
using personal users to execute batch job steps is not a good idea!
Of course it's convenient, but those users might vanish or their authorizations might change – but how to clean this mess up? Since SE37 does not allow you to select jobs by step user, one might try to use SE16 (→ table TBTCP) to find the affected jobs… which will drive you crazy, believe me!

Report

This time, I'll provide you with another nice report to clean up your system and prevent any batch-related headache!

So:

  • Create a new report in SE38 and paste this source code (don't forget to set a program authorization group).
  • In the selection texts:
    • Tick "dictionary reference" for R_JOBNAM, R_SDLUSR and R_USRNAM
    • Leave all other texts empty ("?...")

  • Activate & execute.

Usage

On the selection screen you can choose the:

  • job name, -scheduler and -status (like in SE37) and
  • step user name (initially set to your user name, but try DDIC or SAP*).

Submit your selection and you'll get a result similar to this:

The columns at your disposal are:

  • Job name — … self-explanatory.
  • Job no. — the internal ID of the job.
  • Scheduler — the user, who scheduled the job.
  • Job status — … self-explanatory.
  • Step no. — the step ID that matches your selection (the job might consist of more steps).
  • Rept. name — the report or command.
  • Name — the step user (green, if the user still exists; red otherwise)

As always in my reports, you can double-click on almost everything:

  • Job name — goto SE37 and show all matching jobs by name.
  • Job no. — show only the particular job in SE37.
  • Scheduler — open SU01 for the user, who scheduled the job.
  • Step no. — display the step list of the selected job.
  • Rept. name — jump to SE38.
  • Name — show the step user in SU01.

Conclusion

Red is dead, green is clean … unless it's a personal user ! 😎