pascal-lab / Tai-e

An easy-to-learn/use static analysis framework for Java
https://tai-e.pascal-lab.net/docs/index.html
GNU Lesser General Public License v3.0
1.35k stars 171 forks source link

How to resolve taint propagation in type cast #96

Open Raul1718 opened 5 months ago

Raul1718 commented 5 months ago

Description

Hi,

When I was testing the taint analysis plugin, I found an issues in type cast. It seems that current pointer analysis engine could not resolve the assignment relation in type cast now.

I created a test case using the get method of java.util.Map, the signature show below and config into my yaml file.

  - { method: "<java.util.Map: java.lang.Object put(java.lang.Object,java.lang.Object)>", from: 1, to: base }
  - { method: "<java.util.Map: java.lang.Object get(java.lang.Object)>", from: base, to: result }

And The test case code shown below:

import java.util.HashMap;

class ArgToResultMap {
    public static void main(String[] args) {
        String taint = SourceSink.source();
        java.util.Map<String,String> map = new HashMap();
        map.put("test", taint);
        String s2 = map.get("test");
        SourceSink.sink(s2); 
    }
}

The result tir code:

public static void main(java.lang.String[] r4) {
        java.lang.String $r0, %stringconst0, r3;
        java.util.HashMap $r1;
        java.lang.Object $r2;
        [0@L6] $r0 = invokestatic <SourceSink: java.lang.String source()>();
        [1@L7] $r1 = new java.util.HashMap;
        [2@L7] invokespecial $r1.<java.util.HashMap: void <init>()>();
        [3@L8] %stringconst0 = "test";
        [4@L8] invokeinterface $r1.<java.util.Map: java.lang.Object put(java.lang.Object,java.lang.Object)>(%stringconst0, $r0);
        [5@L9] $r2 = invokeinterface $r1.<java.util.Map: java.lang.Object get(java.lang.Object)>(%stringconst0);
        [6@L9] r3 = (java.lang.String) $r2;
        [7@L10] invokestatic <SourceSink: void sink(java.lang.String)>(r3);
        [8@L11] return;
    }

The propagation interrupted in [6@L9] r3 = (java.lang.String) $r2; In the pta-results.txt, I found r3 was pointed to nothing: []:<ArgToResultMap: void main(java.lang.String[])>/r3 -> []

[]:<ArgToResultMap: void main(java.lang.String[])>/$r0 -> [[]:MergedObj{<Merged java.lang.String>}, []:TaintObj{alloc=<ArgToResultMap: void main(java.lang.String[])>[0@L6] $r0 = invokestatic SourceSink.source()/result,type=java.lang.String}]
[]:<ArgToResultMap: void main(java.lang.String[])>/$r1 -> [[]:NewObj{<ArgToResultMap: void main(java.lang.String[])>[1@L7] new java.util.HashMap}, []:TaintObj{alloc=<ArgToResultMap: void main(java.lang.String[])>[0@L6] $r0 = invokestatic SourceSink.source()/result,type=java.util.Map}]
[]:<ArgToResultMap: void main(java.lang.String[])>/$r2 -> [[]:TaintObj{alloc=<ArgToResultMap: void main(java.lang.String[])>[0@L6] $r0 = invokestatic SourceSink.source()/result,type=java.lang.Object}]
[]:<ArgToResultMap: void main(java.lang.String[])>/%stringconst0 -> [[]:ConstantObj{java.lang.String: "test"}]
[]:<ArgToResultMap: void main(java.lang.String[])>/r3 -> []

There maybe analysis wrong in type cast, or here missing the corresponding pointer propagation. How could I correct or resolve the type cast transfer.

Thanks!

MacOs IDEA Ta-e version:master branch, commit id: https://github.com/pascal-lab/Tai-e/commit/4c6b337c92e9122051c80cd58028f07816ad9e1e(Commits on Dec 29, 2023)

zhangt2333 commented 5 months ago

Thanks for the detailed and helpful issue description.

But I noticed that the steps cannot reproduce the result you give.

Anyway, Maybe the following is what you want?

  - { method: "<java.util.HashMap: java.lang.Object put(java.lang.Object,java.lang.Object)>", from: 1, to: base }
  - { method: "<java.util.HashMap: java.lang.Object get(java.lang.Object)>", from: base, to: result, type: "java.lang.String" }
Raul1718 commented 5 months ago

call-site-mode: true

I also set call-site-mode, so it could config through java.util.Map?

Raul1718 commented 5 months ago

Let me try with the type configuration, thanks But when I want to analyzer other type (not String) in Map, how to do?

zhangt2333 commented 5 months ago

But when I want to analyzer other type (not String) in Map, how to do?

Currently I do not have a better solution. I think there won't be too many configuration rules based on your actual needs.

Raul1718 commented 5 months ago

Thanks a lot, master!

It worked in the test case shown above.

Raul1718 commented 5 months ago

Like this

for (HandleFunctionInfo functionInfo : params) { 
...
}
[8@L82] $r4 = invokeinterface params.<java.util.List: java.util.Iterator iterator()>();
[9@L82] $z0 = invokeinterface $r4.<java.util.Iterator: boolean hasNext()>();
[10@L82] %intconst1 = 0;
[11@L82] if ($z0 == %intconst1) goto 35;
[12@L82] $r5 = invokeinterface $r4.<java.util.Iterator: java.lang.Object next()>();
[13@L82] r6 = (com.xxx.xxx.xxx.xxxx.HandleFunctionInfo) $r5;

I also need to config the type com.xxx.xxx.xxx.xxxx.HandleFunctionInfo into the rule? But actually, we usually could not know the type for target project code.

<java.util.Iterator: java.lang.Object next()>", from: base, to: result, type: "com.xxx.xxx.xxx.xxxx.HandleFunctionInfo" }

zhangt2333 commented 5 months ago

I've been thinking about this for a while and realized I've fallen into a trap (Besides, you never posted the run arguments in your description😵‍💫).

Let me re-answer the whole issue.


The code snippet

import java.util.HashMap;
class ArgToResultMap {
    public static void main(String[] args) {
        String taint = SourceSink.source();
        java.util.Map<String,String> map = new HashMap();
        map.put("test", taint);
        String s2 = map.get("test");
        SourceSink.sink(s2); 
    }
}

can be analyzed directly to detect the taint flow TaintFlow{<ArgToResultMap: void main(java.lang.String[])>[0@L3] temp$0 = invokestatic SourceSink.source()/result -> <ArgToResultMap: void main(java.lang.String[])>[11@L7] invokestatic SourceSink.sink(s2)/0}.

This was originally the POWER of P/Taint Analysis (taint analysis based on pointer analysis).

And you need to set the pointer analysis option only-app to false.

Here are my runtime arguments:

public class MyMain {
    public static void main(String[] args) {
        pascal.taie.Main.main(
                "-pp",
                "-cp", "src/test/resources/pta/taint",
                "-m", "ArgToResultMap", // src/test/resources/pta/tain/ArgToResultMap.java contains the above code snippet
                "-a", """
                        pta=
                        implicit-entries:false;
                        only-app:false;
                        distinguish-string-constants:all;
                        taint-config:src/test/resources/pta/taint/taint-config.yml;
                        """
        );
    }
}