@@ -45,7 +45,7 @@ public String getFileContent1(@RequestParam(name="fileName") String fileName) {
45
45
//GOOD: Get resource from ClassPathResource with input path validation
46
46
public String getFileContent1a (@ RequestParam (name ="fileName" ) String fileName ) {
47
47
String result = null ;
48
- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
48
+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
49
49
ClassPathResource clr = new ClassPathResource (fileName );
50
50
char [] buffer = new char [4096 ];
51
51
StringBuilder out = new StringBuilder ();
@@ -86,9 +86,9 @@ public String getFileContent2(@RequestParam(name="fileName") String fileName) {
86
86
public String getFileContent2a (@ RequestParam (name ="fileName" ) String fileName ) {
87
87
String content = null ;
88
88
89
- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
89
+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
90
90
try {
91
- File file = ResourceUtils .getFile (fileName );
91
+ File file = ResourceUtils .getFile (fileName );
92
92
//Read File Content
93
93
content = new String (Files .readAllBytes (file .toPath ()));
94
94
} catch (IOException ie ) {
@@ -132,7 +132,7 @@ public String getFileContent3(@RequestParam(name="fileName") String fileName) {
132
132
public String getFileContent3a (@ RequestParam (name ="fileName" ) String fileName ) {
133
133
String content = null ;
134
134
135
- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
135
+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
136
136
try {
137
137
Resource resource = resourceLoader .getResource (fileName );
138
138
@@ -150,121 +150,4 @@ public String getFileContent3a(@RequestParam(name="fileName") String fileName) {
150
150
}
151
151
return content ;
152
152
}
153
-
154
- /**
155
- * Check whether the given path contains invalid escape sequences.
156
- * @param path the path to validate
157
- * @return {@code true} if the path is invalid, {@code false} otherwise
158
- * @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
159
- */
160
- private boolean isInvalidEncodedPath (String path ) {
161
- if (path .contains ("%" )) {
162
- try {
163
- // Use URLDecoder (vs UriUtils) to preserve potentially decoded UTF-8 chars
164
- String decodedPath = URLDecoder .decode (path , "UTF-8" );
165
- if (isInvalidPath (decodedPath )) {
166
- return true ;
167
- }
168
- decodedPath = processPath (decodedPath );
169
- if (isInvalidPath (decodedPath )) {
170
- return true ;
171
- }
172
- } catch (IllegalArgumentException | UnsupportedEncodingException ex ) {
173
- // Should never happen...
174
- }
175
- }
176
- return false ;
177
- }
178
-
179
- /**
180
- * Process the given resource path.
181
- * <p>The default implementation replaces:
182
- * <ul>
183
- * <li>Backslash with forward slash.
184
- * <li>Duplicate occurrences of slash with a single slash.
185
- * <li>Any combination of leading slash and control characters (00-1F and 7F)
186
- * with a single "/" or "". For example {@code " / // foo/bar"}
187
- * becomes {@code "/foo/bar"}.
188
- * </ul>
189
- * @since 3.2.12
190
- * @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
191
- */
192
- protected String processPath (String path ) {
193
- path = StringUtils .replace (path , "\\ " , "/" );
194
- path = cleanDuplicateSlashes (path );
195
- return cleanLeadingSlash (path );
196
- }
197
-
198
- /** @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799 **/
199
- private String cleanDuplicateSlashes (String path ) {
200
- StringBuilder sb = null ;
201
- char prev = 0 ;
202
- for (int i = 0 ; i < path .length (); i ++) {
203
- char curr = path .charAt (i );
204
- try {
205
- if ((curr == '/' ) && (prev == '/' )) {
206
- if (sb == null ) {
207
- sb = new StringBuilder (path .substring (0 , i ));
208
- }
209
- continue ;
210
- }
211
- if (sb != null ) {
212
- sb .append (path .charAt (i ));
213
- }
214
- } finally {
215
- prev = curr ;
216
- }
217
- }
218
- return sb != null ? sb .toString () : path ;
219
- }
220
-
221
- /** @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799 **/
222
- private String cleanLeadingSlash (String path ) {
223
- boolean slash = false ;
224
- for (int i = 0 ; i < path .length (); i ++) {
225
- if (path .charAt (i ) == '/' ) {
226
- slash = true ;
227
- }
228
- else if (path .charAt (i ) > ' ' && path .charAt (i ) != 127 ) {
229
- if (i == 0 || (i == 1 && slash )) {
230
- return path ;
231
- }
232
- return (slash ? "/" + path .substring (i ) : path .substring (i ));
233
- }
234
- }
235
- return (slash ? "/" : "" );
236
- }
237
-
238
- /**
239
- * Identifies invalid resource paths. By default rejects:
240
- * <ul>
241
- * <li>Paths that contain "WEB-INF" or "META-INF"
242
- * <li>Paths that contain "../" after a call to
243
- * {@link org.springframework.util.StringUtils#cleanPath}.
244
- * <li>Paths that represent a {@link org.springframework.util.ResourceUtils#isUrl
245
- * valid URL} or would represent one after the leading slash is removed.
246
- * </ul>
247
- * <p><strong>Note:</strong> this method assumes that leading, duplicate '/'
248
- * or control characters (e.g. white space) have been trimmed so that the
249
- * path starts predictably with a single '/' or does not have one.
250
- * @param path the path to validate
251
- * @return {@code true} if the path is invalid, {@code false} otherwise
252
- * @since 3.0.6
253
- * @see Referenced code for path validation fix in https://github.com/mpgn/CVE-2019-3799
254
- */
255
- protected boolean isInvalidPath (String path ) {
256
- if (path .contains ("WEB-INF" ) || path .contains ("META-INF" )) {
257
- return true ;
258
- }
259
- if (path .contains (":/" )) {
260
- String relativePath = (path .charAt (0 ) == '/' ? path .substring (1 ) : path );
261
- if (ResourceUtils .isUrl (relativePath ) || relativePath .startsWith ("url:" )) {
262
- return true ;
263
- }
264
- }
265
- if (path .contains (".." ) && StringUtils .cleanPath (path ).contains ("../" )) {
266
- return true ;
267
- }
268
- return false ;
269
- }
270
153
}
0 commit comments