PHP temporäre Dateinamen für Uploads, die kollidieren

8

Wenn ein Benutzer eine Datei hochlädt, wird diese zufällig durch den Upload eines anderen Benutzers ersetzt. Ich habe das Problem schließlich auf PHP aufgespürt und den Dateinamen der tmp erneut verwendet. Gibt es eine Möglichkeit, das zu beheben? Gibt es eine Möglichkeit, bessere zufällige Namen zu machen? Es scheint sich im Laufe der Zeit zu verschlechtern, da der Name der Zufallsdatei schwächer wird? Dies ist auf PHP 5.2.8 und FreeBSD 7.0

Hier ist ein Protokoll, das zeigt, wie derselbe tmp-Dateiname verwendet wird und von einem anderen Upload überschrieben wird: Ссылка

Jede Hilfe wird sehr geschätzt. Ich habe versucht, das seit über 4 Monaten zu beheben und ist mit der Zeit schlimmer geworden. Danke.

EDIT: Denken Sie daran, dass dies kein PHP-Code-Problem ist, das passiert, bevor es PHP-Code erreicht, die über $ _FILES ['name'] ['tmp_name'] empfangene Datei ist falsch, wenn sie empfangen wird und Es wurde zurückverfolgt, dass es mit dem Upload einer anderen Person überschrieben wird, bevor es das Upload-Verarbeitungsskript erreicht.

    
mrmanman 10.03.2009, 19:22
quelle

5 Antworten

4

Es hört sich so an, als ob etwas ernsthaft mit Ihrer PHP-Installation oder mit dem Systemaufruf, den PHP intern verwendet, um die zufälligen Dateinamen zu erzeugen, falsch ist (höchstwahrscheinlich tempnam ).

Für alle anderen: PHP verarbeitet hochgeladene Dateien intern, bevor der Benutzercode jemals verarbeitet wird. Diese Namen werden in $_FILES['file']['tmp_name'] gespeichert (wobei 'Datei' der Name des Dateieingabeelements im Formular ist).

    
Powerlord 10.03.2009 19:32
quelle
3

Nachdem Sie den relevanten Code bis zu _gettemp verfolgt haben Die libc-Implementierung von FreeBSD 7, ich bin nicht sicher, wie der Inhalt der Datei tmp_name ungültig sein könnte. (Um es zu verfolgen, können Sie eine Kopie von PHP 5.2.8 herunterladen und in main/rfc1867.c - Zeile 1018 Aufrufe in main/php_open_temporary_file.c einlesen, wobei die Funktion ab Zeile 227 beginnt, was ihre Hauptaufgabe in der Funktion ab Zeile 97 ist. Dies ist jedoch im Wesentlichen nur ein Wrapper für mkstemp auf Ihrem System, der sich in der FreeBSD libc-Implementierung in Zeile 66 (verlinkt), die _ gettemp (wie oben), um den zufälligen Dateinamen tatsächlich zu generieren. Allerdings die manpage for mkstemp erwähnt im Abschnitt BUGS, dass die Funktion arc4random() funktioniert ist nicht wiedereintrittsfähig.Es könnte eine Möglichkeit sein, dass zwei gleichzeitige Anfragen in den kritischen Codebereich eintreten und dieselbe tmp_name zurückgeben - ich weiß zu wenig darüber, wie Ap ache arbeitet entweder mit mod_php oder php-cgi, um sie zu kommentieren (obwohl die Verwendung von FastCGI / php-cgi funktionieren könnte - ich kann dies zu diesem Zeitpunkt nicht erfolgreich kommentieren).

Wenn Sie jedoch nicht die Datei tmp_name selbst als ungültig empfinden, sondern stattdessen mit anderen hochgeladenen Dateien kollidieren (z. B. wenn Sie den Dateinamensteil von tmp_name als einzige Quelle für die Eindeutigkeit verwenden) im gespeicherten Dateinamen) könnten Sie aufgrund des Geburtstagsparadoxons mit Kollisionen konfrontiert werden. In einer weiteren Frage erwähnen Sie etwa 5.000.000 Dateien zu verschieben, und in noch eine Frage Sie erwähnen, erhalten 30-40k lädt einen Tag hoch. Dies erscheint mir als eine erstklassige Situation für eine Geburtstagsparadox Kollision. Die mktemp man-Seite erwähnt, dass (wenn man sechs 'Xs' wie PHP verwendet) vorhanden sind 56,800,235,584 mögliche Dateinamen (62 ** 6, oder 62 ** n, wobei n = Anzahl von 'Xs' usw.). Da Sie jedoch mehr als 5 Millionen Dateien haben, ist die Wahrscheinlichkeit einer Kollision ungefähr 100% (eine andere Heuristik legt nahe, dass Sie bereits eine Größenordnung von 220 Kollisionen erlebt haben, if ((Dateien * ( files-1)) / 2) / (62 ** 6) bedeutet alles, wo Dateien = 5.000.000). Wenn dies das Problem ist, dem Sie begegnen (wahrscheinlich, wenn dem generierten hochgeladenen Dateinamen keine weitere Entropie hinzufügt), könnten Sie etwas wie move_uploaded_file($file['tmp_name'], UPLOADS.sha1(mt_rand().$file['tmp_name']).strrchr($file['name'], '.')) versuchen - die Idee wäre, dem zufälligen Dateinamen mehr Zufälligkeit hinzuzufügen , Kollisionen verhindern. Eine Alternative könnte sein, zwei weitere 'X' zu Zeile 134 von main/php_open_temporary_file.c hinzuzufügen und neu zu kompilieren.

    
Iiridayn 19.07.2010 16:52
quelle
2

Läuft PHP unter Apache, als mod_php ?

Sie können versuchen, ein pro-process temporäres Upload-Verzeichnis zu erstellen , dessen Name Ihr php getmypid() , dann ini_set Dein PHP-Prozess ' upload_tmp_dir to dieses Verzeichnis. Dies funktioniert nicht, wenn für jede Anfrage ein neuer php -Prozess erzeugt wird.

    
vladr 10.03.2009 19:28
quelle
0

Verschieben Sie Ihre Dateien nach dem Hochladen in ein Benutzerverzeichnis. Diese temporären Dateien sollten entfernt werden.

    
Andrew Clark 10.03.2009 19:28
quelle
-1

Ich würde empfehlen, einen GUID-Generator für den Dateinamen zu verwenden, da Sie so viele erhalten.

    
webclimber 10.03.2009 19:25
quelle