testable-eu / sast-testability-patterns

Testability Pattern Catalogs for SAST
https://owasp.org/www-project-testability-patterns-for-web-applications/
Apache License 2.0
29 stars 2 forks source link

Review some problems about writing pattern discovery rules #24

Open ManuManu97 opened 1 year ago

ManuManu97 commented 1 year ago

Review of writing discovery rules for complex cases.

In all of the following cases, I used the js2cpg.sh script located in the docker container for generating the cpg.

[JS] pattern 75 functions in Object

In this case, I thought that the ideal discovery rule for example could be something like this:

Search for all Object -> Check if, in the astChild of the Object node, there is a declaration of one or more functions

the problem here is that in the documentation I didn't find the proper way to check for all Objects. For example, I tried with the Node-Type member (I think it is the right one because this Node-Type refers to complex type) but it doesn't work, probably because in the generation of CPG there isn't the functionality to generate this kind of nodes for JS. So, this thing makes hard writing a good discovery rule.

[JS] pattern 6 callback function

In this case, I didn't find a way to check for a function call that has another function as a parameter. The first point is that I didn't find how to check if the type of Identifier node is a function because I think that there is no Type field in the Identifier Node-Type. The second point, I can't extract the Identifier name as can you see in the following snippet but I can get the code that I think is not the right property.

joern> cpg.call.code(".*print.*").argument.filter(_.isIdentifier).name.l 
cmd46.sc:1: value name is not a member of overflowdb.traversal.Traversal[io.shiftleft.codepropertygraph.generated.nodes.Expression]
did you mean take?
val res46 = cpg.call.code(".*print.*").argument.filter(_.isIdentifier).name.l
     ^
Compilation Failed

joern> cpg.call.code(".*print.*").argument.filter(_.isIdentifier).code.l 
res46: List[String] = List("this", "n", "MyFunction", "res", "print")

The last point is that (I don't know a lot scala) I don't understand if I can do something like get the list of function call parameters, if they have type=function, in a variable in scala and the list of all methods in another variable and then check if parameters name are equal to a name of one method.

The following pseudocode is for try to explain better the concept:

@main def main(name : String): Unit = {
    importCpg(name)
    val x2 = (name, "6_callback_function_iall", cpg.call.argument.filter(_.isIdentifier).name.toJson); // the list of function calls arguments
    val y2 = (name, "6_callback_function_iall", cpg.method.name.toJson); // the list of methods name

    for( var x <- x2 ){
        for( var y <- y2 ){
            if(x == y){
                res // put in a List the line number of the function call
            }
        }
    }
    println(res) // return the result of the check 
    delete;
} 

[JS] pattern 98 throw exception

In this case, I found that in theory there is cpg.throws.l to find the throw of exceptions but in this case the cpg gives to me an empty list:

joern> cpg.throws.l 
res61: List[ControlStructure] = List()

So I tried with another version og js2cpg and the cpg gives to me the possibility to find the throws with <operator>.throw and I wrote the following discovery rule:

val x2 = (name, "98_throw_exception_iall", cpg.call.code(".*throw.*").where(n=>n.methodFullName("<operator>.throw")).location.toJson);

but the discovery rule does not work with the js2cpg script in the docker and so I wrote the following that gives as result FP because it get also for example the comment if it contains the word throw:

val x2 = (name, "98_throw_exception_iall", cpg.method.code(".*throw .*").location.toJson);

I hope that I didn't write nonsense things and if you have any doubts tell me. For this week I can only review these 3 patterns because I didn't have a lot of time, I will review other patterns in the next weeks.