@@ -45,7 +45,7 @@ public String getFileContent1(@RequestParam(name="fileName") String fileName) {
4545 //GOOD: Get resource from ClassPathResource with input path validation
4646 public String getFileContent1a (@ RequestParam (name ="fileName" ) String fileName ) {
4747 String result = null ;
48- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
48+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
4949 ClassPathResource clr = new ClassPathResource (fileName );
5050 char [] buffer = new char [4096 ];
5151 StringBuilder out = new StringBuilder ();
@@ -86,9 +86,9 @@ public String getFileContent2(@RequestParam(name="fileName") String fileName) {
8686 public String getFileContent2a (@ RequestParam (name ="fileName" ) String fileName ) {
8787 String content = null ;
8888
89- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
89+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
9090 try {
91- File file = ResourceUtils .getFile (fileName );
91+ File file = ResourceUtils .getFile (fileName );
9292 //Read File Content
9393 content = new String (Files .readAllBytes (file .toPath ()));
9494 } catch (IOException ie ) {
@@ -132,7 +132,7 @@ public String getFileContent3(@RequestParam(name="fileName") String fileName) {
132132 public String getFileContent3a (@ RequestParam (name ="fileName" ) String fileName ) {
133133 String content = null ;
134134
135- if (! isInvalidPath ( fileName ) && !isInvalidEncodedPath ( fileName )) {
135+ if (fileName . startsWith ( "/safe_dir" ) && !fileName . contains ( ".." )) {
136136 try {
137137 Resource resource = resourceLoader .getResource (fileName );
138138
@@ -150,121 +150,4 @@ public String getFileContent3a(@RequestParam(name="fileName") String fileName) {
150150 }
151151 return content ;
152152 }
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- }
270153}
0 commit comments