【第六篇】SAP ABAP7.5x新语法之SQL注入

2019-01-18 10:37:22 浏览数 (1)

这一篇来说一下SAP ABAP中的SQL注入问题。

公众号:SAP Technical公众号:SAP Technical

前言部分

SQL语法允许开放SQL语句的每子句动态指定作为在括号中指定一个数据对象的内容。如果其中一个数据对象的全部或部分内容来自程序外部,则存在以下SQL注入之一的风险:

访问非允许的数据库表

如果动态指定的数据库表完全或部分来自程序外部,则用户可能会访问他们通常没有授权的数据库。如果在动态指定的数据库表中使用外部输入是不可避免的,则必须正确检查输入。

在以下程序部分中,方法CHECK_TABLE_NAME_STR仅允许访问飞行数据模型的表。来自其他或不存在的数据库表的输入被拒绝。也不允许访问超大数据库表,以避免对系统性能造成太大压力。

代码语言:javascript复制
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> ).

访问非允许的表列用户可能会访问为他们通常没有授权表列。用户还可以未经许可重命名列,或使用聚合函数执行未经授权的计算。如果在动态指定的表列中使用外部输入是不可避免的,则必须正确检查输入。

注意点: 在GROUP BY之后指定列时,相同的安全建议适用于在SELECT之后直接动态指定的列。

动态WHERE条件的操作

如果动态WHERE条件完全或部分来自程序外部,则用户可能会访问他们通常没有授权的数据。如果无法避免在动态WHERE条件中使用外部输入 ,则必须正确检查输入并且通常也会屏蔽输入。

注意点: 动态指定HAVING条件时,应用与动态WHERE条件相同的安全建议。

在以下程序部分中,通过使用类CL_ABAP_DYN_PRG的方法QUOTE来防止潜在的SQL注入,该方法在开头和结尾添加引号。如果未使用此方法,并且输入“x'OR name <>' ”,则会显示SCUSTOM表中的所有数据。

代码语言:javascript复制
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=>quote( name ). 

TRY. 
    SELECT * FROM scustom 
             WHERE (cond) 
             INTO TABLE @customers. 
    cl_demo_output=>display( customers ). 
  CATCH cx_sy_dynamic_osql_syntax. 
    cl_demo_output=>display( 'Wrong input' ). 
ENDTRY.

操纵动态变化表达式

如果动态更改表达式完全或部分来自程序外部,则用户可能会更改他们通常没有授权的数据。如果无法避免在动态更改表达式中使用外部输入,则必须正确检查输入并且通常也会屏蔽输入。

在以下程序部分中,通过使用类CL_ABAP_DYN_PRG的方法QUOTE来防止潜在的SQL注入,该方法在开头和结尾添加引号。如果未使用此方法,并且例如,如果在其中一个输入字段中输入“ ...'discount = '90 ”,则相关客户的折扣将设置为90。

代码语言:javascript复制
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 
       WHERE id = @id 
       INTO @customer. 

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=>quote( name ) ) && 
  COND string( WHEN street IS NOT INITIAL 
               THEN ` STREET = `   && 
               cl_abap_dyn_prg=>quote( street ) ) && 
  COND string( WHEN city IS NOT INITIAL 
               THEN ` CITY = ` && 
               cl_abap_dyn_prg=>quote( city ) ) && 
  COND string( WHEN postcode IS NOT INITIAL 
               THEN ` POSTCODE = ` && 
               cl_abap_dyn_prg=>quote( postcode ) ). 

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

0 人点赞