Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extractFilesFromArchive handles '..' in entry paths in a potentially insecure manner #50

Closed
athas opened this issue Jul 25, 2018 · 7 comments

Comments

@athas
Copy link

athas commented Jul 25, 2018

Consider this program, which creates and then unpacks a zip file evil.zip that contains a file with filepath "../evil":

module Main (main) where

import qualified Codec.Archive.Zip as Zip
import qualified Data.ByteString.Lazy as LBS

main :: IO ()
main = writeIt >> readIt
  where writeIt = do
          let entry = Zip.toEntry "../evil" 0 mempty
              archive = Zip.addEntryToArchive entry Zip.emptyArchive
          LBS.writeFile "evil.zip" $ Zip.fromArchive archive

        readIt = do
          archive <- Zip.toArchive <$> LBS.readFile "evil.zip"
          Zip.extractFilesFromArchive [Zip.OptVerbose] archive

When run, this program will indeed create an empty file at "../evil". This means that extractFilesFromArchive is dangerous to use on untrusted zip files. The unzip tool on *nix has some form of safety mechanism here:

$ unzip evil.zip 
Archive:  evil.zip
warning:  skipped "../" path component(s) in ../evil
 extracting: evil

I think the best solution is to fail in a noisy way when such dangerous entries are encountered.

@jgm
Copy link
Owner

jgm commented Jul 25, 2018 via email

@athas
Copy link
Author

athas commented Jul 25, 2018

One possibility is to do what unzip does, and just ignore the '..'s (possibly logging that). Another is to crash with 'error' like I assume is done for other kinds of invalid filepaths (like 'nul' on Windows or something that contains a NUL byte). I don't think it's important to do something particularly nice, since you're already quite far into the weeds and dealing with malformed data if this occurs.

@jgm
Copy link
Owner

jgm commented Jul 25, 2018 via email

@tmspzz
Copy link
Contributor

tmspzz commented Jul 25, 2018

what about deprecating addEntryToArchive and adding securelyAddEntryToArchive with the appropriate type for errors?

@athas
Copy link
Author

athas commented Jul 26, 2018

The problem is not addEntryToArchive, but extractFilesFromArchive. An attacker can always craft a malicious zip archive.

I think the best solution is for extractFilesFromArchive to crash with error when unsafe paths are found. This is also what it will do for other malformed paths (like empty ones). The second best solution is to rewrite the paths to be safe (as unzip(1) does) and print a notice if OptVerbose is used.

@jgm
Copy link
Owner

jgm commented Jul 30, 2018 via email

@tmspzz
Copy link
Contributor

tmspzz commented Jul 30, 2018

ZipException, and throw that exception for unsafe paths. This is better than 'error' because it can be caught.

Yes.

The only remaining question is how we test for unsafe paths?

Make the path absolute (resolving symlinks as well) and check that it does not leave the root directory of the archive.

I use https://github.com/blender/Rome/blob/faed9ce50884338e1dbbe1863bba6e571374bb53/src/Utils.hs#L392

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants