@@ -27,77 +27,102 @@ module ZipSlip {
2727 }
2828
2929 override predicate isSource ( DataFlow:: Node source ) {
30- exists ( PropertyAccess pa |
31- source .asExpr ( ) = archiveFullName ( pa )
32- )
30+ source instanceof Source
3331 }
3432
3533 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
4535 }
4636
4737 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
5239 }
5340 }
5441
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+ }
6051 }
6152
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+ }
6661 }
6762
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+ }
7673 }
7774
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+ }
8283 }
8384
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+ }
8897 }
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+ }
93111 }
94112
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+ }
102127 }
103128}
0 commit comments