SAP SQL INJ DYN TOKENS SCRTY

Get Example source ABAP code based on a different SAP table
  


ARTICLE

SQL Injections Using Dynamic Tokens
The Open SQL syntax allows you to specify every clause of an Open SQL statement as the content of a data object listed in parentheses. If all of part of the content of one of these data objects originates from outside of the program, there is a risk of one of the following SQL injections:
ITOC

Note
In a dynamic token, it is more secure to specify the name of an ABAP data object as an operand, instead of entering a value as a literal.

Example
The first dynamic WHERE condition is insecure compared to an SQL injection, if input is an external input, which is not checked or masked beforehand. This is not necessary for the second dynamic WHERE condition. DATA(sql_cond1) = `CARRID = '` <(> <)><(> <)> input <(> <)><(> <)> `'`.
SELECT SINGLE * FROM scarr INTO wa WHERE (sql_cond1).

DATA(sql_cond2) = `CARRID = input`.
SELECT SINGLE * FROM scarr INTO wa WHERE (sql_cond2).

Access to non-permitted database tables
If a dynamic specification of dbtab_syntax database tables (for the statement SELECT or for writes) originates completely or partially from outside the program, then users could potentially access databases for which they usually do not have authorization. If the use of external input in a dynamic specification of database tables is unavoidable, the input must be properly checked. For example, the class CL_ABAP_DYN_PRG can be used to make a comparison with a whitelist.

Example
In the following program section, the method CHECK_TABLE_NAME_STR only allows access to tables of the flight data model. Inputs from other or non-existent database tables are rejected. Access to oversized database tables is also not allowed, to avoid putting too much strain on system performance. DATA dbtab TYPE string.
cl_demo_input=>request( CHANGING field = dbtab ).

TRY.
dbtab =
cl_abap_dyn_prg=>check_table_name_str(
val = to_upper( dbtab )
packages = 'SAPBC_DATAMODEL' ).
CATCH cx_abap_not_a_table cx_abap_not_in_package.
cl_demo_output=>display( 'Wrong input' ).
LEAVE PROGRAM.
ENDTRY.

DATA dref TYPE REF TO data.
FIELD-SYMBOLS <(><<)>fs> TYPE STANDARD TABLE.
CREATE DATA dref TYPE STANDARD TABLE OF (dbtab)
WITH EMPTY KEY.
ASSIGN dref->* TO <(><<)>fs>.

DATA lines TYPE i.
SELECT COUNT(*)
FROM (dbtab)
INTO (lines).
IF lines > 1000.
cl_demo_output=>display( 'Table too large' ).
LEAVE PROGRAM.
ENDIF.

SELECT *
FROM (dbtab)
INTO TABLE <(><<)>fs>.
cl_demo_output=>display( <(><<)>fs> ).

Access to non-permitted table columns
If a dynamic specification of column_syntax table columns (for the statement SELECT) originates completely or partially from outside the program, then users could potentially access table columns for which they usually do not have authorization. Users could also rename columns without permission or use aggregate functions to perform unauthorized calculations. If the use of external input in a dynamic specification of table columns is unavoidable, the input must be properly checked. For example, the class CL_ABAP_DYN_PRG can be used to make a comparison with a whitelist.

Note
When specifying columns after GROUP BY , the same security advice applies as for the dynamic specification of columns directly after SELECT.

Example
See the example in column _syntax. Here only columns from a whitelist are permitted to be read.

Manipulation of the dynamic WHERE condition
If a dynamic WHERE condition cond_syntax originates completely or partially from outside the program, then users could potentially access data for which they usually do not have authorization. If the use of external input in a dynamic WHERE condition cannot be avoided, the input must be properly checked and usually masked as well. To do this, you can sue the methods of class CL_ABAP_DYN_PRG.

Note
When dynamically specifying a HAVING condition, the same security advice applies as for the dynamic WHERE condition.

Example
In the following program section, a potential SQL injection is impaired by the ESCAPE_QUOTES method of class CL_ABAP_DYN_PRG . If this method is not used, then if 'x' OR name <(><<)>> '' is entered, for example, all the data in the SCUSTOM table is displayed. DATA name TYPE string.
DATA customers TYPE TABLE OF scustom WITH EMPTY KEY.

cl_demo_input=>request( CHANGING field = name ).

DATA(cond) = `country = 'DE' AND name = '` <(> <)><(> <)>
cl_abap_dyn_prg=>escape_quotes( name ) <(> <)><(> <)> `'`.

TRY.
SELECT * FROM scustom
INTO TABLE customers
WHERE (cond).
cl_demo_output=>display( customers ).
CATCH cx_sy_dynamic_osql_syntax.
cl_demo_output=>display( 'Wrong input' ).
ENDTRY.
More examples under dynamic WHERE condition.

Manipulating a change expression
If a dynamic change expression expr_syntax (for the statement UPDATE) originates completely or partially from outside the program, then users could potentially change data for which they usually do not have authorization. If the use of external input in a dynamic change expression cannot be avoided, the input must be properly checked and usually masked as well. To do this, you can sue the methods of class CL_ABAP_DYN_PRG.

Example
In the following program section, a potential SQL injection is impaired by the ESCAPE_QUOTES method of class CL_ABAP_DYN_PRG . If this method is not used, then if '...' discount = '90', for example, is entered in one of the input fields, the discount for the relevant customer is set to 90. DATA in TYPE REF TO if_demo_input.

DATA customer TYPE scustom.

DATA: id TYPE scustom-id,
name TYPE string,
street TYPE string,
city TYPE string,
postcode TYPE string.

id = '00000001'.
SELECT SINGLE *
FROM scustom
INTO customer
WHERE id = id.

name = customer-name.
street = customer-street.
city = customer-city.
postcode = customer-postcode.

in = cl_demo_input=>new( ).
in->add_field( CHANGING field = name
)->add_field( CHANGING field = street
)->add_field( CHANGING field = city
)->add_field( CHANGING field = postcode
)->request( ).

DATA(set_expr) =
COND string( WHEN name IS NOT INITIAL
THEN ` NAME = '` <(> <)><(> <)>
cl_abap_dyn_prg=>escape_quotes( name ) <(> <)><(> <)> `'` ) <(> <)><(> <)>
COND string( WHEN street IS NOT INITIAL
THEN ` STREET = '` <(> <)><(> <)>
cl_abap_dyn_prg=>escape_quotes( street ) <(> <)><(> <)> `'` ) <(> <)><(> <)>
COND string( WHEN city IS NOT INITIAL
THEN ` CITY = '` <(> <)><(> <)>
cl_abap_dyn_prg=>escape_quotes( city ) <(> <)><(> <)> `'` ) <(> <)><(> <)>
COND string( WHEN postcode IS NOT INITIAL
THEN ` POSTCODE = '` <(> <)><(> <)>
cl_abap_dyn_prg=>escape_quotes( postcode ) <(> <)><(> <)> `'` ).

TRY.
UPDATE scustom SET (set_expr) WHERE id = id.
CATCH cx_sy_dynamic_osql_syntax.
cl_demo_output=>display( 'Wrong input' ).
ENDTRY.