Sicherheit in PHP
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
aktion
beispiel
datei
datum
ende
formular
host
http
image
inhalt
jemand
methode
post
programm
rechner
server
string
test
unterschied
zeichen
-
Hallo Leute, hab was gfunden mit dem man lernt halbwegs sicher PHP zu programmieren:
Serverseitige Scripte koennen auf einem Server ein Scheunentor einer
Sicherheitsluecke aufreissen. In diesem Text werde ich ein paar Tips zum
besten geben, was man bei der Programmierung von PHP Scripts beachten
sollte und was man zusaetzlich tun kann um boesen Buben auf die Finger
schauen/klopfen zu koennen.
GET & POST
==========
Kaum einer weiss eigetlich so richtig was der Unterschied zwischen den
Methoden GET und POST ist. Die gefinition laut Self HTML ist wie folgt:
ZITAT: Stefan Muenz SELFHTML Version 7.0 \"Formular definieren\" -->
tcha.htm#a2
Wenn Sie method=get wählen, werden die Daten des ausgefüllten Formulars
auf WWW-Servern mit installiertem HTTP-Protokoll in der CGI-
Umgebungsvariablen QUERY_STRING gespeichert (method = Methode, get =
bekommen). Das CGI-Programm muß den Inhalt dieser Umgebungsvariablen
auslesen und verarbeiten.
Wenn Sie method=post wählen, werden die Daten des augefüllten Formulars
auf dem Server-Rechner von \"stdin\" zur Verfügung gestellt, und das CGI-
Programm muß sie behandeln wie eine Benutzereingabe, die auf der
Kommandozeile gemacht wurde (post = verschicken). Da in diesem Fall
kein EndOfFile-Signal (EOF) gesendet wird, muß das CGI-Programm die
CGI-Umgebungsvariable CONTENT_LENGTH auslesen, um die Länge der
übermittelten Daten und damit deren Ende zu ermitteln.
ZITAT ENDE
In der Regel ist es bei PHP egal welche Methode man verwendet. Jedoch
wuerde ich immer zu POST raten da:
a) die Daten genauso wie bei GET gehandelt werden
b) bei GET Datenlaenge auf die laenge des Referer des Browsers beschraenkt
ist
c) die Variablennamen und deren Inhalte NICHT in der Addressleiste
erscheinen
Im Gegensatz zu GET ist es bei POST nicht ganz so einfach bei einer
Bruteforce Attacke, die Variableninhalte auszutauschen, denn was nicht
angezeigt wird kann auch nivht veraendert werden. Meiner Einschaetzung nach
gilt das aber nur fuer Scriptkiddies oder Beginner, die sich nciht die
Muehe machen wuerden ein eigenes Tool fuer solch eine Aktion zu schreiben.
Ich habe hier einmal den Header des Browsers bei beiden Methoden
aufgelistet:
GET
GET /test.php?ZAHLEN=1234567890 HTTP/1.0
Referer: http://127.0.0.1/test.php
Connection: Keep-Alive
User-Agent: Mozilla/4.73 [de] (Win98; U)
Host: 127.0.0.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png,
*/*
Accept-Encoding: gzip
Accept-Language: de
Accept-Charset: iso-8859-1,*,utf-8
POST
POST /test.php HTTP/1.0
Referer: http://127.0.0.1/test.php
Connection: Keep-Alive
User-Agent: Mozilla/4.73 [de] (Win98; U)
Host: 127.0.0.1
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, image/png,
*/*
Accept-Encoding: gzip
Accept-Language: de
Accept-Charset: iso-8859-1,*,utf-8
Content-type: application/x-www-form-urlencoded
Content-length: 17
ZAHLEN=1234567890
Schon alleine wenn man sich den rot unterlegten Text anschaut wird einem
der unterschied klar. Bei POST muss man die Daten hinter dem Header her
schicken und nicht enfach bequem in die URL einbauen. Die erklaert auch
warum GET auf eine bestimmte groeße begrenzt ist. Bei POST gibt das
Attribut \"Content-length: 17\" gibt die laenge der Nachgesendeten Daten
(inklusive Variablen-/Feldernamen) an. Dies macht es fuer unwissende nicht
umbedingt sehr einfach, schon alleine weil man sich erstmal mit dem HTTP
vertraut machen muss. Also keine 100% Absicherung, aber Menschen neigen ja
dazu jeden noch so kleinen Ast zu ergreifen um nicht unter zu gehen.
Doch sollte jemand auf die Idee kommen die Feldernamen herauszupicken und
die ganze Sache mit einem Programm ueber GET laufen zu lassen, was ist
dann?
Keine Panik, in diesem Fall koennen wir die PHP interne Variable,
$REQUEST_METHOD. Diese enthaelt dann in upcase Letter (Grossbuchstaben)
entweder den Wert GET oder POST. Alles was wir jetzt noch benoetigen ist
eine kleine If-Clause und schon koennen wir die Aktion von aussen
angemessen behandeln.
SAMPLE SOURCE:post_check.php
<?
if($REQUEST_METHOD != \"POST\")
die(\"Hier wird nur gepostet!\");
echo \"Hier geht die Post ab!\";
?>
Das obige Beispiel ist nur kurz zur Veranschaulichung gedacht und wuerde in
der Praxis bestimmt nicht so gehandhabt werden.
Error Parsing
=============
Wenn mal das ganze ein wenig zu paranoid sieht ist jede Eingabe durch den
Client eine Risiko fuer die Anwendung. Wenige Zeichen koennen genuegen um
Guestbooks/Foren unbrauchbar zu machen, in einem CSV Datenbestant die
integrietaet zu nichte zu machen, oder sogar um die kontrolle auf dem
gesamtmen Serversystem zu erlangen. Das mag sich vielleicht erstmal ein
wenig dumm und uebertrieben anhoeren, aber ich werde hier einmal ein
Beispielscript zeigen, wie es mit Sicherheit noch zu hauf im Internet zu
finden ist.
!VERY-BAD! SOURCE: printdata.php
<?
if($isset($data))
readfile($data);
else
echo \"Keine Datei zum ausgeben...\";
?>
Dies ist jetzt die warscheinlich trivialste Variante, jedoch aendert sich
nichts am Prinzip. Das Script soll lediglich die Datei, die durch die
Variable $data definiert wird, an den Client senden. Das waere zum Beispiel
bei Einer Textreihe gut denkbar, weil der Autor sich (warum auch immer)
nicht die Muehe machen wollte alle in HTML zu konvertieren. Nun denn,
zumindest erlaubt die Person uns jetzt netter Weise auf alle Datenbestaende
auf dem Rechner zu zugriefen. Nehmen wir (um dem ganzen noch die Krone
aufzusetzten) dazu noch an, dass der Webserver auf einem schlecht
konfiguriertem UNIX System laeuft. Wir Manipulieren die URL ein wenig...
SAMPLE
Vorher:http://www.host.de/printdata.php?data=text1.txt
Nacher:http://www.host.de/printdata.php?data=../../../../home/user
oder sogar:http://www.host.de/printdata.php?data=../../../../etc/shadow
So etwas sollte niemals passieren. Ein gut konfiguriertes Serversystem ist
mehr als die halbe Miete! Nun aber einmal zur Problem behebung. Wie folgt
wuerde das Script schon ein wenig besser aussehen:
!BAD! SOURCE: printdata.php
function chkstr($string)
{
if(($string[0] . $string[1]) == \"..\") return 1;
for($i=0;$i <= strlen($string);$i++)
if(($string[$i] == \"/\") || ($string[$i] == \"\\\")) return 1;
return 0;
}
if($isset($data))
{
$stat = chkstr($data);
if($stat != 0) die(\"Ungueltiger Dateipfad angegeben...\");
readfile($data);
}
else
echo \"Keine Datei angegeben...\";
Schon ein wenig sicherer. Ich persoenlich wuerde eine ganz andere Technick
anwenden, aber dazu ein anderes mal. Wenn man ein Guestbook hat mochte man
natuerlich vermeiden, dass jemand darin wie wild mit HTML oder gar
clientseitigen Scripten rumspielt. PHP4 bietet die Funktion
htmlspecialchars() die einen String auf Browsersensiebele Zeichen
untersucht, und diese in HTML-Code umsetzt. Dass heisst im klartext:
\"Keine Manipulationsmoeglichkeiten, da Sonderzeichen wie < oder > vom
Script als < bzw. > ausgeschreiben werden, und somit vom Browser als
brave Sonderzeichnen erkannt und angezeigt werden. Kein fremder Syntax
moeglich!\".
Externe Dateien
===============
Viele Lagern haeufig verwendete Funktionen aus und Laden Sie am Anfang des
Scripts. Diese koennen unter anderem Sensiebele Daten wie
Datenbankzugaenge, Passwoerter oder Systempfade enthalten. Deshalb ist es
besonders wichtig diese Dateien zu schuetzen. Die meisten verwenden als
Endung fuer solche Dateien \".inc\". Der Webserver erkennt diesen Dateitypen
(sofern nicht eingetragen) nicht als ein PHP-Script an und wuerde die
Gesamte Source ueber den Webserver zum Client schleusen, ganz unabhaengig
davon ob der Quelltext mit Kommentaren, PHP-Tags oder aenlichem markiert
ist. Aus diesem Grunde sollte man die externen Dateien, immer mit einer
beim Webserver als PHP-Script eingetragenen Dateiendung benennen:
Beispiele:
==========
test.inc.php
test.inc.php3
test.inc.php4
test.inc.phtml
So wird die Datei bei einem direktem Aufruf verarbeitet und der Quelltext
wird nicht preis gegeben.
<input type=\"hidden\">
=====================
Hidden Fields sind nciht umbedingt dazu gedacht etwas vor dem Client zu
verstecken. Das waere ziemlich unsinnig, da in der Source sowieso alles im
Klartext sichtbar ist. Geheime Daten sollte man lieber auf dem Server
zwischenspeichern.
Artikel ist von D.Wilson
Is glaub ich ganz brauchbar, mfg :-) Finch :-)
-
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Und was willst du uns damit sagen? Jeder der sich intensiv mit PHP beschäftigt ist das bekannt.
Keine Diskussionsgrundlage: closed. -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage