How to resolve taint propagation in type cast
Raul1718 opened this issue · 7 comments
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: 4c6b337c92e9122051c80cd58028f07816ad9e1e(Commits on Dec 29, 2023)
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" }
call-site-mode: true
I also set call-site-mode, so it could config through java.util.Map?
Let me try with the type configuration, thanks
But when I want to analyzer other type (not String) in Map, how to do?
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.
Thanks a lot, master!
- { 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" }
It worked in the test case shown above.
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" }
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;
"""
);
}
}