Many security vulnerabilities arise from untrusted unchecked input. This input can be used to access unintended data or even corrupt data. Tainted Flow Analysis is defined between its end points:
- Source: Origin of tainted data
- Sink: Where the tainted data is consumed.
The Flow Analysis follows the Tainted data from the Source to the Sink, and sees if there is sufficient Neutralization (cleaning) along the way. Proper neutralization prevents unintended use of the input.
A Neutralization Routine (or Sanitizer) is any piece of code that can assure that any tainted input data is returned untainted (or “safe”) as output.
A Neutralization routine or sanitizer is any routine that transforms tainted input into safe output.
How to define Custom Neutralizations
Custom Neutralizations in KHS behave the same as in Kiuwan. The guidance and examples from the Kiuwan documentation apply directly to KHS. KHS does introduce a few limitations and extra steps (covered below).
To define a Custom Neutralization or Sanitizer, is to let the KHS know what routines in the source code can be identified as such. For this, create a custom neutralization file, in .xml format. This file can have any name, but needs file extension “.xml”.
XML File location - Scope
In Kiuwan, this XML file can be at different locations for use in the scopes: per analysis, per application, or system-wide.
In the KHS, we can only use the scope per analysis. For this we need to add the XML file to the source code we are analyzing, and the location is:
<Source code root directory>/libraries/<Source code language name>/<filename>.xml
The <Source code language name> is one of the list in the KHS file:
bin/LanguageInfo.properties
The <filename> can be any but it is recommended to use a meaningful name such as “custom_neutralizations“.
The XML file is source code language specific so if you have for example one Custom Neutralization for Java and another one for Javascript, then you will need 2 different XML files, in different directories.
For example, from the source code root directory:
libraries/java/custom_neutralizations_java.xml
libraries/javascript/custom_neutralizations_js.xml
Prevent XML from being analyzed in Static Analysis: Exclusions list
In the KHS, files with the extension “*.xml” are analyzed by default as XML, so to prevent the KHS from analyzing this file with its static analysis, we need to add it to the exclusions list.
In the KHS configuration file:
bin/qaking.user.properties
We need to add to the line:
exclude.patterns=This pattern to the existing list of patterns, with a comma separating if necessary:
libraries/**/*.xmlXML File format
XML Library
The Custom Neutralization XML file is source code language specific, but can hold multiple neutralizations for that same source code language; it acts as a library.
The outer framework of the XML file is, for example:
<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="http://www.optimyth.com/schema/definitions/library_metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="java.custom.libraries" standard="custom" technology="java">
</library>- For name=, it's recommended to use <source code language>.custom.libraries
- The technology Java must refer to the source code language, using the names that are in the KHS file:
bin/LanguageInfo.properties
-
You can find a large number of example XML files in the installation of the KHS, in the folder:
libraries/<language>/*.xml
Adding the custom neutralization routines
Under the <library> tag, we define the routines that are the custom neutralizations for the given source code language.
To declare the routine, you must include the element. The XSD schema file describes the allowed set of elements that form part of the library. The most commonly used elements are either class or function, depending on the source code language. Under, for example, a Java class, you must also define the method used.
In the XML files in the KHS libraries folder, you can see in the example files what elements to use for other languages.
Example
<class name="com.mycompany.otherpackage.MyUtils" kind="class" supertypes="com.mycompany.IMyUtilsClass">
<method name="validate" signature="validate(java.lang.String)" match="name">
<return type="java.lang.String"/>The attributes are easy to identify from the class definition:
public class MyUtils implements IMyUtilsClass {
public static String validate(String value) {Neutralization elements
Once the routine has been identified, it must be marked as a neutralization routine. For this, add the <neutralization> element, with the attributes argpos, kind, and resource.
Example
<neutralization argpos="-1" kind="sql_injection" resource="database" />
argpos
The argpos attribute specifies what object (or objects) are untainted by the routine. It indicates which element is being neutralized by this neutralization. Depending on how your custom neutralization routine works, you should code a different value in this argument. Allowed values are:
| Allowed values | Neutralization in XML |
|
0..n: A non-negative value indicates that the argument at the given index (starting at 0)is being neutralized.
|
|
|
-1: Target object (returned value) is being neutralized.
|
|
|
-2: Called object is being neutralized.
|
Neutralization routines could be defined in the same class where they are used, or in a different one, where you can invoke them through an object instantiation call or by a static call. Any combination of this and the argpos attribute values is possible. |
kind
A neutralization routine is usually applied to a specific vulnerability type (or kind). The kind attribute indicates the type of vulnerability affected by this neutralization, like XSS, sql_injection, open_redirect, etc. Use string for general purpose neutralizations.
To see the exact attribute value, locate the vulnerability you need to neutralize from your analysis results, go to the sink data and see the category value.
Example
<applicationName>_java.xml.issues or
In these lines:
<Issue id='4' check='OPT.JAVA.SEC_JAVA.SqlInjectionRule' severity='critical' security='true'>
<Frames>
<Frame id='2' kind='sink' category='sql_injection' resource='database'>resource
A neutralization routine can also be specifically suited to a particular resource type. For example, your neutralization routine could be applied to database or filesystem.
Valid values of resource can be one of (memory |os |configuration |environment |filesystem |formatstr |database |web |network |gui |crypto |other).
As above, check the Sink data to set the appropriate value, from the analysis results files *.xml.issues.
Example case
This Java program MyServlet.java with a standard SQL Injection case:
package com.mycompany.onepackage;
import com.mycompany.otherpackage.MyUtils;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
public class MyServlet extends HttpServlet {
@Override protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
username = MyUtils.validate(username);
Connection conn = pool.getConnection();
String sql = "select * from user where username='" + username +"'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
}
}In this example, line 17 is supposed to Sanitize the input:
username = MyUtils.validate(username);
This method is defined in another class: “MyUtils.java”
package com.mycompany.otherpackage;
public class MyUtils {
// ....
public static String validate(String value) {
// ...
// perform string value validation/Canonicalization/Normalization/Sanitization
// ...
return value; // once cleaned up
}
}Analyzing these two Java files shows a vulnerability in the file:
<applicationName>_java.xml.issuesIn these lines:
<Issue id='4' check='OPT.JAVA.SEC_JAVA.SqlInjectionRule' severity='critical' security='true'>
<Frames>
<Frame id='1' kind='source' category='user_input' resource='web'>
<Location fileId='1' path='MyServlet.java' line='16'/>
<Code>username = request.getParameter("username")</Code>
</Frame>
<Frame id='2' kind='sink' category='sql_injection' resource='database'>
<Location fileId='1' path='MyServlet.java' line='21'/>
<Code>rs = stmt.executeQuery(sql)</Code>This shows that a Tainted Data Flow was detected from the Source in line 16 to the Sink in line 21, but the Sanitation in line 17 was not detected as such.
Now we add this file to the source code root directory:
libraries/java/custom_neutralizations_java.xmlWith this content:
<?xml version="1.0" encoding="UTF-8"?>
<library xmlns="http://www.optimyth.com/schema/definitions/library_metadata"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
name="java.custom.libraries" standard="custom" technology="java">
<class name="com.mycompany.otherpackage.MyUtils" kind="class">
<method name="validate" signature="validate(java.lang.String)" match="name">
<return type="java.lang.String"/>
<neutralization argpos="-1" kind="sql_injection" resource="database" />
</method>
</class>
</library>Specifically:
- The source code language
technology="java" -
The class, method and return type of the Custom Neutralization routine that is used:
<class name="com.mycompany.otherpackage.MyUtils" kind="class"> <method name="validate" signature="validate(java.lang.String)" match="name"> <return type="java.lang.String"/> -
The neutralization element: with the 3 mandatory attributes, which we can read from the KHS output on the Sink node.
<Frame id='2' kind='sink' category='sql_injection' resource='database'>The returned value is being neutralized, so
argpos = -1Which gives:
<neutralization argpos="-1" kind="sql_injection" resource="database" />
Analyzing again, this will show that this violation now no longer detected:
<Issue id='4' check='OPT.JAVA.SEC_JAVA.SqlInjectionRule'....