Message262572
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. |
|
Date |
User |
Action |
Args |
2016-03-28 15:30:15 | Thomas | set | recipients:
+ Thomas |
2016-03-28 15:30:15 | Thomas | set | messageid: <1459179015.77.0.509336394494.issue26657@psf.upfronthosting.co.za> |
2016-03-28 15:30:15 | Thomas | link | issue26657 messages |
2016-03-28 15:30:15 | Thomas | create | |
|