Skip to content

Commit

Permalink
Mitigate path traversal vulnerability #227
Browse files Browse the repository at this point in the history
  • Loading branch information
ikus060 committed Oct 3, 2022
1 parent ee98e5a commit 323383d
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 29 deletions.
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,13 @@ Professional support for Rdiffweb is available by contacting [IKUS Soft](https:/

# Changelog

## 2.4.9 (2002-09-28)
## 2.4.10 (2022-10-03)

This releases include a security fix. If you are using an earlier version, you should upgrade to this release immediately.

* Mitigate path traversal vulnerability [CVE-2022-3389](https://nvd.nist.gov/vuln/detail/CVE-2022-3389)

## 2.4.9 (2022-09-28)

This releases include a security fix. If you are using an earlier version, you should upgrade to this release immediately.

Expand Down
42 changes: 20 additions & 22 deletions rdiffweb/controller/dispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@
"""


import os

import cherrypy
from cherrypy.lib.static import mimetypes, serve_file

from rdiffweb.core.rdw_helpers import unquote_url

Expand Down Expand Up @@ -96,32 +93,33 @@ def decorated(cls_or_self=None, vpath=None):
return decorated


def static(path):
def staticdir(path):
"""
Create a page handler to serve static directory.
"""

@cherrypy.expose
@cherrypy.tools.auth_form(on=False)
@cherrypy.tools.sessions(on=False)
@cherrypy.tools.secure_headers(on=False)
@cherrypy.tools.staticdir(section="", dir=path)
def handler(*args, **kwargs):
return None

return handler


def staticfile(path):
"""
Create a page handler to serve static files. Disable authentication.
Create a page handler to serve static file.
"""
assert isinstance(path, str)
assert os.path.exists(path), "%r doesn't exists" % path
content_type = None
if os.path.isfile(path):
# Set content-type based on filename extension
ext = ""
i = path.rfind('.')
if i != -1:
ext = path[i:].lower()
content_type = mimetypes.types_map.get(ext, None) # @UndefinedVariable

@cherrypy.expose
@cherrypy.tools.auth_form(on=False)
@cherrypy.tools.sessions(on=False)
@cherrypy.tools.secure_headers(on=False)
@cherrypy.tools.staticfile(filename=path)
def handler(*args, **kwargs):
if cherrypy.request.method not in ('GET', 'HEAD'):
return None
filename = os.path.join(path, *args)
assert filename.startswith(path)
if not os.path.isfile(filename):
return None
return serve_file(filename, content_type)
return None

return handler
25 changes: 24 additions & 1 deletion rdiffweb/controller/tests/test_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
@author: Patrik Dufresne
"""

from parameterized import parameterized

import rdiffweb.test

Expand All @@ -46,14 +47,36 @@ def test_theme(self):
self.assertStatus('200 OK')
self.assertInBody('/static/default.css')

@parameterized.expand(
[
'/favicon.ico',
'/static/default.css',
'/static/js/rdiffweb.js',
'/static/orange.css',
]
)
def test_static_files(self, path):
"""
Check if the theme is properly configure.
"""
self.getPage('/logout')
self.getPage(path)
self.assertStatus(200)

def test_path_traversal(self):
self.getPage('/static//../../test.txt')
self.assertStatus(403)


class ControllerOrangeThemeTest(rdiffweb.test.WebCase):

login = True

default_config = {'DefaultTheme': 'orange'}

def test_theme(self):
from parameterized import parameterized

def test_static(self):
"""
Check if the theme is properly configure.
"""
Expand Down
10 changes: 5 additions & 5 deletions rdiffweb/rdw_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import rdiffweb.tools.secure_headers
from rdiffweb.controller import Controller
from rdiffweb.controller.api import ApiPage
from rdiffweb.controller.dispatch import static # noqa
from rdiffweb.controller.dispatch import staticdir, staticfile
from rdiffweb.controller.page_admin import AdminPage
from rdiffweb.controller.page_browse import BrowsePage
from rdiffweb.controller.page_delete import DeletePage
Expand Down Expand Up @@ -97,11 +97,11 @@ def __init__(self):

# Register static dir.
static_dir = pkg_resources.resource_filename('rdiffweb', 'static') # @UndefinedVariable
self.static = static(static_dir)
self.static = staticdir(static_dir)

# Register robots.txt
robots_txt = pkg_resources.resource_filename('rdiffweb', 'static/robots.txt') # @UndefinedVariable
self.robots_txt = static(robots_txt)
self.robots_txt = staticfile(robots_txt)


class RdiffwebApp(Application):
Expand Down Expand Up @@ -208,11 +208,11 @@ def __init__(self, cfg):
Application.__init__(self, root=Root(), config=config)

# Register favicon.ico
self.root.favicon_ico = static(self._favicon)
self.root.favicon_ico = staticfile(self._favicon)

# Register header_logo
if self._header_logo:
self.root.header_logo = static(self._header_logo)
self.root.header_logo = staticfile(self._header_logo)

# Define TEMP env
if self._tempdir:
Expand Down

0 comments on commit 323383d

Please sign in to comment.