secure-software-engineering / FlowDroid

FlowDroid Static Data Flow Tracker
GNU Lesser General Public License v2.1
1.06k stars 298 forks source link

Test Aliasing4 is failing #761

Open Jclavo opened 2 months ago

Jclavo commented 2 months ago

I am checking the tests from securibench in the soot-infoflow/ folder and I have noticed that test Aliasing4 (https://github.com/secure-software-engineering/FlowDroid/blob/develop/soot-infoflow/securiBench/securibench/micro/aliasing/Aliasing4.java) is failing.

This test has two 2 sinks

       String name = req.getParameter(FIELD_NAME);
       Object o1 = name;
       Object o2 = name.concat("abc");
       Object o3 = "anc";

       PrintWriter writer = resp.getWriter();
       writer.println(o1);                              /* BAD */
       writer.println(o2);                              /* BAD */
       writer.println(o3);                              /* OK */

but the solution is reporting just one. image

so analysing the code I found that Flowdroid is not recognizing Object o2 as tainted when the next line is performed

Object o2 = name.concat("abc");

My question is: Does Flowdroid support calls to native method like toUpperCase() or concat() without losing the tainted for the variable?

Jclavo commented 2 months ago

I have been continuing checking and I found that there are others tests failing for the same reason:

Also, I found an interesting thing; test for factories3 https://github.com/secure-software-engineering/FlowDroid/blob/develop/soot-infoflow/securiBench/securibench/micro/factories/Factories3.java calls to a native method and their tainted is not lost

        StringWrapper w1 = new StringWrapper(s1);
        StringWrapper w2 = new StringWrapper("abc");

        PrintWriter writer = resp.getWriter();

        writer.println(w1.toString());    /* BAD */
        writer.println(w2.toString());    /* OK */

while Test for factories2 https://github.com/secure-software-engineering/FlowDroid/blob/develop/soot-infoflow/securiBench/securibench/micro/factories/Factories2.java calls to a native method and their tainted is lost.

        String s1 = req.getParameter("name");
        String s2 = s1.toString();
        String s3 = "abc".toString();

        PrintWriter writer = resp.getWriter();

        writer.println(s2);    /* BAD */
        writer.println(s3);    /* OK */

In conclusion: Flowdroid loses tainted flow calling native method like "toString()" when the variable is an "string" but if it is an "object" the tainted flow is not lost.

@StevenArzt Do you think that I am missing some configurations to enable this behaviour?

StevenArzt commented 1 month ago

That's strange. I had to update quite a few things to get the SecuriBench test cases running again because they were originally based on a highly outdated version of the servlet API, but once I migrated that to Jakarta, the tests ran fine.

For Aliasing4:

[main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke r4.<java.io.PrintWriter: void println(java.lang.Object)>(r1) in method <securibench.micro.aliasing.Aliasing4: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.Infoflow - - r1 = interfaceinvoke r0.<jakarta.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>("name") in method <securibench.micro.aliasing.Aliasing4: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)>
[main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke r4.<java.io.PrintWriter: void println(java.lang.Object)>(r2) in method <securibench.micro.aliasing.Aliasing4: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.Infoflow - - r1 = interfaceinvoke r0.<jakarta.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>("name") in method <securibench.micro.aliasing.Aliasing4: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)>

For Datastructures5:

[main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke r9.<java.io.PrintWriter: void println(java.lang.String)>(r7) in method <securibench.micro.datastructures.Datastructures5: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.Infoflow - - r1 = interfaceinvoke r0.<jakarta.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>("name") in method <securibench.micro.datastructures.Datastructures5: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)>

For Factories1:

[main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke r6.<java.io.PrintWriter: void println(java.lang.String)>(r2) in method <securibench.micro.factories.Factories1: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.Infoflow - - r1 = interfaceinvoke r0.<jakarta.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>("name") in method <securibench.micro.factories.Factories1: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)>

For Factories2:

[main] INFO soot.jimple.infoflow.Infoflow - The sink virtualinvoke r6.<java.io.PrintWriter: void println(java.lang.String)>(r2) in method <securibench.micro.factories.Factories2: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)> was called with values from the following sources:
[main] INFO soot.jimple.infoflow.Infoflow - - r1 = interfaceinvoke r0.<jakarta.servlet.http.HttpServletRequest: java.lang.String getParameter(java.lang.String)>("name") in method <securibench.micro.factories.Factories2: void doGet(jakarta.servlet.http.HttpServletRequest,jakarta.servlet.http.HttpServletResponse)>

FlowDroid uses summaries to cover methods from the Java standard library. It therefore makes no difference whether these methods are implemented in native code or not.

How did you run the tests? Did you use the offical JUnit test cases for SecuriBench or something else? Maybe you are missing the library summary configuration if you have your own runner instead of the official test cases.

Jclavo commented 1 month ago

Hi @StevenArzt, I set up to work with Jakarta and now the tests that I mentioned run smoothly. However a few tests (13) are still failing. Capture d’écran du 2024-09-24 18-16-10 I am wondering if when you run them, all the tests were green?