New submission from Thomas:

SimpleHTTPServer and http.server allow directory traversal on Windows.
To exploit this vulnerability, replace all ".." in URLs with "c:c:c:..".


Example:
Run
python -m http.server
and visit
127.0.0.1:8000/c:c:c:../secret_file_that_should_be_secret_but_is_not.txt


There is a warning that those modules are not secure in the module docs,
but for some reason they do not appear in the online docs:
https://docs.python.org/3/library/http.server.html
https://docs.python.org/2/library/simplehttpserver.html


It would be nice if that warning was as apparent as for example here:
https://docs.python.org/2/library/xml.etree.elementtree.html


There are a lot of other URLs that are insecure as well, which can all
be traced back to here:
https://hg.python.org/cpython/file/tip/Lib/http/server.py#l766


The splitdrive and split functions, which should make sure that the
final output is free of ".." are only called once which leads to this
control flow:
---------------------------------------------------------------
path = "c:/secret/public"
word = "c:c:c:.."

_, word = os.path.splitdrive(word) # word = "c:c:.."
_, word = os.path.split(word) # word = "c:.."
path = os.path.join(path, word) # path = "c:/secret/public\\.."
---------------------------------------------------------------


Iterating splitdrive and split seems safer:
---------------------------------------------------------------
for word in words:
    # Call split and splitdrive multiple times until
    # word does not change anymore.
    has_changed = True
    while has_changed:
        previous_word = word
        _, word = os.path.split(word)
        _, word = os.path.splitdrive(word)
        has_changed = word != previous_word
---------------------------------------------------------------






There is another weird thing which I am not quite sure about here:
https://hg.python.org/cpython/file/tip/Lib/http/server.py#l761

---------------------------------------------------------------
path = posixpath.normpath(path)
words = path.split('/')
---------------------------------------------------------------

posixpath.normpath does not do anything with backslashes and then the
path is split by forward slashes, so it may still contain backslashes.
Maybe replacing posixpath.normpath with os.path.normpath and then
splitting by os.sep would work, but I don't have enough different
operating systems to test this, so someone else should have a look.





I have attached some simple fuzzing test that tries a few weird URLs and
sees if they lead where they shouldn't.
Disclaimer: Might still contain other bugs.

----------
components: Library (Lib)
files: fuzz.py
messages: 262572
nosy: Thomas
priority: normal
severity: normal
status: open
title: Directory traversal with http.server and SimpleHTTPServer on windows
type: security
versions: Python 3.6
Added file: http://bugs.python.org/file42315/fuzz.py

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue26657>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to