Skip to content

Commit 36fc4f7

Browse files
ningningerauroraberryIsla-top
authored
Add commonly used taint configuration (#136)
Co-authored-by: auroraberry <2507097782@qq.com> Co-authored-by: Isla-top <211220177@smail.nju.edu.cn>
1 parent 10efc00 commit 36fc4f7

97 files changed

Lines changed: 2126 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/en/taint-analysis.adoc

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Taint analysis can be enabled in one of two ways, or both approaches together:
1515

1616
* using the programmatic configuration provider.
1717

18+
[[yaml-configuration-file]]
1819
=== YAML Configuration File
1920

2021
In Tai-e, taint analysis is designed and implemented as a plugin of pointer analysis framework.
@@ -513,3 +514,95 @@ then you can open the TFG with your web browser and examine it.
513514
NOTE: We plan to develop more user-friendly mechanisms for examining taint analysis results in the future.
514515

515516
// TODO: == Troubleshooting
517+
518+
== Pre-prepared Commonly Used Taint Configuration
519+
520+
Manually collecting and writing taint analysis configurations for different vulnerability types can be time-consuming and challenging, especially for developers and security researchers with limited experience.
521+
To help users streamline this process and improve the efficiency and accuracy of vulnerability detection, we have curated _Commonly Used Taint Configuration_.
522+
When creating or modifying your own taint analysis configuration, you can refer to this configuration for guidance in your process.
523+
524+
Commonly Used Taint Configuration is a comprehensive collection of source, sink, and transfer rules tailored for various common vulnerability types.
525+
Currently, this collection contains 327 source rules, 920 sink rules, and 138 transfer rules, enabling users to adapt and extend them to detect 13 types of vulnerabilities.
526+
527+
To further enhance the user experience, we have also carefully organized the project structure by packages and vulnerability types to ensure clarity and ease of understanding of the rules, allowing users to quickly locate and apply the relevant rules.
528+
529+
530+
=== Organizational structure
531+
532+
The structure of this project is as follows:
533+
534+
[source]
535+
----
536+
Tai-e/src/main/resources/commonly-used-taint-config
537+
├── sink
538+
│ ├── infoleak # contains 141 sinks
539+
│ │ └── java-io
540+
│ └── injection # contains 779 sinks
541+
│ ├── android
542+
│ │ └── sql-injection
543+
│ ├── java
544+
│ │ ├── crlf
545+
│ │ ├── path-traversal
546+
│ │ ├── rce
547+
│ │ └── ...
548+
│ └── ...
549+
├── source
550+
│ ├── infoleak # contains 158 sources
551+
│ │ └── java
552+
│ └── injection # contains 169 sources
553+
│ ├── apache-struts2
554+
│ ├── javax
555+
│ │ ├── javax-portlet
556+
│ │ ├── javax-servlet
557+
│ │ └── javax-swing
558+
│ └── ...
559+
└── transfer # contains 138 transfers about String
560+
----
561+
562+
Specifically, this project firstly categorizes the configuration files into three main categories: sink, source, and transfer.
563+
564+
* `sink` category: Contains sinks configurations files related to information leakage and injection vulnerabilities, further subdivided into two subdirectories:
565+
** `infoleak`: Categorized by package name.
566+
** `injection`: Categorized by vulnerability type.
567+
568+
* `source` category: Contains sources configurations related to information leakage and injection vulnerabilities, further subdivided into two subdirectories:
569+
** `infoleak`: Categorized by package name.
570+
** `injection`: Categorized by package name.
571+
572+
* `transfer` category: Contains transfers.
573+
574+
Additionally, each subdirectory contains a corresponding `README` file that provides a brief overview of the relevant vulnerability types.
575+
576+
=== How to Use it? (An Example)
577+
578+
Users can directly integrate the configuration files from this collection into the <<yaml-configuration-file,Configuration File for the Tai-e taint analysis>>,
579+
or modify and extend them as needed to better meet specific analysis requirements.
580+
581+
Here is an example of how to use the configuration files from this collection.
582+
If the user needs to detect an RCE (Remote Code Execution) injection vulnerability in a Java project using the *Jetty software library*, the following steps can be taken to modify the taint configuration file:
583+
584+
1. Add the source rules related to the *Jetty software library* from the file `source/injection/jetty/jetty-http/jetty-http.yml`.
585+
2. Add the sink rules related to the *RCE type injection vulnerability* from the file `sink/injection/java/rce/command.yml`.
586+
3. Add the transfer rules related to *String type* from the file `transfer/string-transfers.yml`.
587+
588+
After these steps, the taint configuration file will be as follows:
589+
590+
```YAML
591+
source:
592+
- { kind: call, method: "<org.eclipse.jetty.http.HttpCookie: java.lang.String getName()>", index: result, type: "java.lang.String" }
593+
- { kind: call, method: "<org.eclipse.jetty.http.HttpCookie: java.lang.String getValue()>", index: result, type: "java.lang.String" }
594+
- { kind: call, method: "<org.eclipse.jetty.http.HttpCookie: java.lang.String asString()>", index: result, type: "java.lang.String" }
595+
#...
596+
597+
sinks:
598+
- { method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String)>", index: 0 }
599+
- { method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String[])>", index: 0 }
600+
- { method: "<java.lang.Runtime: java.lang.Process exec(java.lang.String, java.lang.String[])>", index: 0 }
601+
#...
602+
603+
transfer:
604+
- { method: "<java.lang.String: java.lang.String substring(int)>", from: base, to: result }
605+
- { method: "<java.lang.String: java.lang.String substring(int,int)>", from: base, to: result }
606+
#...
607+
```
608+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
= Description
2+
3+
- **Overview**:
4+
The sinks in this directory are composed of output-related APIs from the Java standard library's `io` package, primarily including the `write` functions in various output component classes.
5+
6+
- **Common Use Cases**:
7+
These APIs are commonly used to output data carried by parameters to specified locations, such as files or command lines.
8+
9+
- **Security Risks**:
10+
Information Disclosure: Attackers can use these APIs to output sensitive information to a specified location, allowing them to exploit the acquired data for illegal activities such as extortion.
Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
sinks:
2+
- { method: "<java.io.BufferedOutputStream: void write(byte[],int,int)>", index: 0 }
3+
- { method: "<java.io.BufferedOutputStream: void write(int)>", index: 0 }
4+
5+
- { method: "<java.io.BufferedWriter: void write(char[],int,int)>", index: 0 }
6+
- { method: "<java.io.BufferedWriter: void write(int)>", index: 0 }
7+
- { method: "<java.io.BufferedWriter: void write(java.lang.String,int,int)>", index: 0 }
8+
9+
- { method: "<java.io.ByteArrayOutputStream: void write(byte[],int,int)>", index: 0 }
10+
- { method: "<java.io.ByteArrayOutputStream: void write(int)>", index: 0 }
11+
- { method: "<java.io.ByteArrayOutputStream: void writeTo(java.io.OutputStream)>", index: 0 }
12+
13+
- { method: "<java.io.CharArrayWriter: void write(char[],int,int)>", index: 0 }
14+
- { method: "<java.io.CharArrayWriter: void write(int)>", index: 0 }
15+
- { method: "<java.io.CharArrayWriter: void write(java.lang.String,int,int)>", index: 0 }
16+
- { method: "<java.io.CharArrayWriter: void writeTo(java.io.Writer)>", index: 0 }
17+
- { method: "<java.io.CharArrayWriter: java.lang.CharSequence append(java.lang.CharSequence)>", index: 0 }
18+
- { method: "<java.io.CharArrayWriter: java.lang.CharSequence append(java.lang.CharSequence,int,int)>", index: 0 }
19+
- { method: "<java.io.CharArrayWriter: java.lang.CharSequence append(char)>", index: 0 }
20+
21+
22+
- { method: "<java.io.DataOutputStream: void write(int)>", index: 0 }
23+
- { method: "<java.io.DataOutputStream: void write(byte[],int,int)>", index: 0 }
24+
- { method: "<java.io.DataOutputStream: void writeBoolean(boolean)>", index: 0 }
25+
- { method: "<java.io.DataOutputStream: void writeByte(int)>", index: 0 }
26+
- { method: "<java.io.DataOutputStream: void writeBytes(java.lang.String)>", index: 0 }
27+
- { method: "<java.io.DataOutputStream: void writeChar(int)>", index: 0 }
28+
- { method: "<java.io.DataOutputStream: void writeChars(java.lang.String)>", index: 0 }
29+
- { method: "<java.io.DataOutputStream: void writeDouble(double)>", index: 0 }
30+
- { method: "<java.io.DataOutputStream: void writeFloat(float)>", index: 0 }
31+
- { method: "<java.io.DataOutputStream: void writeInt(int)>", index: 0 }
32+
- { method: "<java.io.DataOutputStream: void writeLong(long)>", index: 0 }
33+
- { method: "<java.io.DataOutputStream: void writeShort(int)>", index: 0 }
34+
- { method: "<java.io.DataOutputStream: void writeUTF(java.lang.String)>", index: 0 }
35+
36+
- { method: "<java.io.FileOutputStream: void write(byte[],int,int)>", index: 0 }
37+
- { method: "<java.io.FileOutputStream: void write(int)>", index: 0 }
38+
- { method: "<java.io.FileOutputStream: void write(byte[])>", index: 0 }
39+
40+
- { method: "<java.io.FilterOutputStream: void write(byte[])>", index: 0 }
41+
- { method: "<java.io.FilterOutputStream: void write(byte[],int,int)>", index: 0 }
42+
- { method: "<java.io.FilterOutputStream: void write(int)>", index: 0 }
43+
44+
- { method: "<java.io.ObjectOutputStream: void write(int)>", index: 0 }
45+
- { method: "<java.io.ObjectOutputStream: void write(byte[])>", index: 0 }
46+
- { method: "<java.io.ObjectOutputStream: void write(byte[],int,int)>", index: 0 }
47+
- { method: "<java.io.ObjectOutputStream: void writeBoolean(boolean)>", index: 0 }
48+
- { method: "<java.io.ObjectOutputStream: void writeByte(int)>", index: 0 }
49+
- { method: "<java.io.ObjectOutputStream: void writeBytes(java.lang.String)>", index: 0 }
50+
- { method: "<java.io.ObjectOutputStream: void writeChar(int)>", index: 0 }
51+
- { method: "<java.io.ObjectOutputStream: void writeChars(java.lang.String)>", index: 0 }
52+
- { method: "<java.io.ObjectOutputStream: void writeDouble(double)>", index: 0 }
53+
- { method: "<java.io.ObjectOutputStream: void writeFloat(float)>", index: 0 }
54+
- { method: "<java.io.ObjectOutputStream: void writeInt(int)>", index: 0 }
55+
- { method: "<java.io.ObjectOutputStream: void writeLong(long)>", index: 0 }
56+
- { method: "<java.io.ObjectOutputStream: void writeObject(java.lang.Object)>", index: 0 }
57+
- { method: "<java.io.ObjectOutputStream: void writeShort(int)>", index: 0 }
58+
- { method: "<java.io.ObjectOutputStream: void writeUTF(java.lang.String)>", index: 0 }
59+
- { method: "<java.io.ObjectOutputStream: void defaultWriteObject()>", index: 0 }
60+
- { method: "<java.io.ObjectOutputStream: void writeUnshared(java.lang.Object)>", index: 0 }
61+
62+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,boolean)>", index: 0 }
63+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,byte)>", index: 0 }
64+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,char)>", index: 0 }
65+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,short)>", index: 0 }
66+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,int)>", index: 0 }
67+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,long)>", index: 0 }
68+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,float)>", index: 0 }
69+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,double)>", index: 0 }
70+
- { method: "<java.io.ObjectOutputStream.PutFiled: void put(java.lang.String,java.lang.Object)>", index: 0 }
71+
- { method: "<java.io.ObjectOutputStream.PutFiled: void write(java.io.ObjectOutput)>", index: 0 }
72+
73+
- { method: "<java.io.RandomAccessFile: void write(byte[],int,int)>", index: 0 }
74+
- { method: "<java.io.RandomAccessFile: void write(int)>", index: 0 }
75+
- { method: "<java.io.RandomAccessFile: void write(byte[])>", index: 0 }
76+
77+
- { method: "<java.io.OutputStream: void write(byte[],int,int)>", index: 0 }
78+
- { method: "<java.io.OutputStream: void write(byte[])>", index: 0 }
79+
- { method: "<java.io.OutputStream: void write(int)>", index: 0 }
80+
81+
- { method: "<java.io.OutputStreamWriter: void write(java.lang.String,int,int)>", index: 0 }
82+
- { method: "<java.io.OutputStreamWriter: void write(char[],int,int)>", index: 0 }
83+
- { method: "<java.io.OutputStreamWriter: void write(int)>", index: 0 }
84+
85+
- { method: "<java.io.PipedOutputStream: void write(byte[],int,int)>", index: 0 }
86+
- { method: "<java.io.PipedOutputStream: void write(int)>", index: 0 }
87+
88+
- { method: "<java.io.PipedWriter: void write(char[],int,int)>", index: 0 }
89+
- { method: "<java.io.PipedWriter: void write(int)>", index: 0 }
90+
91+
- { method: "<java.io.PrintStream: void print(boolean)>", index: 0 }
92+
- { method: "<java.io.PrintStream: void print(char)>", index: 0 }
93+
- { method: "<java.io.PrintStream: void print(int)>", index: 0 }
94+
- { method: "<java.io.PrintStream: void print(long)>", index: 0 }
95+
- { method: "<java.io.PrintStream: void print(float)>", index: 0 }
96+
- { method: "<java.io.PrintStream: void print(double)>", index: 0 }
97+
- { method: "<java.io.PrintStream: void print(char[])>", index: 0 }
98+
- { method: "<java.io.PrintStream: void print(java.lang.String)>", index: 0 }
99+
- { method: "<java.io.PrintStream: void print(java.lang.Object)>", index: 0 }
100+
101+
- { method: "<java.io.PrintStream: void println(boolean)>", index: 0 }
102+
- { method: "<java.io.PrintStream: void println(char)>", index: 0 }
103+
- { method: "<java.io.PrintStream: void println(int)>", index: 0 }
104+
- { method: "<java.io.PrintStream: void println(long)>", index: 0 }
105+
- { method: "<java.io.PrintStream: void println(float)>", index: 0 }
106+
- { method: "<java.io.PrintStream: void println(double)>", index: 0 }
107+
- { method: "<java.io.PrintStream: void println(char[])>", index: 0 }
108+
- { method: "<java.io.PrintStream: void println(java.lang.String)>", index: 0 }
109+
- { method: "<java.io.PrintStream: void println(java.lang.Object)>", index: 0 }
110+
111+
- { method: "<java.io.PrintStream: java.io.PrintStream printf(java.util.Locale,java.lang.String,java.lang.Object[])>", index: 2 }
112+
- { method: "<java.io.PrintStream: java.io.PrintStream printf(java.lang.String,java.lang.Object[])>", index: 1 }
113+
114+
- { method: "<java.io.PrintStream: java.io.PrintStream append(java.lang.CharSequence)>", index: 0 }
115+
- { method: "<java.io.PrintStream: java.io.PrintStream append(java.lang.CharSequence,int,int)>", index: 0 }
116+
- { method: "<java.io.PrintStream: java.io.PrintStream append(char)>", index: 0 }
117+
118+
- { method: "<java.io.PrintStream: java.io.PrintStream format(java.lang.String,java.lang.Object[])>", index: 1 }
119+
- { method: "<java.io.PrintStream: java.io.PrintStream format(java.util.Locale,java.lang.String,java.lang.Object[])>", index: 2 }
120+
121+
- { method: "<java.io.PrintStream: void write(int)>", index: 0 }
122+
- { method: "<java.io.PrintStream: void write(byte[],int,int)>", index: 0 }
123+
124+
125+
- { method: "<java.io.PrintWriter: void print(boolean)>", index: 0 }
126+
- { method: "<java.io.PrintWriter: void print(char)>", index: 0 }
127+
- { method: "<java.io.PrintWriter: void print(int)>", index: 0 }
128+
- { method: "<java.io.PrintWriter: void print(long)>", index: 0 }
129+
- { method: "<java.io.PrintWriter: void print(float)>", index: 0}
130+
131+
- { method: "<java.io.PrintWriter: void write(char[],int,int)>", index: 0 }
132+
- { method: "<java.io.PrintWriter: void write(int)>", index: 0 }
133+
- { method: "<java.io.PrintWriter: void write(java.lang.String,int,int)>", index: 0 }
134+
- { method: "<java.io.PrintWriter: void write(java.lang.String)>", index: 0 }
135+
- { method: "<java.io.PrintWriter: void write(char[])>", index: 0 }
136+
137+
- { method: "<java.io.PrintWriter: void println(boolean)>", index: 0 }
138+
- { method: "<java.io.PrintWriter: void println(char)>", index: 0 }
139+
- { method: "<java.io.PrintWriter: void println(char[])>", index: 0 }
140+
- { method: "<java.io.PrintWriter: void println(double)>", index: 0 }
141+
- { method: "<java.io.PrintWriter: void println(float)>", index: 0 }
142+
- { method: "<java.io.PrintWriter: void println(int)>", index: 0 }
143+
- { method: "<java.io.PrintWriter: void println(long)>", index: 0 }
144+
- { method: "<java.io.PrintWriter: void println(java.lang.Object)>", index: 0 }
145+
- { method: "<java.io.PrintWriter: void println(java.lang.String)>", index: 0 }
146+
147+
- { method: "<java.io.PrintWriter: java.io.PrintWriter append(java.lang.CharSequence)>", index: 0 }
148+
- { method: "<java.io.PrintWriter: java.io.PrintWriter append(java.lang.CharSequence,int,int)>", index: 0 }
149+
- { method: "<java.io.PrintWriter: java.io.PrintWriter append(char)>", index: 0 }
150+
151+
- { method: "<java.io.PrintWrite: java.io.PrintWrite printf(java.util.Locale,java.lang.String,java.lang.Object[])>", index: 2 }
152+
- { method: "<java.io.PrintWrite: java.io.PrintWrite printf(java.lang.String,java.lang.Object[])>", index: 1 }
153+
154+
- { method: "<java.io.StringWriter: java.io.StringWriter append(java.lang.CharSequence)>", index: 0 }
155+
- { method: "<java.io.StringWriter: java.io.StringWriter append(java.lang.CharSequence,int,int)>", index: 0 }
156+
- { method: "<java.io.StringWriter: java.io.StringWriter append(char)>", index: 0 }
157+
158+
- { method: "<java.io.StringWriter: void write(char[],int,int)>", index: 0 }
159+
- { method: "<java.io.StringWriter: void write(int)>", index: 0 }
160+
- { method: "<java.io.StringWriter: void write(java.lang.String,int,int)>", index: 0 }
161+
- { method: "<java.io.StringWriter: void write(java.lang.String)>", index: 0 }
162+
- { method: "<java.io.StringWriter: void write(char[])>", index: 0 }
163+
164+
- { method: "<java.io.Writer: java.io.Writer append(java.lang.CharSequence)>", index: 0 }
165+
- { method: "<java.io.Writer: java.io.Writer append(java.lang.CharSequence,int,int)>", index: 0 }
166+
- { method: "<java.io.Writer: java.io.Writer append(char)>", index: 0 }
167+
168+
- { method: "<java.io.Writer: void write(char[],int,int)>", index: 0 }
169+
- { method: "<java.io.Writer: void write(int)>", index: 0 }
170+
- { method: "<java.io.Writer: void write(java.lang.String,int,int)>", index: 0 }
171+
- { method: "<java.io.Writer: void write(java.lang.String)>", index: 0 }
172+
- { method: "<java.io.Writer: void write(char[])>", index: 0 }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
sinks:
2+
- { method: "<android.content.ContentProvider: android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String[],java.lang.String,java.lang.String)>", index: 2 }
3+
- { method: "<android.content.ContentProvider: android.database.Cursor query(android.net.Uri,java.lang.String[],java.lang.String[],java.lang.String,java.lang.String,android.os.CancellationSignal)>", index: 3 }
4+
- { method: "<android.content.ContentProvider: int delete(android.net.Uri,java.lang.String,java.lang.String[])>", index: 1 }
5+
- { method: "<android.content.ContentProvider: int update(android.net.Uri,android.content.ContentValues,java.lang.String,java.lang.String[])>", index: 1 }
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
sinks:
2+
- { method: "<android.database.DatabaseUtils: long longForQuery(android.database.sqlite.SQLiteDatabase,java.lang.String,java.lang.String[])>", index: 1 }
3+
- { method: "<android.database.DatabaseUtils: java.lang.String stringForQuery(android.database.sqlite.SQLiteDatabase,java.lang.String,java.lang.String[])>", index: 1 }
4+
- { method: "<android.database.DatabaseUtils: android.os.ParcelFileDescriptor blobFileDescriptorForQuery(android.database.sqlite.SQLiteDatabase,java.lang.String,java.lang.String[])>", index: 1 }
5+
- { method: "<android.database.DatabaseUtils: void createDbFromSqlStatements(android.content.Context,java.lang.String,int,java.lang.String)>", index: 0 }
6+
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
= Description
2+
3+
- **Overview**:
4+
The sinks in this directory consist of Android database SQL-related APIs, including but not limited to `query`, `update`, `delete`, and other methods. Their main functionality is to perform database queries and update operations.
5+
6+
- **Common Use Cases**:
7+
These APIs are commonly used for handling user-inputted data for queries, data insertion, data updates, data deletion, and SQL statement execution. Users typically have some level of control over the parameters.
8+
9+
- **Security Risks**:
10+
SQL Injection: Attackers can exploit these APIs by constructing malicious input to inject SQL commands, thereby gaining control over the database.

0 commit comments

Comments
 (0)