Changeset 13082 in project


Ignore:
Timestamp:
01/25/09 17:43:52 (11 years ago)
Author:
sjamaan
Message:

Add checks for traversal attacks

Location:
release/4/spiffy/trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • release/4/spiffy/trunk/spiffy.scm

    r13054 r13082  
    5050
    5151(import chicken scheme extras ports files data-structures)
    52 (require-extension srfi-1 srfi-18 tcp regex posix
     52(require-extension srfi-1 srfi-13 srfi-18 tcp regex posix
    5353                   intarweb uri-common sendfile matchable)
    5454
     
    239239  (let ((path (make-pathname (root-path) filename)))
    240240    (with-headers `((content-length ,(file-size path))
    241                     (content-type ,(extension->mime-type (pathname-extension filename))))
     241                    (content-type ,(extension->mime-type
     242                                    (pathname-extension filename))))
    242243      (lambda ()
    243244        (write-logged-response)
     
    263264                          (index-files))))
    264265    (if index-page
    265         (process-entry (make-pathname path index-page) '())
     266        (process-entry path index-page '())
    266267        ((handle-directory) (make-pathname "/" path)))))
    267268
     
    282283        (continue))))
    283284
    284 (define (process-entry current-path remaining-path)
    285   (let ((path (make-pathname (root-path) current-path)))
     285;; Is the file impossible to be requested directly?
     286;;
     287;; Any file that the the filesystem is incapable of representing is
     288;; considered impossible to request.  This includes files with a name that
     289;; includes a slash, and "." and ".." because they are special files.
     290;; If this is requested, it's probably an encoded traversal attack
     291(define (impossible-filename? name)
     292  (or (string=? name ".") (string=? name "..") (string-index name #\/)))
     293
     294(define (process-entry previous-path fragment remaining-path)
     295  (let* ((current-path (make-pathname previous-path fragment))
     296         (full-path (make-pathname (root-path) current-path)))
    286297    (cond
    287298     ;; TODO Check if there's a registered URI-handler first
    288      ((directory? path)
    289       (apply-access-file path
    290        (lambda ()
    291          (match remaining-path
    292                 (()    (redirect-directory-root (make-pathname "/" current-path)))
    293                 (("")  (process-directory current-path))
    294                 (else  (process-entry (make-pathname current-path (car remaining-path))
    295                                       (cdr remaining-path)))))))
    296      ((file-exists? path)
     299     ((impossible-filename? fragment)
     300      ((handle-not-found) (make-pathname "/" current-path)))
     301     ((directory? full-path)
     302      (apply-access-file full-path
     303                         (lambda ()
     304                           (match remaining-path
     305                                  (()    (redirect-directory-root (make-pathname "/" current-path)))
     306                                  (("")  (process-directory current-path))
     307                                  (else  (process-entry current-path
     308                                                        (car remaining-path)
     309                                                        (cdr remaining-path)))))))
     310     ((file-exists? full-path)
    297311      (parameterize ((current-pathinfo remaining-path)
    298312                     (current-file (make-pathname "/" current-path)))
    299313        ((handle-file) (current-file)))) ;; hmm, not too useful
    300      (else ((handle-not-found) (list "/" current-path))))))
     314     (else ((handle-not-found) (make-pathname "/" current-path))))))
    301315
    302316;; Determine the vhost and port to use. This follows RFC 2616, section 5.2:
     
    362376                                                   (string-match h host))))))
    363377                    (if handler
    364                         (handler (lambda () (process-entry "" (cdr path))))
     378                        (handler (lambda () (process-entry "" "" (cdr path))))
    365379                        ;; Is this ok?
    366380                        ((handle-not-found) path)))
  • release/4/spiffy/trunk/tests/run.scm

    r13054 r13082  
    7373(test "break out of vhost webroot gives index of root" `(200 ,index-subsubdir) (fetch-file "/subsubdir/../../subsubdir/" "subdir-host"))
    7474(test "break out of vhost webroot fails" `(404 ,NOT-FOUND) (fetch-file "../hello.txt" "subdir-host"))
     75(test "encoded break out of vhost webroot fails" `(404 ,NOT-FOUND) (fetch-file "%2e%2e%2fhello.txt" "subdir-host"))
    7576(test-end "path normalization")
    7677
Note: See TracChangeset for help on using the changeset viewer.