• Jetzt anmelden. Es dauert nur 2 Minuten und ist kostenlos!

_GET, _POST, _SESSION, _COOKIE was ist wo und wann sicher?

wessei

Neues Mitglied
hab zur zeit ein projekt am lafen und wie es der zufall so will hab ich im internet gelesen das man variable die per _GET, _POST, _SESSION, _COOKIE verändern kann.
was ist dan demnach am sichersten?

in meiner seite werden _GET, _POST und _SESSION verwendet.

wie kann ich diese variablen sicher machen und überprüfen.

z.b index.php?id=1 wird ja per _GET übergeben was ist wenn man in der url stadt 1 eine 2 macht
kann ich dies vordefinieren und überprüfen erst dan ausgeben.

z.b in einem formular werden grundsätzlich ber _POST übergeben. gibt es dazu eine javascript funktion die zum beispiel die hässlich grauen buttons durch einen normalen link ersetzt und dessen daten nicht durch ein <form> zu übergeben?

zu _SESSION wo wird diese gespeichert und definiert bzw. ist diese sicher und wie verhalten sich diese bei veränderungen?

zu _GOOKIES weis ich die werden clientseitig gespeichert deshalb will ich diese heher vermeiden

mir ist klarr das manche _GET nicht ausbleiben werden wegen verschiedenen mitgliederlisten und das menü selbst darauf aufgebaut wurde. es wurde durchaus auch erwähnt die dateinamen in einem array() oder mysql zu definieren. ist da was wahres dran?

freu mich schauf eure antwort und danke schon im vorraus

mfg. wessei
 
Werbung:
Welcher Übertragungsweg am geeignetsten ist kann man pauschal nicht sagen. Mir fällt nur ein Tipp ein: übernimm nie Variablen aus einem der Arrays ungeprüft in deine Programmierung.

Falsch:
PHP:
<?php
if( $_POST["loeschen"] ) { unlink("datei.php"); }
?>

Richtiger:
PHP:
<?php
$loeschen = $_POST["loeschen"];
if( $loeschen == 1 ){ unlink("datei.php");
?>

In manchen Fällen sollte man auch mit Securecodes als zweite Sicherung arbeiten.

PHP:
<?php
$loeschen = $_POST["loeschen"];
$sec = $_POST["loeschen_sec"];
if( $loeschen == 1 && $sec == "abcd" ){ unlink("datei.php");
?>

Per GET sollte man so etwas natürlich wiederum nicht übertragen.
 
Sicher und Unsicher sind sie alle gleichzeitig.

Nehmen wir ein Beispiel eines Login-Formulares:

Code:
<form action="login.php" method="POST">
  <table>
    <tr>
      <td>Loginname:</td><td><input type="text" name="loginname" /></td>
    </tr>
    <tr>
      <td>Passwort:</td><td><input type="password" name="password" /></td>
    </tr>
    <tr>
      <td></td><td><input type="submit" name="submit" value="Einloggen" /></td>
    </tr>
  </table>
</form>

Nun..

$_POST wird befüllt mit..

$_POST[ 'loginname' ]
$_POST[ 'password' ]
$_POST[ 'submit' ]

Sogesehen nichts schlimmes daran.. wenn jeder sich an die Regeln hält.. sagen wir, wir überprüfen ob der Benutzername und Passwort überhaupt richtig sind:

PHP:
$sql = mysql_query( 'SELECT * FROM `users` WHERE `loginname`="'.$_POST[ 'loginname' ].'" AND `password`="'.$_POST[ 'password' ].'" ' );
..
..

sieht nicht schlecht aus..

Nehmen wir aber an das der User beim Loginnamen folgendes eingegeben hat:

administrator" AND 1=1;#


dann sieht die Query für MySQL folgend aus:

PHP:
SELECT * FROM `users` WHERE `loginname`="administrator" AND 1=1;# `password`="rammstein"

; bedeutet Ende der Query
# bedeutet "alles dahinter sind Kommentare, ignoriere sie"

Also im Endeffekt fragt er die Datenbank, ob es einen User "administrator" gibt und 1 gleich 1 ist ( ja es ist IMMER -true/wahr- ).

Damit gibt die Query normalerweise genau 1 Zeile wieder undzwar die vom Administrator und falls im Code einfach abgefragt wird, ob mindestens 1 Ergebniss gibt, dann ist man auch eingeloggt..

..den Vorgang nennt man Cross-Side-Scripting ( XSS ) welches einer der bekanntesten Sicherheitslücken im Code ist.


Wie du dich schützen kannst? Einfach!

Mehrere möglichkeiten:

Alles was garantiert eine Zahl sein soll, z.B. $_POST[ 'id' ] ( ID's sind normalerweise Zahlen ) , bei dennen machst du folgendes

PHP:
$id = intval( $_POST[ 'id' ] );

Alles andere kannst du zwei möglichkeiten machen:

PHP:
$loginname = mysql_real_escape_string( $_POST[ 'loginname' ] );
$loginname = htmlentities( $_POST[ 'loginname' ] );

Ich würde dir erstes empfehlen.
 
Werbung:
Nun, an Sessions kommt man aber wesentlich schwerer ran als an $_GET oder $_POST.
Überprüfung ist da alles.

Übergibt man z.B. eine Zahl, könnte man mit is_numeric() alles abwürgen, was nicht Zahl ist. Dabei gillt 1 gleich "1".
Um sicherzustellen, das Zahlen übergeben werden könnte man auch auf eine einfache Rechnung zurückgreifen:

PHP:
$b = $_POST['zahl'] * 1;

PHP:
$a = 1;
$b = "1";
$c = "test";

echo ($a * 1)."<br>";
echo ($b * 1)."<br>";
echo ($c * 1)."<br>";
 
Zuletzt bearbeitet von einem Moderator:
Das ist eine schöne Darstellung (zorndyuke). Das SQL-Problem nennt sich aber SQL-Injection. Cross-Site-Scripting (XSS) ist schematisch allerdings ähnlich. Es geht in beiden Fällen um Kontextwechsel-Problematiken.

- Artikel:Kontextwechsel

Es ist entscheidend, die passende Escaping-Funktion für den jeweiligen Kontextwechsel anzuwenden.

Benutzereingabe nach SQL (Gefahr: SQL Injection) → mysql_real_escape_string, intval, (int), …

Benutzereingabe nach HTML-Ausgabe (Gefahr: XSS) → htmlspecialchars, htmlentities

Die fett gedruckte Funktion klappt dabei jeweils immer (na ja, wenn die alte mysql-Erweiterung für DB-Zugriffe verwendet wird) und ist deshalb vorzuziehen.
 
Naja aufs XSS'ing wollte ich ursprünglich hinaus, da kam die SQL-Injection einfach super dazu und weiter hab ich nicht nachgedacht. Ich bin aber auch Hundemüde und schreibe teils im Kaffee Suff^^
 
Werbung:
mit den sessions ist es so, dass bei session_start() ein cookie mit einer id beim nutzer gespeichert wird. die werte werden serverseitig gespeichert und mit der id verknüpft. post wird mt einem formular erzeugt und wird an alle aufrufenden seiten einer domain weitergegeben, solange nur mit links, javascript, vor oder zurück auf der seite navigiert wird. get wird in der url übermittelt.
 
das heist wie kann ich bei einem login prüfen das es nur zahlen (0-9) und buchstaben (a-z, ä, ö, ü) möglich sind. Sowas wie ( !, ", §, $, %, &, /, (, ), =, ?, `, {, [, ], }, \, ´, +, *, ~, #, ', ;, ,, ., :, -, _, und andere zeichen solln unterbunden werden sowie chinesische, japanische, etc. zeichen auch.

dann noch wie kann ich es bei der registrierung schon überprüfen ob es sich um einen korrekten namen, pw und E-mail handelt?

mfg. wessei
 
PHP:
//Überprüfen, ob andere Zeichen als erlaubte vorhanden sindd
if(!preg_match("/[^a-z0-9äöü]+/i",$eingabe)){
    echo "Alles OK!";
}
else{
    echo "Fehler. Unerlaubte Zeichen verwendet!";
}
// E-Mail Überprüfung
if (preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/i", $email)){ 
echo "E-Mail-Syntax richtig!"; 
}else{
echo "E-Mail falsch!";
}
 
Zuletzt bearbeitet:
Werbung:
PHP:
//Überprüfen, ob andere Zeichen als erlaubte vorhanden sindd
if(!preg_match("/[^a-z0-9äöü]+/i",$eingabe)){

Doppelte Verneinung? Das Pattern könnte wohl auch „positiv“ geschrieben werden: Wenn Eingabe entspricht /^[a-z0-9äöü]+$/i, dann Eingabe zulässig.

Warum aber diese Einschränkung?

Muster für E-Mail-Adressen… Hm, ja. Du kannst als „Service“ für den Nutzer testen, ob auch etwas wie eine E-Mail-Adresse in das Feld eingetragen wurde (und nicht im Eifer des Gefechts vielleicht der Name), aber falsche E-Mail-Adressen zu filtern, ist nicht so leicht. [noparse][email protected][/noparse] einzutragen, ist ja kein großes Problem.

Immer einen Blick wert: http://php.net/manual/en/book.filter.php
 
hallo,

$_REQUEST, $_POST, $_GET und $_SERVER müssen vor der weiterverarbeitung auf schadcode geprüft werden.
$_SESSION muss vor hijacking geschützt werden


pregmatch ist für die sicherheit nicht von bedeutung. hier lese ich in den meisten tutorials immer, dass man es unbedingt verwenden sollte.
die tatsache, dass php für die standardwerte: e-mail, text ohne html, text ohne sql injection, primitive datentypen usw.. schon funktionen mitliefert, macht pregmatch da sehr uninteresannt und unnötig kompliziert.

für die überprüfung von zahlen bieten sich z.b. die casts an: (int) (float), dabei stellt man sogar den typ der eingabe sicher, um keine probleme bei einem serialize zu bekommen.
habe übrigens noch keinen vollständigen pregmatch für e-mails gefunden.... glaube kaum, dass man hier ohne eine tld whitelist auskommt.

beim loginbeispiel ist es sogar nicht förderlich. wieso sollte ich meinem user verbieten chinesische zeichen zu verwenden? macht das ganze doch nur sicherer!
Beim passwort kann man sogar alle zeichen erlauben auch html und sql... es wird idealerweise per md5 verschlüsselt und in einen alphanumerischen string umgewandelt:
PHP:
$pw = md5("'); truncate tabele xyz; <script>");


bitte nicht vergessen, dass felder mit einer url als daten typ auch überprüft werden müssen! ping senden... ip abfragen, url auseinandernehmen überprüfen und wieder zusammensetzen... manche experten basteln hier unglaubliche get anfragen wie z.b. index.php?a=[avc]="abc"||id=<§$%&/`´... sowas würde ich einfach ignorieren und nicht akzeptieren. urlencode hilft hier auch.


wann und wie die variablen gefüllt werden und die tatsache, dass es einfache arrays sind, kann man leicht prüfen:

PHP:
echo $_POST['test'];

echo $_REQUEST['test'];

echo $_POST['test'] = "123";

setcookie("TestCookie", "1234");
echo $_COOKIE("TestCookie");


gruß
 
Zuletzt bearbeitet von einem Moderator:
idealerweise mit md5 verschlüsselt
für md5 existieren rainbow tables, deshalb sollte das schonmal nicht verwendet werden. es gibt hier gerade noch einen anderen thread, wo schon diskutiert wird, wie passwörter verschlüsselt werden sollten und wie es mit der sicherheit aussieht.
 
Werbung:
md5 ist keine Verschlüsselung, sondern ein Hashing-Verfahren. md5 ist nicht umkehrbar („entschlüsselbar“).

Siehe dazu auch hier im Wiki: Sicherheit von Webanwendungen

Allgemein noch mal zum Thema: Der Schutz vor Schadcode ist nur ein Nebeneffekt. Das sind alles allgemeine Kontextwechsel-Problematiken (#5), die immer beachtet werden müssen, wenn ein Kontextwechsel stattfindet (Nutzereingaben in SQL-String, DB-Rückgaben in HTML, …). Da gibt es gewisse Regeln, so was richtig zu machen. Mehr ist das nicht. Schutz vor Angriffen, die „Fallstellen“ zwischen Kontexten ausnutzen, erfolgt damit automatisch.
 
Was ja immer den Eindruck erweckt, man könnte MD5 umdrehen und den Text aus dem der Hash generiert wurde wieder herstellen. So ist das aber nicht. Die NICHT UMKEHRBARKEIT ist es, was MD5 so wertvoll macht.
Dass da irgendwann mal jemand eine Datenbank mit tausenden von MD5 Hashes angelegt hat, hat ja mit decodierung nichts zu tun. da wird schlicht nachgesehen, ob es den Hash schon gibt und was der ursprüngliche Text war.
Das sollte jedem klar sein, der solche Datenbanken abfragt. Generell finde ich die Dinger aber wiederum ganz gut, da man den eigenen Hash testen kann....

Um Mailadressen zu prüfen habe ich auch noch keine wirklich funktionierende Lösung gefunden. Je nach Konfiguration des Mailservers können Adressen, die die Prüfung bestehen, durchaus als nicht zustellbar abgeurteilt werden.
Meine eigene Prüfung sieht so aus:
PHP:
if(!preg_match( '/^([a-zA-Z0-9_-])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/' , $an)) 
{
   $_SESSION['fehler'] = "Mailadresse nicht gültig....";
}
Ich lasse eine ganze Menge an (lt. Rfc) gültigen Zeichen hier zwar nicht zu, aber die Prüfung harmoniert mit 99,9% der Mailserver die ich kenne.
 
Werbung:
Was ja immer den Eindruck erweckt, man könnte MD5 umdrehen und den Text aus dem der Hash generiert wurde wieder herstellen. So ist das aber nicht. Die NICHT UMKEHRBARKEIT ist es, was MD5 so wertvoll macht.
Dass da irgendwann mal jemand eine Datenbank mit tausenden von MD5 Hashes angelegt hat, hat ja mit decodierung nichts zu tun. da wird schlicht nachgesehen, ob es den Hash schon gibt und was der ursprüngliche Text war.
Das sollte jedem klar sein, der solche Datenbanken abfragt. Generell finde ich die Dinger aber wiederum ganz gut, da man den eigenen Hash testen kann....

Um Mailadressen zu prüfen habe ich auch noch keine wirklich funktionierende Lösung gefunden. Je nach Konfiguration des Mailservers können Adressen, die die Prüfung bestehen, durchaus als nicht zustellbar abgeurteilt werden.
Meine eigene Prüfung sieht so aus:
PHP:
if(!preg_match( '/^([a-zA-Z0-9_-])+([\.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-]+)+/' , $an)) 
{
   $_SESSION['fehler'] = "Mailadresse nicht gültig....";
}
Ich lasse eine ganze Menge an (lt. Rfc) gültigen Zeichen hier zwar nicht zu, aber die Prüfung harmoniert mit 99,9% der Mailserver die ich kenne.
PHP:
/*
    user data - email
*/
function email_cleanup($email)
{
    $email = trim($email);
    if(filter_var($email, FILTER_VALIDATE_EMAIL) === false)
    {
        return false;
    } 
    else
    {
        return $email;
    }
}

so kann ich den quellcode auch lesen :)
 
ja das pw ist bei mir schon sicher und _POST naja muss da noch ein paar änderungen machen.

das problem was ich noch hab ist _GET

PHP:
  //Wenn man keine Seite angegeben hat, ist man automatisch auf Seite "user"
  $content = (isset($_GET['page'])) ? $_GET['page'] : "user";
   switch($content){
    case "user":
    include("user/user.php");
    break;
    case "bearbeiten_bild":
    include("user/avatar.php");
    break;
    case "bearbeiten_daten":
    include("user/daten.php");
    break;
    default:
    include("user/user.php");
    break;

so hab ichs zur zeit stehn

wie kann ich z.B: einen link der wie folgt aussieht darin abfragen wenn ich über _GET 2 oder mehr variablen weitergebe

"index.php?page=user&id=<?php echo $row['ID'] ?>"

also möchte ich mit diesem link die seite (page) --> user ausgeben und mit id die ID des Users ausgeben.
weis allerdings nicht ob der link korrekt ist wie ich ihn schon geschrieben hab.
dieses problem hab ich zur zeit in mehreren funktionen

mfg. wessei
 
Werbung:
naja ich rufe den link per "index.php?page=user" und die ID des users "id=<?php echo $row['ID'] ?>" auf.
brauche deswegen _GET['page'] zum auslesen der seite für die user und dan brauch ich in der userseite _GET['id'] zum auslesen der userid in der datenbank.

wie kann ich in der content wo ausgelesen wird welche seite angzeigt anzeigen soll die id des users mitgeben und den entsprechenden link dazu


mfg. wessei
 
Zurück
Oben