@@ -13,7 +13,12 @@ module InsecureDownload {
13
13
/**
14
14
* A data flow source for download of sensitive file through insecure connection.
15
15
*/
16
- abstract class Source extends DataFlow:: Node { }
16
+ abstract class Source extends DataFlow:: Node {
17
+ /**
18
+ * Gets a flow-label for this source.
19
+ */
20
+ abstract DataFlow:: FlowLabel getALabel ( ) ;
21
+ }
17
22
18
23
/**
19
24
* A data flow sink for download of sensitive file through insecure connection.
@@ -23,28 +28,67 @@ module InsecureDownload {
23
28
* Gets the call that downloads the sensitive file.
24
29
*/
25
30
abstract DataFlow:: Node getDownloadCall ( ) ;
31
+
32
+ /**
33
+ * Gets a flow-label where this sink is vulnerable.
34
+ */
35
+ abstract DataFlow:: FlowLabel getALabel ( ) ;
26
36
}
27
37
28
38
/**
29
39
* A sanitizer for download of sensitive file through insecure connection.
30
40
*/
31
41
abstract class Sanitizer extends DataFlow:: Node { }
32
42
43
+ /**
44
+ * Flow-labels for reasoning about download of sensitive file through insecure connection.
45
+ */
46
+ module Label {
47
+ /**
48
+ * A flow-label for file URLs that are both sensitive and downloaded over an insecure connection.
49
+ */
50
+ class SensitiveInsecureURL extends DataFlow:: FlowLabel {
51
+ SensitiveInsecureURL ( ) { this = "sensitiveInsecure" }
52
+ }
53
+
54
+ /**
55
+ * A flow-label for a URL that is downloaded over an insecure connection.
56
+ */
57
+ class InsecureURL extends DataFlow:: FlowLabel {
58
+ InsecureURL ( ) { this = "insecure" }
59
+ }
60
+ }
61
+
33
62
/**
34
63
* A HTTP or FTP URL that refers to a file with a sensitive file extension,
35
64
* seen as a source for download of sensitive file through insecure connection.
36
65
*/
37
66
class SensitiveFileUrl extends Source {
67
+ string str ;
68
+
38
69
SensitiveFileUrl ( ) {
39
- exists ( string str | str = this .getStringValue ( ) |
40
- str .regexpMatch ( "http://.*|ftp://.*" ) and
41
- exists ( string suffix | suffix = unsafeExtension ( ) |
42
- str .suffix ( str .length ( ) - suffix .length ( ) - 1 ) .toLowerCase ( ) = "." + suffix
43
- )
44
- )
70
+ str = this .getStringValue ( ) and
71
+ str .regexpMatch ( "http://.*|ftp://.*" )
72
+ }
73
+
74
+ override DataFlow:: FlowLabel getALabel ( ) {
75
+ result instanceof Label:: InsecureURL
76
+ or
77
+ hasUnsafeExtension ( str ) and
78
+ result instanceof Label:: SensitiveInsecureURL
45
79
}
46
80
}
47
81
82
+ /**
83
+ * Holds if `str` is a string that ends with an unsafe file extension.
84
+ */
85
+ bindingset [ str]
86
+ predicate hasUnsafeExtension ( string str ) {
87
+ exists ( string suffix | suffix = unsafeExtension ( ) |
88
+ str .suffix ( str .length ( ) - suffix .length ( ) - 1 ) .toLowerCase ( ) = "." + suffix
89
+ )
90
+ }
91
+
48
92
/**
49
93
* Gets a file-extension that can potentially be dangerous.
50
94
*
@@ -58,13 +102,48 @@ module InsecureDownload {
58
102
59
103
/**
60
104
* A url downloaded by a client-request, seen as a sink for download of
61
- * sensitive file through insecure connection.a
105
+ * sensitive file through insecure connection.
62
106
*/
63
107
class ClientRequestURL extends Sink {
64
108
ClientRequest request ;
65
109
66
110
ClientRequestURL ( ) { this = request .getUrl ( ) }
67
111
68
112
override DataFlow:: Node getDownloadCall ( ) { result = request }
113
+
114
+ override DataFlow:: FlowLabel getALabel ( ) {
115
+ result instanceof Label:: SensitiveInsecureURL
116
+ or
117
+ hasUnsafeExtension ( request .getASavePath ( ) .getStringValue ( ) ) and
118
+ result instanceof Label:: InsecureURL
119
+ }
120
+ }
121
+
122
+ /**
123
+ * Gets a node for the response from `request`, type-tracked using `t`.
124
+ */
125
+ DataFlow:: SourceNode clientRequestResponse ( DataFlow:: TypeTracker t , ClientRequest request ) {
126
+ t .start ( ) and
127
+ result = request .getAResponseDataNode ( )
128
+ or
129
+ exists ( DataFlow:: TypeTracker t2 | result = clientRequestResponse ( t2 , request ) .track ( t2 , t ) )
130
+ }
131
+
132
+ /**
133
+ * A url that is downloaded through an insecure connection, where the result ends up being saved to a sensitive location.
134
+ */
135
+ class FileWriteSink extends Sink {
136
+ ClientRequest request ;
137
+ FileSystemWriteAccess write ;
138
+
139
+ FileWriteSink ( ) {
140
+ this = request .getUrl ( ) and
141
+ clientRequestResponse ( DataFlow:: TypeTracker:: end ( ) , request ) .flowsTo ( write .getADataNode ( ) ) and
142
+ hasUnsafeExtension ( write .getAPathArgument ( ) .getStringValue ( ) )
143
+ }
144
+
145
+ override DataFlow:: FlowLabel getALabel ( ) { result instanceof Label:: InsecureURL }
146
+
147
+ override DataFlow:: Node getDownloadCall ( ) { result = request }
69
148
}
70
149
}
0 commit comments