Browse Source

Prevent content_dir breakouts using malicious request URLs

It's appalling that nobody (including me!) thought about that!
Daniel Rudolf 9 years ago
parent
commit
9e2604af85
1 changed files with 22 additions and 1 deletions
  1. 22 1
      lib/Pico.php

+ 22 - 1
lib/Pico.php

@@ -556,7 +556,28 @@ class Pico
         if (empty($this->requestUrl)) {
             $this->requestFile = $this->getConfig('content_dir') . 'index' . $this->getConfig('content_ext');
         } else {
-            $this->requestFile = $this->getConfig('content_dir') . $this->requestUrl;
+            // prevent content_dir breakouts using malicious request URLs
+            // we don't use realpath() here because we neither want to check for file existance
+            // nor prohibit symlinks which intentionally point to somewhere outside the content_dir
+            // it is STRONGLY RECOMMENDED to use open_basedir - always, not just with Pico!
+            $requestUrl = str_replace('\\', '/', $this->requestUrl);
+            $requestUrlParts = explode('/', $requestUrl);
+
+            $requestFileParts = array();
+            foreach ($requestUrlParts as $requestUrlPart) {
+                if (($requestUrlPart === '') || ($requestUrlPart === '.')) {
+                    continue;
+                } elseif ($requestUrlPart === '..') {
+                    array_pop($requestFileParts);
+                    continue;
+                }
+
+                $requestFileParts[] = $requestUrlPart;
+            }
+
+            // discover the content file to serve
+            // Note: $requestFileParts neither contains a trailing nor a leading slash
+            $this->requestFile = $this->getConfig('content_dir') . implode('/', $requestFileParts);
             if (is_dir($this->requestFile)) {
                 // if no index file is found, try a accordingly named file in the previous dir
                 // if this file doesn't exist either, show the 404 page, but assume the index