[Scala] [Java] J'ai essayé de corriger la vulnérabilité de traversée de répertoire lors de la décompression de Zip4j par opération de code d'octet.

Connaissez-vous Zip-Slip, une vulnérabilité de traversée de répertoires lors de la décompression de Zip?

Je laisserai les détails à d'autres articles tels que ↓, mais cette fois je vais essayer de réparer la bibliothèque appelée zip4j en manipulant le code d'octet. Impact de la vulnérabilité de la traversée des répertoires Zip Slip sur de nombreux projets Java

À propos, les versions de contre-mesures de vulnérabilité de chaque bibliothèque qui gère Zip sont répertoriées ici. snyk/zip-slip-vulnerability: Zip Slip Vulnerability (Arbitrary file write through archive extraction) Il semble que zip4j n'ait pas de distribution jar ... Si vous prenez la position de distribuer le code source et d'en faire un pot vous-même, je pense qu'il sera plus probable que vous n'utiliserez pas la dernière version ...

↓ données de test zip-slip zip-slip-vulnerability/archives at master · snyk/zip-slip-vulnerability

Code que j'ai essayé de corriger

import javassist._
import javassist.expr.ExprEditor
import javassist.expr.MethodCall
import net.lingala.zip4j.core.ZipFile

/**
  *Patch de sécurité dynamique Zip4j par réécriture de code d'octet
  */
object Zip4jSecurity {
  def main(args: Array[String]): Unit = {
    patch()

    //Testez si la validation fonctionne. Zip *: français-Une exception se produit en raison de la validation du bordereau.
    val zipFile = new ZipFile("/home/momose/Documents/zip-slip.zip")
    zipFile.extractAll("/home/momose/Documents/tmp/")
  }

  /**
    *Appliquer le patch
    */
  def patch(): Unit = {
    val cp = ClassPool.getDefault
    val classLoader = Thread.currentThread().getContextClassLoader()
    cp.appendClassPath(new LoaderClassPath(classLoader))
    val cc = cp.get("net.lingala.zip4j.unzip.Unzip")
    val zipSlipValidationEditor = new Zip4jSecurity.ZipSlipValidationEditor
    cc.instrument(zipSlipValidationEditor)
    //Inscrivez-vous avec le chargeur de classe
    cc.toClass(null, clazz.getProtectionDomain)
  }

  private class ZipSlipValidationEditor extends ExprEditor {
    //Indicateurs qui s'appliquent uniquement au premier appel de méthode
    private var unedited = true

    override def edit(m: MethodCall): Unit = {
      if (unedited &&
        m.getClassName.equals("net.lingala.zip4j.model.CentralDirectory") &&
        m.getMethodName.equals("getFileHeaders")) {
        //Code de validation
        val statement ="""
java.io.File outputDir = new java.io.File(outPath);
java.util.List fileHeaders = $0.getFileHeaders($$);
for( int i=0; i<fileHeaders.size(); i++ ){
    net.lingala.zip4j.model.FileHeader e = (net.lingala.zip4j.model.FileHeader)fileHeaders.get(i);
    if (!new java.io.File(outputDir, e.getFileName()).getCanonicalPath().startsWith(outputDir.getCanonicalPath())) {
            throw new RuntimeException("ZIP illégal");
    }
}
$_ = fileHeaders;"""
        m.replace(statement)
        unedited = false
      }
    }
  }

}

Résultat d'exécution

Exception in thread "main" java.lang.RuntimeException:ZIP illégal
	at net.lingala.zip4j.unzip.Unzip.extractAll(Unzip.java:50)
	at net.lingala.zip4j.core.ZipFile.extractAll(ZipFile.java:488)
	at net.lingala.zip4j.core.ZipFile.extractAll(ZipFile.java:451)
	at com.github.momosetkn.zip.Zip4jSecurity$.main(Zip4jSecurity.scala:18)
	at com.github.momosetkn.zip.Zip4jSecurity.main(Zip4jSecurity.scala)

Il valide le résultat de la méthode Java getCanonicalPath, tel que realpath dans les commandes C et Linux. ↓ Matériaux de référence IDS02 \ -J . Normaliser les chemins d'accès avant validation

Uniquement lorsqu'il est utilisé dans la méthode net.lingala.zip4j.core.ZipFile # extractAll Nous n'avons pas confirmé qu'il s'agira d'une contre-mesure, de sorte que des vulnérabilités peuvent se développer dans d'autres cas. Je veux que vous le testiez vous-même.

↓ Cette partie est préparée dans l'appel de méthode net.lingala.zip4j.model.CentralDirectory # getFileHeaders (). zip4j/Unzip.java at master · supasate/zip4j

Impressions

Avec Scala, les littéraux de chaîne devraient être faciles à gérer. De plus, il est agréable de traiter toutes les exceptions comme des exceptions non vérifiées. Lors de la réécriture avec javassist, il est difficile d'écrire dans du code Java qui correspond à la version Java à réécrire.

Recommended Posts

[Scala] [Java] J'ai essayé de corriger la vulnérabilité de traversée de répertoire lors de la décompression de Zip4j par opération de code d'octet.
J'ai essayé de traduire le message d'erreur lors de l'exécution d'Eclipse (Java)
[Java] J'ai essayé de faire un labyrinthe par la méthode de creusage ♪
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
J'ai essayé d'implémenter la fonction similaire par communication asynchrone
[JDBC] J'ai essayé d'accéder à la base de données SQLite3 depuis Java.
J'ai essayé de résumer les bases de kotlin et java
J'ai essayé de construire l'environnement petit à petit en utilisant docker
Je veux juger de la nécessité de tester en comparant les différences des fichiers de classe lors de la refactorisation de Java.
J'ai essayé de vérifier le fonctionnement du serveur gRPC avec grpcurl
J'ai essayé de résumer les méthodes de Java String et StringBuilder
J'ai essayé d'exécuter le formulaire FaaS compatible Java "Fn Project"
J'ai essayé d'afficher le calendrier sur la console Eclipse en utilisant Java.
En vérifiant le fonctionnement de Java sous Linux, j'ai pu comprendre la compilation et la hiérarchie.
J'ai essayé d'interagir avec Java
J'ai essayé d'expliquer la méthode
J'ai essayé le framework Java "Quarkus"
J'ai essayé de résumer l'apprentissage Java (1)
J'ai essayé de résumer Java 8 maintenant
J'ai essayé de connecter le compteur de points à la plate-forme MZ par communication série
[Introduction à Java] J'ai essayé de résumer les connaissances que j'estime essentielles
Je souhaite obtenir l'adresse IP lors de la connexion au Wi-Fi avec Java
J'ai essayé de résumer les méthodes utilisées
J'ai essayé de résumer les expressions Java lambda
J'ai essayé le nouveau yuan à Java
J'ai essayé d'implémenter le modèle Iterator
J'ai essayé de résumer l'API Stream
Je suis allé au Java Women's Club # 1
Une histoire où j'ai essayé de faire une vidéo en liant Traitement et Resolume
Ce que j'ai essayé quand je voulais obtenir tous les champs d'un haricot
Je veux que vous utilisiez Scala comme meilleur Java pour le moment
[JavaScript] Le cas le plus fort lorsque j'ai essayé de résumer les parties que je ne comprends pas
[Petite histoire] J'ai essayé de rendre java ArrayList un peu plus pratique