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

访问非允许的数据库表

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

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

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表中的所有数据。

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。

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.

评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!