SAP NetWeaver AS ABAP Release 750, ©Copyright 2016 SAP AG. All rights reserved.
ABAP - Keyword Documentation → ABAP - Security Notes → Security Risks Caused by Input from Outside →System Command Injections
A system command injection is a attack method that can result from insufficiently secure input from outside. A System Command Injection forwards malicious operating system statements, which enter a program from an external source, to the operating system. In ABAP, this can occur when the following programming techniques are used:
The SXPG framework is the only recommended method for executing operating system statements from the application server in ABAP. Here, only predefined logical command names can be passed to function modules in the function group SXPG, so enabling a certain amount of independence from the operating system in question. These predefined logical command names comprise a whitelist, preventing both unwanted operating system statements from being executed and also direct system command injections. When the statement is called, authorization checks and other checks take place. If further parameters can be passed to the function modules, they can be checked for unwanted code relatively easily.
The two other ways of executing operating system statements from the application server are not at all secure (even with no external input) and should be avoided in ABAP programs. Calls of the SYSTEM function using internal statements should be especially avoided and can and should be deactivated using the profile parameter rdisp/call_system. External statements or parts of external statements should never be passed to the operating system without being checked first. Checking and filtering user input when using FILTER or CALL 'SYSTEM' is, however, particularly difficult, since all possible operating systems and code pages must be covered.
In principle, all input from outside must be checked if passed to the parameters of SXPG framework function modules and to parameters of the method or function module used to execute operating system statements on the presentation server. This prevents unwanted effects from operating system statements.
Example
In the following program section, the operating system statement ping of the current application server is executed for a database server using the unwanted system function SYSTEM. If this function has been deactivated (using the profile parameter rdisp/call_system), a runtime error occurs. The number of "pings" and the database server can be set externally. The program can be manipulated by two attacks:
TYPES char255 TYPE c LENGTH 255.
DATA dbserver TYPE char255.
CALL 'C_SAPGPARAM' ID 'NAME' FIELD 'SAPDBHOST'
ID 'VALUE' FIELD dbserver.
DATA pings TYPE i VALUE 1.
cl_demo_input=>add_field( CHANGING field = pings ).
cl_demo_input=>add_field( CHANGING field = dbserver ).
cl_demo_input=>request( ).
IF dbserver IS INITIAL.
cl_demo_output=>display( 'DBSERVER must not be initial ...' ).
RETURN.
ENDIF.
DATA command TYPE char255.
command = |ping -c{ COND i( WHEN pings <= 1 THEN 1
ELSE pings )
} { dbserver }|.
DATA result TYPE TABLE OF char255 WITH EMPTY KEY.
CALL 'SYSTEM' ID 'COMMAND' FIELD command
ID 'TAB' FIELD result.
cl_demo_output=>display( result ).
Example
In the following program section, the unwanted use of the system function SYSTEM is replaced by calling the function module SXPG_CALL_SYSTEM for the logical command name PING predefined by SAP. The function module call only shows some of the possible exceptions.
DATA dbserver TYPE c LENGTH 255.
CALL 'C_SAPGPARAM' ID 'NAME' FIELD 'SAPDBHOST'
ID 'VALUE' FIELD dbserver.
DATA pings TYPE i VALUE 1.
cl_demo_input=>add_field( CHANGING field = pings ).
cl_demo_input=>add_field( CHANGING field = dbserver ).
cl_demo_input=>request( ).
DATA parameters TYPE sxpgcolist-parameters.
parameters = |-c{ COND i( WHEN pings <= 1 THEN 1
WHEN pings >= 10 THEN 10
ELSE pings )
} { dbserver }|.
DATA result TYPE TABLE OF btcxpm WITH EMPTY KEY.
CALL FUNCTION 'SXPG_CALL_SYSTEM'
EXPORTING
commandname = 'PING'
additional_parameters = parameters
TABLES
exec_protocol = result
EXCEPTIONS
no_permission = 1
command_not_found = 2
security_risk = 3
OTHERS = 4.
IF sy-subrc = 0.
cl_demo_output=>display( result ).
ELSE.
cl_demo_output=>display( |Error, return code { sy-subrc }| ).
ENDIF.
Note
The example above can itself be improved by using a self-defined logical command name instead of the predefined logical command name PING. For each operating system used, this command name gives the ping statement a specific path, such as /bin/ping for Linux or c:\Windows\System32\ping.exe for MS Windows. This calls the specified statement precisely and any attacker is unable to smuggle a statement with the same name (but with the wrong function) into a directory in front of the required target directory in the environment variable for the path.