Skip to content

Tutorial 1. Write your first InternalFLuentTQL specification

Ranjith K edited this page Sep 9, 2021 · 23 revisions

Note: Links for the examples. For the security vulnerabilities example click here. For the InternalFluentTQL specification of the respective security vulnerability click here.

Let's take a simple SQL-Injection example. The below example code contains the SQL-Injection.

public class SimpleSQLInjection {

    public static ResultSet getEmployeeInformationWithSanitizer() throws SQLException {
        Scanner mySC = new Scanner(System.in);

        // Source: Method nextLine is a source that takes input from the user.
        String employeeID = mySC.nextLine();

        mySC.close();

        PolicyFactory POLICY_DEFINITION = new HtmlPolicyBuilder().toFactory();

        // Sanitizer: Method sanitize is a sanitizer that sanitizes the user input, therefore, the below line should be uncommented to avoid SQL-Injection.
        //employeeID = POLICY_DEFINITION.sanitize(employeeID);

        Connection myConnection = DriverManager.getConnection("jdbc:hsqldb:mem:EMPLOYEES", "test", "test");
        Statement myStatement = myConnection.createStatement();

        // Sink: Method executeQuery is a sink that performs the sensitive operation and leaks the data.
        ResultSet queryResult = myStatement.executeQuery("SELECT * FROM EMPLOYEE where EID = " + employeeID);

        return queryResult;

    }
}

For InternalFluentTQL specification, Class must implements the interface FluentTQLUserInterface.

import de.fraunhofer.iem.secucheck.InternalFluentTQL.fluentInterface.SpecificationInterface.FluentTQLUserInterface;

public class SimpleSQLInjectionSpec implements FluentTQLUserInterface {
...

All the methods(source, sanitizer, required propagators, and sink) has to be defined in InternalFluentTQL. The below example shows how to define the method.

Method sanitizer = new MethodConfigurator("org.owasp.html.PolicyFactory: java.lang.String sanitize(java.lang.String)")
            .in().param(0)
            .out().returnValue().configure();

The sensitive information that goes into the method is configured using the InputDeclaration (in()) and the sensitive information that comes out of the method is configured using OutputDeclaration (out()).

An example of the information that flows into the method: In the method sanitize, the first parameter is the user input that is sensitive information. To configure this in InternalFluentTQL, param() with the parameter id can be used. The first parameter is 0 in InternalFluentTQL specification.

An example of the information that comes out from the method: In the method sanitize, the return value is the sanitized user input. To configure this in InternalFluentTQL, returnValue() can be used.

Sometimes, we also need to configure that the sensitive information may flow through "this" object. For this, thisObject() can be used.

Below is the complete InternalFluentTQL specification for our example SQL-Injection.

public class SimpleSQLInjectionSpec implements FluentTQLUserInterface {
    /**
     * Source
     */
    Method source = new MethodConfigurator("java.util.Scanner: java.lang.String nextLine()")
            .out().returnValue().configure();

    /**
     * sanitize method is OWASP HTML sanitizer, which sanitizes the special characters so that SQL Injection does not occur. It is a simple example, For security, it's better to use
     * encodeForSQL or make the settings of sanitizing method to avoid SQL Injection.
     */
    Method sanitizer = new MethodConfigurator("org.owasp.html.PolicyFactory: java.lang.String sanitize(java.lang.String)")
            .in().param(0)
            .out().returnValue().configure();

    /**
     * Sink
     */
    Method sink = new MethodConfigurator("java.sql.Statement: java.sql.ResultSet executeQuery(java.lang.String)")
            .in().param(0).configure();

    /**
     * Returns the Internal FluentTQL specification
     *
     * @return Internal FluentTQL specification
     */
    public List<FluentTQLSpecification> getFluentTQLSpecification() {
        TaintFlowQuery myTF = new TaintFlowQueryBuilder()
                .from(source)
                .notThrough(sanitizer)
                .to(sink)
                .report("There is a SQL Injection - CWE89!!!")
                .at(LOCATION.SOURCEANDSINK)
                .build();

        List<FluentTQLSpecification> myFluentTQLSpecs = new ArrayList<FluentTQLSpecification>();
        myFluentTQLSpecs.add(myTF);

        return myFluentTQLSpecs;
    }
}

All the InternalFluentTQL specifications must override the method getFluentTQLSpecification().

  1. Taint Flow must start from the source, therefore all the source methods must be passed to "from()".
  2. If the sensitive information goes 'through' the required propagator or the de-sanitizer then there will be a taint flow, therefore these methods are passed to "through()".
  3. If the sensitive information does 'not goes through' the sanitizer then there will be a taint flow, therefore all the sanitizer must be passed to "notThrough()".
  4. Finally, Taint flow ends in the sink method, therefore sink methods are passed to "to()".
  5. The error message can be customized using "report()".
  6. The location at which the error message should be displayed in the IDE can be configured using "at()"."at()" takes the argument enum LOCATION. LOCATION can be SOURCE (displays at source method location), sink (displays at sink method location), or SOURCEANDSINK (display at both source and sink method location).

More than one method can be merged using the "MethodSet". The "MethodSet" behavior is like an OR operator. More than one TaintFLowQuery can be combined using the "QueriesSet", even "QueriesSet" behavior also like an OR operator.