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

12Jun 13

Mastering S_RFC authorizations // Part 1

Hi!Mastering S_RFC authorizations
In this article, I'll show you a handy way of identifying the S_RFC authorizations your users need; this method helped me a lot recently.

Generally, you might be interested in this topic, because…

  • … you were asked to raise the value of profile parameter
    auth/rfc_authority_check from zero to a greater value
  • … you need a practical approach to improve your S_RFC authorizations
  • … you updated your SAP kernel to a patch level ≥ 7.20-400
    or ≥ 7.21-041 (see SAP Note 1785761)

The challenge

The authorization object S_RFC consists of three fields, but only one of them is of interest for us: RFC_NAME – which is checked against the called function module's group (the other two fields have only one possible value each, so we'll ignore them here).

I opted for a heuristic approach to determine values for that field… so first we'll collect a list of function module calls that occur on a productive system. In part 2 of this series, we'll use that list to determine the affected function groups and derive the required S_RFC values from that.

Unfortunately, this approach assumes that all required RFC calls succeed – so during the analysis phase, S_RFC authorizations have to be (or stay?) oversized to ensure no authorization problems distort the result. I'll leave it to you, how you deal with that…, but you might want to think about setting the profile parameter auth/rfc_authority_check to zero… Danger, Will Robinson! → this has security implementations! 😕

Your options

Obtaining a list of called function modules per user is possible in various ways:

  • the Security Audit Log (tcode SM19/20 » audit class "RFC call")
  • the Business Transaction Analysis (tcode STAD)
  • if you have another good idea, please leave a comment

Using the Security Audit Log would imply some nasty problems: the log size per day is limited (parameters rsau/max_diskspace/*); all logs generated after that limitation is reached are lost.
The functionality of tcode STAD on the contrary quite exactly matches what we need. Furthermore, there is no need to configure anything, as the statistics are recorded anyway (in fact the profile parameter stat/level has to be set to 1… but that's the system default). The structure which is used to record the statistics contains a field that holds the called function modules — so another benefit of the latter method is that we don't have to split a text string (like the one stored in an Audit Log message text, e.g. "Successful RFC Call RFCPING (Function Group = SYST)").

Solution

I chose the second solution — evaluating statistics from STAD —, because it seems to be smarter, more reliable… and gives me the opportunity to code a bit! 😉

The next step is to create a new report called ZS_STAD_EXTRACT_RFC_CALLS and copy-paste this source code.

Then you need to set up two new customer tables that hold the data we want to collect.
Go to SE11 and create the tables ZSSTAD_RFC_DATA and ZSSTAD_LASTRUN.
I'd suggest using the following settings in the subsequent steps:

  • Delivery class "A" = application table,
  • Data class "APPL1" = transaction data, transparent tables (in: Technical settings),
  • Size category "0" = up to 100.000 entries (in: Technical settings) and
  • Enhancement category "Can be enhanced (deep)" (menu: ExtrasEnhancement category)

The field definitions can be found in the top comment of the report source code; use them as shown below:
Creation of table ZSSTAD_RFC_DATA
Then please repeat these steps for the second table.

Last but not least you should schedule the report to run every hour — that's a good value because the runtime of the report stays rather short and there's no danger of losing data (the retention period for STAD data is usually 48 hours, because the statistics files are written every hour and the parameter stat/max_files determines the number of files kept – 48 per default).

Update 1:
You also might want to increase the profile parameter stat/rfcrec, which determines the maximum number of RFC calls in a session that will be recorded in STAD. The default value of 5 is probably not sufficient for all cases!

Update 2:
Please check SAP Note 1964997 for information on the parameters stat/rfc/distinct and stat/rfc/distinct_depth, which are also relevant. Thanks to Christian Wippermann for pointing me to this!

Functionality

So what does it do?
The report reads all statistics records since the time it was last started (which is saved in table ZSSTAD_LASTRUN) or — if that table contains no values — the ones since one hour ago. The records are filtered for RFC calls (all other record types are discarded) and the called function modules' groups are determined.
As the last step, this information is saved to table ZSSTAD_RFC_DATA.
It contains:

  • the date (DATUM),
  • SAP client (MANDT),
  • calling user (UNAME),
  • called function module (FUMOD),
  • the respective function group (FUGRP) and
  • the number of calls (NCALL) per line.

In the below example, the user SAPJSF called RFCPING 22 times on the 4th of May 2013 in client 000:
Sample contents of table ZSSTAD_RFC_DATA
The information in this table will later be used to determine the values for S_RFC.

What's next?

In part 2 of this series, I'll post a nice evaluation report for the above log…

See you then!

5May 13

Sniffing SAP GUI passwords // Part 2

Hi, folks!
In my article about Sniffing SAP GUI passwords in Nov. 2012, I took a look at several state-of-the-art sniffing tools for capturing SAP GUI passwords.
One of those tools was a Wireshark plugin by Martin Gallo of CoreLabs — unfortunately it refused to compile over and over again, which is why I never tested it… but meanwhile Martin released an improved version.

Fortunately, I took the time to try it, because it turned out to be a real gem — a bit hard to obtain, but pretty useful once you got it. 😉

The nice part: Usage

In contrast to the other Wireshark plugin by Positive Research, this one does not only decompress, but also dissect almost all parts of the traffic and shows the respective fields and values (below you can see a DDIC login with the password in plain text).
Another invaluable advantage is of course its availability as source code!

Sniffing the SAP DIAG protocol: Wireshark with CoreLabs plugin

The nasty part: Compilation

The following script does the trick, although you'll probably want to adjust it to the build environment, the Wireshark version and your needs…
(It assumes to be run from the directory, where the plugin tarball is located.)

#!/bin/bash -ex
 
rm -rf wireshark
svn co http://anonsvn.wireshark.org/wireshark/trunk wireshark
 
mkdir wireshark/plugins/sap
tar -C wireshark/plugins/sap -xzf sap-wireshark-plugin-0.1.3.tar.gz
 
cd wireshark
./autogen.sh
 
patch -p0 < plugins/sap/wireshark.patch
 
test -x /usr/bin/python2 && export PYTHON=/usr/bin/python2
./configure --prefix="$PWD" --disable-warnings-as-errors
 
make
make install
 
bin/wireshark

See you soon!

28Mar 13

SAP security policies

Hi there.
This time I'd like to present a hot new SAP feature to you: Security policies!
( Available starting from ERP 6.0 EHP6. )

Effect

The system behavior regarding password rules and logon restrictions is controlled by profile parameters, e.g. "login/min_password_lng" for the minimum password length. These parameters are valid system-wide and could not be overridden by any means.
With the new security policies, it is now possible to define different sets of password rules, password change policies and logon restrictions and assign these policies to users.

This provides the flexibility to segregate users and assign an appropriate policy to each of those groups of users!
For instance, you can enforce strict rules on the global level (= profile parameters) and loosen them on user level via a security policy (e.g. increased validity period of unused initial password for users, who use SAP less frequently).

For users with a security policy assignment, the attributes defined therein override replace the profile parameters – for users without a SecPol the parameters stay relevant.

Creation

The administration of security policies can be performed via the new tcode SECPOL, which is secured by two brand-new authorization objects: S_SECPOL is checked during the maintenance of the policies themselves, while S_SECPOL_A is used to define the values that may be assigned to the security policy attributes.
First of all, let's create a new policy:

Security policy creation

… then mark it and switch to the attribute maintenance screen by double-clicking on "Attributes".

Attributes

The following attributes are available:

TypeSecurity policy
attribute
Corresponding
profile parameter
Description
Password rulesCHECK_PASSWORD_BLACKLIST( none )Check the password blacklist
MIN_PASSWORD_DIGITSlogin/min_password_digitsMinimum number of digits
MIN_PASSWORD_LENGTHlogin/min_password_lngMinimum password length
MIN_PASSWORD_LETTERSlogin/min_password_lettersMinimum number of letters
MIN_PASSWORD_LOWERCASElogin/min_password_lowercaseMinimum number of lowercase letters
MIN_PASSWORD_SPECIALSlogin/min_password_specialsMinimum number of special characters
MIN_PASSWORD_UPPERCASElogin/min_password_uppercaseMinimum number of uppercase letters
Password change
policies
MIN_PASSWORD_CHANGE_WAITTIMElogin/password_change_waittimeMinimum wait time for password change
MIN_PASSWORD_DIFFERENCElogin/min_password_diffNo. of different characters when changing
PASSWORD_CHANGE_FOR_SSOlogin/password_change_for_SSOPassword change requirement for SSO logons
PASSWORD_CHANGE_INTERVALlogin/password_expiration_timeInterval for regular password changes
PASSWORD_COMPLIANCE_TO_CURRENT_POLICYlogin/password_compliance_to_current_policyPassword change after rule tightening
PASSWORD_HISTORY_SIZElogin/password_history_sizeSize of the password history
Logon restrictionsDISABLE_PASSWORD_LOGONlogin/disable_password_logon,
login/password_logon_usergroup
Disable password logon
DISABLE_TICKET_LOGON( none )Disable ticket logon
MAX_FAILED_PASSWORD_LOGON_ATTEMPTSlogin/fails_to_user_lockMaximum number of failed attempts
MAX_PASSWORD_IDLE_INITIALlogin/password_max_idle_initialValidity of unused initial passwords
MAX_PASSWORD_IDLE_PRODUCTIVElogin/password_max_idle_productiveValidity of unused productive passwords
PASSWORD_LOCK_EXPIRATIONlogin/failed_user_auto_unlockAutomatic expiration of password lock

The button "Effective…" shows the relation of the policy values to the default ones (=, ≠ or not set), while the "Superfluous Entries" button identifies unnecessary entries (i.e. identical to the default ones).

Security policy attribute maintenance

Assignment

To assign the newly created security policy, just edit a user in SU01, switch to the "Logon Data" tab and enter the SecPol name in the "Security Policy" field:

Security policy assignment via SU01

Mass-assignments via SU10 are of course possible, too!

To be able to assign a SecPol, you'll need the authorization object "S_SECPOL", which behaves similar to S_USER_AGR – i.e. activity 22 (assign) and the policy's name are checked.

If you want to select users by their security policy assignment, you can simply use the User Information System:

SUIM » User » by Logon Date and Password Change

Central user administration

The security policy ↔ user assignment is supported by the CUA and its distribution can be configured via SCUM as usual.

See you next time!

23Feb 13

Cross-client SAP user listing

Hello!
You might be faced with the task to create a really comprehensive user listing for a SAP system with several productive clients – even including 000 and 066.

This is usually a boring task, as you have to log in to every client… gather the list… proceed to the next client… and so on…
Apart from dying of boredom you might run into the problem of not having access to all clients (e.g. 066). 😕

Mediocre solution:

Write a report like this:

REPORT.
TABLES: usr02.
 
SELECT * FROM usr02 CLIENT SPECIFIED ORDER BY mandt.
  WRITE: / usr02-mandt, usr02-bname.
ENDSELECT.

Pro: Easy, simple, fast.
Con: Has to be transported, protected… and using "CLIENT SPECIFIED" is considered bad code by many companies!

Slick solution:

Use the report RSUVM005, which is intended for system measurement: it gives you a list of (almost!) all users on the clients you specify on the selection screen.
Still the list is missing a few users, because SAP quite rightly considers them irrelevant for licensing — they are automatically filtered out by the report (or more specifically: by the function module SLIM_EXCLUDE_USER):

SAP clientExcluded user
000DDIC
001
066EARLYWATCH
( all other clients )ALEREMOTE
SAPCPIC
ITSLOGIN
J2EE_ADMIN
J2EE_GUEST
SAP*
SAPSUPPORT
TMSADM
WF-BATCH
WFTEST

To get the comprehensive user listing, we just need a cross-client selection for those excluded user names in addition.
Fortunately you can simply achieve this via tcode SM21 and (mis-)use the "User" field to check for the existence of the missing users on other clients.

SM21 cross-client user selection

Now you can compile the cross-client user listing from within one client…
😎

9Feb 13

Audit-proof versioning of programs: VERS_AT_IMP

Hi there,
let's have a look at a very handy system parameter, which is nevertheless not checked as frequently as others in audits — the tp parameter VERS_AT_IMP.

In a default installation this parameter is set to »NEVER«, which means that no new version is created when transporting a program to a target system; the code is simply overwritten there.
If the parameter is set to »ALWAYS« (which is the only other valid option), a version history is maintained analogous to the development system.

Btw.: not only reports are affected by this, but actually all workbench objects that support versioning.

Functionality of tp parameter VERS_AT_IMP

Why does that matter?

The legal codes of many (all?) countries prescribe a duty to preserve records, which is also relevant for program code – the German HGB (Handelsgesetzbuch) for instance. Therefore it is a risk to allow old program versions to be deleted (due to a lack of knowledge – or on purpose).

Developers are usually allowed to execute all reports on a development system, which also includes RSVCAD03 and RSVCAD04. These reports allow the deletion of a program's version history (they're NOT assigned to any program authorization group and the program code does NOT contain any AUTHORITY-CHECKs ← read comments below).

Update: Meanwhile SAP has added an authorization check for S_CTS_ADMI with value TABL to both programs. Anyway, this authorization is checked in many places and chances are high that a number of users have (and need) this authorization for other purposes. So this does not change the general recommendation of this article…

So your options are:

  • if you want to keep the version history on the development system: do whatever it takes to secure RSVCAD03 and RSVCAD04 (just removing S_CTS_ADMI from all roles will not work, especially on non-productive systems) and be careful when restoring the system; you might lose versions (think of reinstallations)
  • set VERS_AT_IMP to »ALWAYS« on the productive system and keep your version history there (of course the above reports have to be secured as well)

As you probably guessed, the second option is favorable, because:

  • authorizations on production are much more limited, so protecting the reports RSVCAD03/04 is much easier there
  • the continuity of a productive system can be ensured, while this is not true for a development system

Where to check it?

Start report RSTMSTPP, enter the productive system's SID and go for it.

Where to set it?

Go to STMS → System Overview. Then double-click in your productive system and switch to the "Transport Tool" tab.
If the parameter does not appear there, it is set to the default value »NEVER«!

Update: Effect on installation of support packages

SPAM settings: Object versioning during support package installations
Switching the parameter to ALWAYS has no automatic effect on transaction SPAM. In other words: installing support packages does not lead numerous (useless) versions of SAP standard objects.
The simple reason is that SPAM allows you to choose whether to create versions of the objects in support packages or not (→ disabled per default).
To enable it, setting VERS_AT_IMP to ALWAYS is a prerequisite — check out SPAM → Extras → SettingImport queueCreate object versions during import — but be aware that this might have an impact on performance and database size.

So long!