CVE-2022-25358 (published 2022-02-18T22:15Z)

A ..%2F path traversal vulnerability exists in the path handler of awful-salmonella-tar before 0.0.4. Attackers can only list directories (not read files). This occurs because the safe-path? Scheme predicate is not used for directories.

Severity: MEDIUM
CVSS v2 base score: 5.0 (AV:N/AC:L/Au:N/C:P/I:N/A:N)
CVSS v3 base score: 5.3, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:N)

Weakness information:
cwe_id: CWE-22
cwe_name: Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
description: The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
extended_description: 
            Many file operations are intended to take place within a restricted directory. By using special elements such as ".." and "/" separators, attackers can escape outside of the restricted location to access files or directories that are elsewhere on the system. One of the most common special elements is the "../" sequence, which in most modern operating systems is interpreted as the parent directory of the current location. This is referred to as relative path traversal. Path traversal also covers the use of absolute pathnames such as "/usr/local/bin" to access unexpected files. This is referred to as absolute path traversal.
         
         

Fix information:
repo_url: https://github.com/mario-goulart/awful-salmonella-tar
commit_details: repo_url: https://github.com/mario-goulart/awful-salmonella-tar
author: Mario Domenech Goulart
author_date: 2022-02-13 00:04:19+01:00
msg: Fix path traversal vulnerability

This change fixes a path traversal vulnerability that would allow
attackers to navigate through the filesystem of the server (provided
execute access to directories for the user running the web server).
Attackers could only list the contents of directories -- not download
files.

The vulnerability was caused by the lack of a check for the validity
requested paths when handling directories, notably when `..%2F' (`../`
URL-encoded) was present in requested paths.

Background:

awful-samonella-tar is implemented using awful [0].  Awful is
implemented on top of spiffy [1], and overrides the
`(handle-not-found)` parameter to map URL paths to procedures.  Spiffy
takes some precautions regarding dealing with malicious paths when it
handles static files.  Code that uses spiffy to implement generation
of dynamic content (like awful does), must take their own precautions.

awful-salmonella-tar uses a procedure (`safe-path?') with a relatively
strict policy to allow access to files, but it was not being used to
validate access to directories, and that was causing the
vulnerability.

This change applies `safe-path?` to all requested paths.

Thanks to Chris Brannon for responsibly reporting this issue.

[0] https://wiki.call-cc.org/eggref/5/awful
[1] https://wiki.call-cc.org/eggref/5/spiffy
repository: repo_url: https://github.com/mario-goulart/awful-salmonella-tar
repo_name: mario-goulart/awful-salmonella-tar
repo_language: Scheme
owner: mario-goulart
file_changes: filename: awful-salmonella-tar.scm
change_type: ModificationType.MODIFY
diff: @@ -231,30 +231,34 @@
       (lambda (req-path)
         (let ((fs-path (make-pathname (list (root-path)
                                             (salmonella-reports-dir))
-                                      req-path)))
-          (if (directory? fs-path)
-              (render-dir req-path fs-path)
-              (lambda ()
-                (let ((not-found (lambda ()
-                                   (send-status 'not-found))))
-                  (handle-exceptions exn
-                    (not-found)
-                    (cond ((equal? (pathname-strip-directory req-path)
-                                   (salmonella-report-dir))
-                           (redirect-to (string-append req-path "/")))
-                          ((equal? (pathname-strip-directory (string-chomp req-path "/"))
-                                   (salmonella-report-dir))
-                           (cond ((tar-get (make-pathname req-path (index-file)))
-                                  => send-file-from-cache)
-                                 (else (not-found))))
-                          ((tar-get req-path) => send-file-from-cache)
-                          (else
-                           (if (file-exists? (make-pathname (list (root-path)
-                                                                  (salmonella-reports-dir))
-                                                            req-path))
-                               (parameterize ((root-path (salmonella-reports-dir)))
-                                 (send-file req-path))
-                               (not-found)))))))))))
+                                      req-path))
+              (not-found (lambda ()
+                           (send-status 'not-found))))
+          (cond ((not (safe-path? req-path))
+                 (lambda ()
+                   (not-found)))
+                ((directory? fs-path)
+                 (render-dir req-path fs-path))
+                (else
+                 (lambda ()
+                   (handle-exceptions exn
+                     (not-found)
+                     (cond ((equal? (pathname-strip-directory req-path)
+                                    (salmonella-report-dir))
+                            (redirect-to (string-append req-path "/")))
+                           ((equal? (pathname-strip-directory (string-chomp req-path "/"))
+                                    (salmonella-report-dir))
+                            (cond ((tar-get (make-pathname req-path (index-file)))
+                                   => send-file-from-cache)
+                                  (else (not-found))))
+                           ((tar-get req-path) => send-file-from-cache)
+                           (else
+                            (if (file-exists? (make-pathname (list (root-path)
+                                                                   (salmonella-reports-dir))
+                                                             req-path))
+                                (parameterize ((root-path (salmonella-reports-dir)))
+                                  (send-file req-path))
+                                (not-found)))))))))))
     ) ;; end define-app
   ) ;; end awful-salmonella-tar
 ) ;; end module

programming_language: Python