Pfaddurchlauf zippen

OWASP-Kategorie:MASVS-STORAGE: Storage

Übersicht

Die Sicherheitslücke „Zip Path Traversal“, auch als „ZipSlip“ bezeichnet, hängt mit der Verarbeitung komprimierter Archive zusammen. Auf dieser Seite wird diese Sicherheitslücke anhand des ZIP-Formats demonstriert. Ähnliche Probleme können jedoch auch in Bibliotheken auftreten, die andere Formate wie TAR, RAR oder 7z verarbeiten.

Der zugrunde liegende Grund für dieses Problem ist, dass in ZIP-Archiven jede gepackte Datei mit einem vollständig qualifizierten Namen gespeichert wird, der Sonderzeichen wie Schrägstriche und Punkte zulässt. Die Standardbibliothek aus dem java.util.zip-Paket prüft die Namen der Archiveinträge nicht auf Zeichen für Directory Traversal (../). Daher ist besondere Vorsicht geboten, wenn der aus dem Archiv extrahierte Name mit dem Zielverzeichnispfad verkettet wird.

Es ist sehr wichtig, alle Code-Snippets oder Bibliotheken zum Entpacken von ZIP-Dateien aus externen Quellen zu validieren. Viele solcher Bibliotheken sind anfällig für ZIP-Pfaddurchläufe.

Positiv beeinflussen

Die Sicherheitslücke beim ZIP-Pfaddurchlauf kann verwendet werden, um beliebige Dateien zu überschreiben. Je nach den Umständen kann die Auswirkung variieren, aber in vielen Fällen kann diese Sicherheitslücke zu schwerwiegenden Sicherheitsproblemen wie der Ausführung von Code führen.

Maßnahmen zur Risikominderung

Um dieses Problem zu beheben, sollten Sie vor dem Extrahieren jedes Eintrags immer prüfen, ob der Zielpfad ein untergeordnetes Element des Zielverzeichnisses ist. Im folgenden Code wird davon ausgegangen, dass das Zielverzeichnis sicher ist – nur Ihre App kann darauf schreiben und es unterliegt nicht der Kontrolle von Angreifern. Andernfalls könnte Ihre App anfällig für andere Sicherheitslücken wie Symlink-Angriffe sein.

Kotlin

companion object {
    @Throws(IOException::class)
    fun newFile(targetPath: File, zipEntry: ZipEntry): File {
        val name: String = zipEntry.name
        val f = File(targetPath, name)
        val canonicalPath = f.canonicalPath
        if (!canonicalPath.startsWith(
                targetPath.canonicalPath + File.separator)) {
            throw ZipException("Illegal name: $name")
        }
        return f
    }
}

Java

public static File newFile(File targetPath, ZipEntry zipEntry) throws IOException {
    String name = zipEntry.getName();
    File f = new File(targetPath, name);
    String canonicalPath = f.getCanonicalPath();
    if (!canonicalPath.startsWith(targetPath.getCanonicalPath() + File.separator)) {
      throw new ZipException("Illegal name: " + name);
    }
    return f;
 }

Damit vorhandene Dateien nicht versehentlich überschrieben werden, sollte das Zielverzeichnis leer sein, bevor Sie mit dem Extrahieren beginnen. Andernfalls riskieren Sie potenzielle App-Abstürze oder im Extremfall eine Kompromittierung der Anwendung.

Kotlin

@Throws(IOException::class)
fun unzip(inputStream: InputStream?, destinationDir: File) {
    if (!destinationDir.isDirectory) {
        throw IOException("Destination is not a directory.")
    }
    val files = destinationDir.list()
    if (files != null && files.isNotEmpty()) {
        throw IOException("Destination directory is not empty.")
    }
    ZipInputStream(inputStream).use { zipInputStream ->
        var zipEntry: ZipEntry
        while (zipInputStream.nextEntry.also { zipEntry = it } != null) {
            val targetFile = File(destinationDir, zipEntry.name)
            // ...
        }
    }
}

Java

void unzip(final InputStream inputStream, File destinationDir)
      throws IOException {
  if(!destinationDir.isDirectory()) { 
    throw IOException("Destination is not a directory.");
  }

  String[] files = destinationDir.list();
  if(files != null && files.length != 0) { 
    throw IOException("Destination directory is not empty.");
  }

  try (ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
    ZipEntry zipEntry;
    while ((zipEntry = zipInputStream.getNextEntry()) != null) {
      final File targetFile = new File(destinationDir, zipEntry);
        
    }
  }
}

Ressourcen

  • Hinweis: Linktext wird angezeigt, wenn JavaScript deaktiviert ist.
  • Pfad-Traversal