Net.Data provides several mechanisms that allow users to assign values to input variables. To ensure that macros execute in the manner intended, these input variables should be validated by the macro. Your database and application should also be designed to limit a user's access to the data that the user is authorized to see.
Use the following development techniques when writing your Net.Data macros. These techniques will help you ensure that your applications execute as intended and that access to data is limited to properly authorized users.
Example: Instead of using %DEFINE SHOWSQL="NO" to set the Net.Data SHOWSQL variable, use @DTW_ASSIGN(SHOWSQL, "NO"). Then, a query string assignment such as SHOWSQL=YES does not override the macro setting.
You can disable the display of SQL statements in production environments using one of the following methods:
See SHOWSQL in the variables chapter of Net.Data Reference for syntax and examples for the SHOWSQL Net.Data variable.
You can also use DTW_ASSIGN to ensure that other Net.Data variables, such as RPT_MAX_ROWS or START_ROW_NUM, are not overridden. See the variables chapter of Net.Data Reference for more information about these variables.
Adding a Net.Data variable to an SQL statement within a macro allows users to dynamically alter the SQL statement before executing it. It is the responsibility of the macro writer to validate user-provided input values and ensure that an SQL statement containing a variable reference is not being modified in an unexpected manner. Your Net.Data application should validate user-provided input values from the URL so the Net.Data application can reject invalid input. Your validation design process should include for the following steps:
Example 1: Using the DTW_POS() string function to verify SQL statements
%FUNCTION(DTW_SQL) query1() { select * from shopper where shlogid = '$(shlogid)' %}
The value of the shlogid variable is intended to be a shopper ID. Its purpose is to limit the rows returned by the SELECT statement to rows that contain information about the shopper identified by the shopper ID. However, if the string "smith' or shlogid<>'smith" is passed as the value of the variable shlogid, the query becomes:
select * from shopper where shlogid = 'smith' or shlogid<>'smith'
This user-modified version of the original SQL SELECT statement returns the entire shopper table.
The Net.Data string functions can be used to verify that the SQL statement is not modified by the user in inappropriate ways. For example, the following logic can be used to ensure that the input value associated with the shlogid variable consists of a single shopper ID:
@DTW_POS(" ", $(shlogid), result) %IF (result == "0") @query1() %ELSE %{ perform some sort of error processing %} %ENDIF
Example 2: Using DTW_TRANSLATE()
Suppose that your application needs to validate that the value provided in the input variable number_of_orders is an integer. One way of accomplishing this is to create a translation table input_translation_table that contains all keyboard characters except the numeric characters 0-9 and to use the DTW_TRANSLATE and DTW_POS string functions to validate the input:
@DTW_TRANSLATE(number_of_orders, "x", input_translation_table, "x", string_out) @DTW_POS("x", string_out, result) %IF (result = "0") %{ continue with normal processing %} %ELSE %{ perform some sort of error processing %} %ENDIF
Note that SQL statements within stored procedures cannot be modified by users at Web browsers and that user-provided input parameter values are constrained by the SQL data types associated with the input parameters. In situations where it is impractical to validate user input values using the Net.Data string functions, you can use stored procedures.
Example: A query string assignment such as filename="../../x" can result in the inclusion of a file from a directory not normally specified in the INCLUDE_PATH configuration statement. Suppose that your Net.Data initialization file contains the following path configuration statement:
INCLUDE_PATH /usr/lpp/netdata/include
and that your Net.Data macro contains the following INCLUDE statement:
%INCLUDE "$(filename)"
A query string assignment of filename="../../x" would include the file /usr/lpp/x , which was not intended by the INCLUDE_PATH configuration statement specification.
The Net.Data string functions can be used to verify that the file name provided is appropriate for the application. For example, the following logic can be used to ensure that the input value associated with the file name variable does not contain the string "..":
@DTW_POS("..", $(filename), result) %IF (result > "0") %{ perform some sort of error processing %} %ELSE %{ continue with normal processing %} %ENDIF
Example: The following SQL statement returns order information for an order identified by the variable order_rn:
select setsstatcode, setsfailtype, mestname from merchant, setstatus where merfnbr = setsmenbr and setsornbr = $(order_rn)
This method permits users at a browser to specify random order numbers and possibly obtain sensitive information about the orders of other customers. One way to safeguard against this type of exposure is to make the following changes:
For example, if shlogid is the column containing the customer ID associated with the order, and SESSION_ID is a Net.Data variable that contains the authenticated ID of the user at the browser, then you can replace the previous SELECT statement with the following statement:
select setsstatcode, setsfailtype, mestname from merchant, setstatus where merfnbr = setsmenbr and setsornbr = $(order_rn) and shlogid = $(SESSION_ID)
For more information on protecting your assets, see the Internet security list of frequently asked questions (FAQ) at this Web site:
http://www.w3.org/Security/Faq