@@ -27,77 +27,102 @@ module ZipSlip {
27
27
}
28
28
29
29
override predicate isSource ( DataFlow:: Node source ) {
30
- exists ( PropertyAccess pa |
31
- source .asExpr ( ) = archiveFullName ( pa )
32
- )
30
+ source instanceof Source
33
31
}
34
32
35
33
override predicate isSink ( DataFlow:: Node sink ) {
36
- exists ( MethodCall mc |
37
- sink .asExpr ( ) = compressionExtractToFileArgument ( mc ) or
38
- sink .asExpr ( ) = fileOpenArgument ( mc )
39
- )
40
- or
41
- exists ( ObjectCreation oc |
42
- sink .asExpr ( ) = streamConstructorArgument ( oc ) or
43
- sink .asExpr ( ) = fileInfoConstructorArgument ( oc )
44
- )
34
+ sink instanceof Sink
45
35
}
46
36
47
37
override predicate isSanitizer ( DataFlow:: Node node ) {
48
- exists ( MethodCall mc |
49
- node .asExpr ( ) = fileNameExtraction ( mc ) or
50
- node .asExpr ( ) = stringCheck ( mc )
51
- )
38
+ node instanceof Sanitizer
52
39
}
53
40
}
54
41
55
- // access to full name of the archive item
56
- Expr archiveFullName ( PropertyAccess pa ) {
57
- pa .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.Compression.ZipArchiveEntry" ) and
58
- pa .getTarget ( ) .getName ( ) = "FullName" and
59
- result = pa
42
+ /** An access to the `FullName` property of a `ZipArchiveEntry`. */
43
+ class ArchiveFullNameSource extends Source {
44
+ ArchiveFullNameSource ( ) {
45
+ exists ( PropertyAccess pa |
46
+ this .asExpr ( ) = pa |
47
+ pa .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.Compression.ZipArchiveEntry" ) and
48
+ pa .getTarget ( ) .getName ( ) = "FullName"
49
+ )
50
+ }
60
51
}
61
52
62
- // argument to extract to file extension method
63
- Expr compressionExtractToFileArgument ( MethodCall mc ) {
64
- mc .getTarget ( ) .hasQualifiedName ( "System.IO.Compression.ZipFileExtensions" , "ExtractToFile" ) and
65
- result = mc .getArgumentForName ( "destinationFileName" )
53
+ /** An argument to the `ExtractToFile` extension method. */
54
+ class ExtractToFileArgSink extends Sink {
55
+ ExtractToFileArgSink ( ) {
56
+ exists ( MethodCall mc |
57
+ mc .getTarget ( ) .hasQualifiedName ( "System.IO.Compression.ZipFileExtensions" , "ExtractToFile" ) and
58
+ this .asExpr ( ) = mc .getArgumentForName ( "destinationFileName" )
59
+ )
60
+ }
66
61
}
67
62
68
- // File Stream created from tainted file name through File.Open/File.Create
69
- Expr fileOpenArgument ( MethodCall mc ) {
70
- (
71
- mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "Open" ) or
72
- mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "OpenWrite" ) or
73
- mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "Create" )
74
- ) and
75
- result = mc .getArgumentForName ( "path" )
63
+ /** A path argument to a `File.Open`, `File.OpenWrite` or `File.Create` method call. */
64
+ class FileOpenArgSink extends Sink {
65
+ FileOpenArgSink ( ) {
66
+ exists ( MethodCall mc |
67
+ mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "Open" ) or
68
+ mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "OpenWrite" ) or
69
+ mc .getTarget ( ) .hasQualifiedName ( "System.IO.File" , "Create" ) |
70
+ this .asExpr ( ) = mc .getArgumentForName ( "path" )
71
+ )
72
+ }
76
73
}
77
74
78
- // File Stream created from tainted file name passed directly to the constructor
79
- Expr streamConstructorArgument ( ObjectCreation oc ) {
80
- oc .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.FileStream" ) and
81
- result = oc .getArgumentForName ( "path" )
75
+ /** A path argument to a call to the `FileStream` constructor. */
76
+ class FileStreamArgSink extends Sink {
77
+ FileStreamArgSink ( ) {
78
+ exists ( ObjectCreation oc |
79
+ oc .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.FileStream" ) |
80
+ this .asExpr ( ) = oc .getArgumentForName ( "path" )
81
+ )
82
+ }
82
83
}
83
84
84
- // constructor to FileInfo can take tainted file name and subsequently be used to open file stream
85
- Expr fileInfoConstructorArgument ( ObjectCreation oc ) {
86
- oc .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.FileInfo" ) and
87
- result = oc .getArgumentForName ( "fileName" )
85
+ /**
86
+ * A path argument to a call to the `FileStream` constructor.
87
+ *
88
+ * This constructor can accept a tainted file name and subsequently be used to open a file stream.
89
+ */
90
+ class FileInfoArgSink extends Sink {
91
+ FileInfoArgSink ( ) {
92
+ exists ( ObjectCreation oc |
93
+ oc .getTarget ( ) .getDeclaringType ( ) .hasQualifiedName ( "System.IO.FileInfo" ) |
94
+ this .asExpr ( ) = oc .getArgumentForName ( "fileName" )
95
+ )
96
+ }
88
97
}
89
- // extracting just file name, not the full path
90
- Expr fileNameExtraction ( MethodCall mc ) {
91
- mc .getTarget ( ) .hasQualifiedName ( "System.IO.Path" , "GetFileName" ) and
92
- result = mc .getAnArgument ( )
98
+
99
+ /**
100
+ * An argument to GetFileName.
101
+ *
102
+ * This is considered a sanitizer because it extracts the just the file name, not the full path.
103
+ */
104
+ class GetFileNameSanitizer extends Sanitizer {
105
+ GetFileNameSanitizer ( ) {
106
+ exists ( MethodCall mc |
107
+ mc .getTarget ( ) .hasQualifiedName ( "System.IO.Path" , "GetFileName" ) |
108
+ this .asExpr ( ) = mc .getAnArgument ( )
109
+ )
110
+ }
93
111
}
94
112
95
- // Checks the string for relative path, or checks the destination folder for whitelisted/target path, etc.
96
- Expr stringCheck ( MethodCall mc ) {
97
- (
98
- mc .getTarget ( ) .hasQualifiedName ( "System.String" , "StartsWith" ) or
99
- mc .getTarget ( ) .hasQualifiedName ( "System.String" , "Substring" )
100
- ) and
101
- result = mc .getQualifier ( )
113
+ /**
114
+ * A qualifier in a call to `StartsWith` or `Substring` string method.
115
+ *
116
+ * A call to a String method such as `StartsWith` or `Substring` can indicate a check for a
117
+ * relative path, or a check against the destination folder for whitelisted/target path, etc.
118
+ */
119
+ class StringCheckSanitizer extends Sanitizer {
120
+ StringCheckSanitizer ( ) {
121
+ exists ( MethodCall mc |
122
+ mc .getTarget ( ) .hasQualifiedName ( "System.String" , "StartsWith" ) or
123
+ mc .getTarget ( ) .hasQualifiedName ( "System.String" , "Substring" ) |
124
+ this .asExpr ( ) = mc .getQualifier ( )
125
+ )
126
+ }
102
127
}
103
128
}
0 commit comments