merkwürdiger Fehler
misterunknown
- php
0 Der Martin
0 Der Martin
0 Vinzenz Mai0 dedlfix
0 misterunknown
Moin,
ich habe mir vor längerer Zeit einen Filemanager auf PHP-Basis gebaut. Nun habe ich einen "Bug" entdeckt. Als ich vorhin eine Datei ändern wollte, habe ich beim Absenden die Fehlermeldung gekriegt, dass keine Berechtigung auf das Verzeichnis vorliegt (vom Webserver). Da ich die Datei über mein Tool aber schon x mal geändert hatte konnte das natürlich nicht sein. Nach einem probieren ist mir aufgefallen, dass selbst wenn ich die Datei nicht speichern wollte, sondern Abbrechen gedrückt hab, dieser Fehler kam. Ansonsten arbeitete das Skript aber fehlerfrei. Die 2 Buttons "Save" und "Cancel" sind im selben Formular, so dass beim Klicken prinzipiell das Formular abgesendet wird. Nur prüft eben das Skript, welcher Button gedrückt wurde. Es muss also an dem Inhalt der Textarea liegen, den ich speichern will.
Nach einigem Probieren habe ich das Problem gefunden: Wenn in der Textarea ein "session_start();" steht, kommt genau dieser Fehler. Jeglicher anderer PHP, HTML oder Javascript-Code lässt sich aber problemlos abspeichern. Da ich mit dem Tool sehr oft und viele kleine Skripts erstelle, ist das natürlich schlecht, auch wenn ich Sessions relativ wenig brauche.
Meine Frage wäre jetzt: Woran liegt es, dass der Webserver einen Berechtigungsfehler bringt? Hat jemand eine Idee? (etwas Code am Ende)
Grüße Marco
Etwas Code:
Formular zum Bearbeiten einer Datei:
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset>
<textarea cols="60" rows="15" name="newcontent">'.htmlspecialchars(file_get_contents($_POST["filename"]), ENT_QUOTES).'</textarea><br />
<input type="hidden" name="action" value="editsure" /><input type="hidden" name="filename" value="'.$_POST["filename"].'" />
<input type="submit" name="subbut" value="Save" style="float:left;" /><input type="submit" name="subbut" value="Cancel" />
</fieldset></form>';
}
Auswertung:
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset>
<textarea cols="60" rows="15" name="newcontent">'.htmlspecialchars(file_get_contents($_POST["filename"]), ENT_QUOTES).'</textarea><br />
<input type="hidden" name="action" value="editsure" /><input type="hidden" name="filename" value="'.$_POST["filename"].'" />
<input type="submit" name="subbut" value="Save" style="float:left;" /><input type="submit" name="subbut" value="Cancel" />
</fieldset></form>';
}
Hallo,
Nach einigem Probieren habe ich das Problem gefunden: Wenn in der Textarea ein "session_start();" steht, kommt genau dieser Fehler.
das lässt mich irgendein Escaping-Problem vermuten, das ich am gezeigten Code aber nicht nachvollziehen kann. Denn wenn dieser String in einer textarea vorkommt, ist es ja nichts weiter als Text. Die Behandlung mit htmlspecialchars() ist auch richtig an der Stelle (und ENT_QUOTES innerhalb einer textarea nicht unbedingt nötig) - warum also sollte das ein Fehlverhalten auslösen?
Meine Frage wäre jetzt: Woran liegt es, dass der Webserver einen Berechtigungsfehler bringt? Hat jemand eine Idee? (etwas Code am Ende)
Wenn du beim Absenden einen 403er bekommst, muss ja die Ziel-URL, an die das Formular verschickt wird, irgendwie problematisch sein. Was also kommt für $_SERVER['PHP_SELF'] tatsächlich beim Client an?
Leider hilft mir der Code da nicht wirklich weiter ...
Formular zum Bearbeiten einer Datei:
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset> <textarea cols="60" rows="15" name="newcontent">'.htmlspecialchars(file_get_contents($_POST["filename"]), ENT_QUOTES).'</textarea><br /> <input type="hidden" name="action" value="editsure" /><input type="hidden" name="filename" value="'.$_POST["filename"].'" /> <input type="submit" name="subbut" value="Save" style="float:left;" /><input type="submit" name="subbut" value="Cancel" /> </fieldset></form>';
}
>
> Auswertung:
> ~~~php
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
> print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset>
> <textarea cols="60" rows="15" name="newcontent">'.htmlspecialchars(file_get_contents($_POST["filename"]), ENT_QUOTES).'</textarea><br />
> <input type="hidden" name="action" value="editsure" /><input type="hidden" name="filename" value="'.$_POST["filename"].'" />
> <input type="submit" name="subbut" value="Save" style="float:left;" /><input type="submit" name="subbut" value="Cancel" />
> </fieldset></form>';
> }
Copy'n'Paste Error? Das ist zweimal derselbe Schnipsel. :-)
So long,
Martin
Moin,
das lässt mich irgendein Escaping-Problem vermuten, das ich am gezeigten Code aber nicht nachvollziehen kann. Denn wenn dieser String in einer textarea vorkommt, ist es ja nichts weiter als Text. Die Behandlung mit htmlspecialchars() ist auch richtig an der Stelle (und ENT_QUOTES innerhalb einer textarea nicht unbedingt nötig) - warum also sollte das ein Fehlverhalten auslösen?
Tja, das wäre meine Frage. Vor allem da, außer eben der Start einer Session, jeglicher PHP und HTML Code angenommen wird.
Wenn du beim Absenden einen 403er bekommst, muss ja die Ziel-URL, an die das Formular verschickt wird, irgendwie problematisch sein. Was also kommt für $_SERVER['PHP_SELF'] tatsächlich beim Client an?
Als $_SERVER['PHP_SELF'] kommt korrekter weise "/files.php" an.
Leider hilft mir der Code da nicht wirklich weiter ...
Was würdest du noch benötigen?
Copy'n'Paste Error? Das ist zweimal derselbe Schnipsel. :-)
Das ist vollkommen richtig. Hier das zweite Schnipsel:
if(isset($_POST["action"])&&$_POST["action"]=="editsure"&&$config["edit"]==1&&$_POST["subbut"]=="Save") {
if($_POST["newcontent"]==""){file_put_contents($_POST["filename"], "");print '<span class="message">The file was edited successfully.</span>';}
elseif(file_put_contents($_POST["filename"], stripslashes($_POST["newcontent"]))) {
print '<span class="message">The file was edited successfully.</span>';
} else print '<span class="error">Error while editing this file.</span>';
}
Grüße Marco
Hi,
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset> <textarea cols="60" rows="15" name="newcontent">'.htmlspecialchars(file_get_contents($_POST["filename"]), ENT_QUOTES).'</textarea><br /> <input type="hidden" name="action" value="editsure" /><input type="hidden" name="filename" value="'.$_POST["filename"].'" /> <input type="submit" name="subbut" value="Save" style="float:left;" /><input type="submit" name="subbut" value="Cancel" /> </fieldset></form>';
}
welchen Wert hat $\_POST["filename"] hier? Ist es wirklich ein Dateiname?
Der müsste ja auch als value-Attribut des Hidden-Feldes "filename" ablesbar sein. Hier fehlt übrigens das Escaping: Was ist, wenn $\_POST["filename"] aus irgendeinem dummen Grund mal ein Anführungszeichen enthält?
Oder versuchst du hier versehentlich, per HTTP auf die gewünschte Datei zuzugreifen? Dann würdest du im Falle einer PHP-Datei nicht das Script selbst bekommen, sondern eine neue PHP-Instanz mit eben diesem Script starten und dessen Ausgabe bekommen.
Allerdings hätte dir das dann anhand anderer PHP-Scripte schon auffallen müssen.
So long,
Martin
--
Besteht ein Personalrat aus nur einer Person, erübrigt sich die Trennung nach Geschlechtern.
(aus einer Info des deutschen Lehrerverbands Hessen)
Selfcode: fo:) ch:{ rl:| br:< n4:( ie:| mo:| va:) de:] zu:) fl:{ ss:) ls:µ js:(
Moin,
welchen Wert hat $_POST["filename"] hier? Ist es wirklich ein Dateiname?
Ja, das ist korrekt. Mein Skript zeigt den Inhalt eines Verzeichnisses an, und hinter den Dateinamen die entsprechend verfügbaren Aktionen. Wenn man auf bearbeiten klickt, öffnet sich dieses Formular. Da der Dateiname bei Windows (und meines Wissens auch bei Linux) kein doppeltes Anführungszeichen enthalten darf ist das kein Problem.
Ein Problem gäbe es allerdings, wenn jemand die POST-Daten manuell verändert, von daher werde ich das noch ändern.
Oder versuchst du hier versehentlich, per HTTP auf die gewünschte Datei zuzugreifen? Dann würdest du im Falle einer PHP-Datei nicht das Script selbst bekommen, sondern eine neue PHP-Instanz mit eben diesem Script starten und dessen Ausgabe bekommen.
Nein, den Inhalt der Datei lese ich mit file_get_contents()
direkt per PHP auf dem Server ein.
Wenn du Lust hast, kannst du ja mal das komplette Skript ausprobieren.
Grüße Marco
Hallo Marco,
um das von Dir angesprochene Problem habe ich mich noch nicht gekümmert, aber bitte ersetze
$_SERVER['PHP_SELF']
durch
$_SERVER['SCRIPT_NAME']
oder einfach
action=""
if(isset($_POST["action"])&&$_POST["action"]=="edit"&&$config["edit"]==1) {
print ' <form action="'.$_SERVER['PHP_SELF'].'" method="post"><fieldset> [...]
Die Verwendung von $\_SERVER['PHP\_SELF'] stellt eine Sicherheitslücke dar, siehe z.B. die Links in [diesem Archivbeitrag](/archiv/2009/10/t191215/#m1275088).
Freundliche Grüße
Vinzenz
Tach!
Die Verwendung von $_SERVER['PHP_SELF'] stellt eine Sicherheitslücke dar,
Nicht die Verwendung an sich stellt eine Sicherheitslücke dar, sondern die Verwendung ohne htmlspecialchars() - wie bei allem, was man in den HTML-Kontext einfügt.
dedlfix.
Moin,
Die Verwendung von $_SERVER['PHP_SELF'] stellt eine Sicherheitslücke dar, siehe z.B. die Links in diesem Archivbeitrag.
Die Darstellung in dem Blogbeitrag ist nicht ganz richtig. Die Standardeinstellung von einem Apache-Webserver im Bezug auf die Direktive "AcceptPathInfo" ist "default". Das bedeutet, dass der jeweilige Handler entscheidet, ob der Zugriff zugelassen wird oder nicht. Bei gewöhnlichen Dateien ist der Handler so konfiguriert, dass er es standardmäßig abweist. Nur bei speziellen Skripten, wie cgi oder isapi werden die Zugriffe standardmäßig zugelassen.
Und selbst wenn die Direktive auf "on" stehen würde, könnte man sie mittels .htaccess für seinen Webspace überschreiben.
Das Sicherheitsproblem liegt hier also eher an der Konfiguration des Servers.
Trotzdem danke für den Hinweis; SCRIPT_NAME ist grundsätzlich unanfällig für externe Veränderungen, von daher habe ich es im Skript auch verändert.
Grüße Marco