Chan9390 / codeql-javascript-unsafe-jquery-plugin

Home Page:https://lab.github.com/githubtraining/codeql-for-javascript:-unsafe-jquery-plugin

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Step 9 - Detecting untrusted data flow sources

github-learning-lab opened this issue · comments

Step 9: Detecting the sources

We have now identified places in the program which receive jQuery plugin options, and which may be considered as sources of untrusted data. In this step we'll create a predicate that will hold true if a DataFlow::Node is such a source. This predicate will be helpful for our last query.

📖 The exists quantifier

So far, we have declared variables in the from section of a query clause. Sometimes we need temporary variables in other parts of the query, and don't want to expose them in the query clause. The exists keyword helps us do this. It is a quantifier: it introduces temporary variables and checks if they satisfy a particular condition.

To understand how exists works, visit the documentation.

Then let's take an example. In a previous step you created a query to get calls to $:

from CallExpr dollarCall
where dollarCall.getCalleeName() = "$"
select dollarCall

How would you transform this query to get only calls to $ that have at least one argument? You could write:

from CallExpr dollarCallWithArgument, Expr dollarArg
where dollarCallWithArgument.getCalleeName() = "$" and dollarArg = dollarCallWithArgument.getAnArgument()
select dollarCallWithArgument

But in that query dollarArg is not used other than as a temporary variable, so another way to write the same thing is to use the exists quantifier:

from CallExpr dollarCallWithArgument
where dollarCallWithArgument.getCalleeName() = "$" and exists(Expr dollarArg | dollarArg = dollarCallWithArgument.getAnArgument())
select dollarCallWithArgument

And we can simplify the query to finally write:

from CallExpr dollarCallWithArgument
where dollarCallWithArgument.getCalleeName() = "$" and exists(dollarCallWithArgument.getAnArgument())
select dollarCallWithArgument

⌨️ Identify sources

You will transform the previous query you wrote to identify the places in the program which receive jQuery plugin options, into a predicate called isSource, by using the exists quantifier.

Edit the file sources.ql and fill in the TODOs in the template below.

The from ... where ... select query here is just there to test your isSource predicate,
and should give you the same results as your previous query.

You notice that below the source is of type DataFlow::Node whereas in your previous query you used
DataFlow::ParameterNode. This is ok as a ParameterNode is a Node.

Submit your query.

import javascript

predicate isSource(DataFlow::Node source) {
    exists(<TODO: declare temporary variables> |
      <TODO: clause that identifies your source as a jquery plugin option>
    )
}

from DataFlow::Node node
where isSource(node)
select node