2010-03-03 1 views
32

Ich habe eine Java-Server-Implementierung (TFTP, wenn es Ihnen wichtig ist) und ich möchte sicherstellen, dass es nicht anfällig für Pfad Traversalen Angriffe den Zugriff auf Dateien und Standorte, die nicht verfügbar sein sollten.Was ist der beste Weg, um gegen einen Traversal-Angriff zu verteidigen?

Mein bester Versuch so weit zu verteidigen ist keine Einträge abzulehnen, die File.isAbsolute() und dann verlassen sich auf File.getCanonicalPath() passen aus dem Weg alle ../ und ./ Komponenten zu lösen. Schließlich stelle ich sicher, dass der resultierende Weg noch innerhalb der erforderlichen Stammverzeichnis von meinem Server ist:

public String sanitize(final File dir, final String entry) throws IOException { 
    if (entry.length() == 0) { 
     throw new PathTraversalException(entry); 
    } 

    if (new File(entry).isAbsolute()) { 
     throw new PathTraversalException(entry); 
    } 

    final String canonicalDirPath = dir.getCanonicalPath() + File.separator; 
    final String canonicalEntryPath = new File(dir, entry).getCanonicalPath(); 

    if (!canonicalEntryPath.startsWith(canonicalDirPath)) { 
     throw new PathTraversalException(entry); 
    } 

    return canonicalEntryPath.substring(canonicalDirPath.length()); 
} 

Gibt es Sicherheitsprobleme, dass dies verpasst? Ist es besser/schneller, das gleiche Ergebnis zuverlässig zu erreichen?

Der Code muss konsistent über Windows und Linux hinweg funktionieren.

+1

Vergessen Sie nicht, den Zugriff auf die Windows-Spezialgeräte (NUL, COM1, etc.), die in dem Dateisystem vorhanden sind überall zu verbieten. –

+0

Guten Gedanken Heath. Der folgende Link scheint eine definitive Liste der reservierten Windows-Dateinamen zu haben: http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx –

+0

Warum können Sie das nicht auf Ihrem Computer konfigurieren? Apache/IIS Server stattdessen? – kikito

Antwort

2

Wenn Sie dies auf einem Unix-Rechner ausführen (ich bin mir nicht sicher, ob Windows etwas ähnliches hat, aber vielleicht), sollten Sie sich chroot ansehen. Selbst wenn Sie denken, dass Sie alle Wege für jemanden gefunden haben, um ein paar Verzeichnisse zu referenzieren, ist es nett, dass das Betriebssystem dort die Tat durchsetzt.

(chroot bewirkt, dass '/' auf ein anderes Verzeichnis verweist, also könnte "/" "/ home/me/project" sein und "/../../ .." ist immer noch "/ home/me/Projekt“)

EDIT:.

Es gibt einen Anruf chroot-System sowie ein chroot-Befehlszeilenprogramm. Ich weiß nicht, ob Java eine native Methode hat, aber nichts würde Sie davon abhalten, Ihren Server mit dem Befehlszeilentool auszuführen. Dies sollte natürlich zusätzlich dazu getan werden, Ihr Bestes zu tun, um andere Pfadmanipulationen zu verhindern.

+0

Eigentlich ist das nicht wahr, eine Chroot kann verwendet werden, um einen laufenden Prozess auf eine vollständige Indipendant zu setzen Verzeichnisbaum mit einem eigenen/home/var/etc ... Auch Directory Traversal innerhalb einer Chroot kann immer noch zu fiesen Attacken führen, sogar Remote-Code-Ausführung. – rook

+0

Ihre erste Aussage ist wahr, wenn auch etwas irreführend. Sie würden Ihren eigenen Spiegel der Wurzelsystempfade in einem Unterverzeichnis erstellen - alles, was Sie ausführen müssen, einschließlich Java und verwandter Bibliotheken. Die zweite Aussage ist eine starke Übertreibung, da sie chroot mit dem Angriff implizit verbindet. Wenn Sie ein Loch haben, das zu einem Angriff führen könnte, sollte es als separates Problem gepatcht werden. Chroot ist da, um die Auswirkungen potenzieller Sicherheitsbedenken zu minimieren. Am Ende können Sie keinen Code als sicher beweisen, Sie können nur Ihre Angriffsfläche reduzieren und das Schadenspotenzial verringern. – Sniggerfardimungus

0

Sie können die erlaubten Zeichen in Dateinamen (http://en.wikipedia.org/wiki/Filename) auschecken und alle nicht erlaubten Zeichen herausfiltern (weiße Auflistung) und dann können Sie sicher sein, dass Sie dort einen Dateinamen haben.

1

Folgendes kann helfen. Es vergleicht die kanonischen und absoluten Pfade, und wenn sie sich unterscheiden, wird es scheitern. Nur getestet auf einem Mac/Linux-System (dh keine Windows).

Dies ist für den Fall, dass Sie zulassen möchten, dass der Benutzer einen relativen Pfad und keinen absoluten Pfad angibt und keine übergeordneten Verzeichnisverweise zulassen.

public void failIfDirectoryTraversal(String relativePath) 
{ 
    File file = new File(relativePath); 

    if (file.isAbsolute()) 
    { 
     throw new RuntimeException("Directory traversal attempt - absolute path not allowed"); 
    } 

    String pathUsingCanonical; 
    String pathUsingAbsolute; 
    try 
    { 
     pathUsingCanonical = file.getCanonicalPath(); 
     pathUsingAbsolute = file.getAbsolutePath(); 
    } 
    catch (IOException e) 
    { 
     throw new RuntimeException("Directory traversal attempt?", e); 
    } 


    // Require the absolute path and canonicalized path match. 
    // This is done to avoid directory traversal 
    // attacks, e.g. "1/../2/" 
    if (! pathUsingCanonical.equals(pathUsingAbsolute)) 
    { 
     throw new RuntimeException("Directory traversal attempt?"); 
    } 
} 
Verwandte Themen