GET Parameter - Sicherheit

versuch13

Erfahrenes Mitglied
Hi. Was muss man beachten wenn man GET Parameter weiter verarbeitet? Muss ich da mit rawurldecode o.ä. ran? Ich weiß einfach nicht was man da an Zeichen alles einschleusen könnte. Vielleicht hat dazu jemand Informationen, vor was muss man sich in acht nehmen?

Um auch ein kleines Beispiel zu geben. Eine Tagcloud. Im groben sieht das etwa so aus:

Die Tags werden ausgegeben
PHP:
echo '<a href="/tags/'. rawurlencode(strip_tags($_GET['tag'])) .'/">'.$_GET['$tag].'</a>';

Im optimal Fall entsteht dann eine URL die wie folgt aussieht

domain.de/tags/dasVorhandeneTag/

die URL wird auseinander genommen und ich habe dann das Tag in einer
Variable:

$tag = "dasVorhandeneTag"

dieses wird auf der Seite ausgegeben und auch in MySQL Abfragen genutzt.
Vor einer MySQL Anfrage nutze ich mysql_real_escape_string(), vor der Ausgabe
mit echo nutze ich htmlentities()


Jetzt kann natürlicher jemand der böses will, eventuell einen Aufruf wie

domain.de/tags/böseZeichen/

aufrufen. Ich kenn mich da nicht ausreichend aus um zu wissen welchem Möglichkeiten
einem Angreifer zur Verfügung stehen daher weiß ich auch nicht wie es einem Angriff vorbeugen kann. Also die Frage, wie schütze ich mich ausreichend gegen Angriffe über GET Parameter ab?

Bei meiner Recherche bei aus der ich leider nicht richtig schlau wurde, habe ich teilweise auch gelesen man solle urlencode Funktionen
auf Formulardaten anwenden? Und in Fällen wo Daten per xmlhttprequest versendet werden? Wann genau muss man es nun einsetzen?


Vielen Dank. Grüße
 
Zuletzt bearbeitet:
Also ich nutze für meine URLs den URL-Helper von CodeIgniter.

Das macht aus:

Hier ist mein Title

domain.com/article/hier-ist-mein-title

Ich decode es nicht sondern mache in meiner abfrage einfach folgendes:

Code:
SELECT * FROM articles WHERE url_title= '$db->escape($url_title)'

db_escape ist halt mysql_real_escape

Um genau zu sein und um doppelte Artikel auszuschließen habe ich das ganze so gemacht:

PHP:
// Übergeben wird: domain.com/article/2007-12-03/artikelverzeichnis-pagerank

$url_title = 'artikelverzeichnis-pagerank'; // Wird geholt mit GET o.Ä.
$url_date = '2007-12-03';

$query = "SELECT * FROM articles WHERE url_title= ".$db->escape($url_title)." AND DATE(date) = ".$db->escape($url_date)."";

So klappt das ganze bei mir sehr gut
 
Wie Benutzereingaben zu behandeln sind, hängt davon ab, was damit geschieht. Du hast eigentlich schon die wichtigsten Maßnahmen zum Schutz vor Einschleusen von Schadcode genannt: bei der Verwendung in einer MySQL-Abfrage die mysql_real_escape_string()-Funktion, bei HTML die htmlentities()-Funktion (wobei auch htmlspecialchars() ausreicht) und bei URLs die rawurlencode()-Funktion.
Wichtig ist es dabei immer die jeweilig gültigen Metazeichen zu kennen und beachten, die schließlich auch die Wahl der Schutzmaßnahmen bestimmen.
 
Wie Benutzereingaben zu behandeln sind, hängt davon ab, was damit geschieht. Du hast eigentlich schon die wichtigsten Maßnahmen zum Schutz vor Einschleusen von Schadcode genannt: bei der Verwendung in einer MySQL-Abfrage die mysql_real_escape_string()-Funktion, bei HTML die htmlentities()-Funktion (wobei auch htmlspecialchars() ausreicht) und bei URLs die rawurlencode()-Funktion..

Ok, das ist schon mal gut zu hören. Aber muss irgendwann auch rawurldecode angewendet werden oder ist das überflüssig?

Wichtig ist es dabei immer die jeweilig gültigen Metazeichen zu kennen und beachten, die schließlich auch die Wahl der Schutzmaßnahmen bestimmen.

Genau hier liegt das Problem. Ich weiß zum Beispiel nicht ob und wie ich damit umgehen muss wenn per $_GET Variable ein ' oder %27 ankommt, wird das %27 auch mit einem Backslash maskiert?- ok das kann ich auch einfach mal ausprobieren. Aber welche Zeichen sind die wichtigsten zu maskierenden? Sollte man MySQL Keywords wie SELECT o.ä. ganz verbieten. Das # Zeichen birgt Gefahr oder nicht? Kann man sich irgendwo einen guten Überblick verschaffen?

Danke
 
Metazeichen sind Zeichen, die im jeweiligen Kontext eine besondere Funktion haben. Klassisches Beispiel sind Anführungszeichen (auch in PHP): Der folgende Satz soll als Zeichenkette ausgezeichnet werden:
Andrea fragte mich: "Hast du Grass' 'Blechtrommel' gelesen?"
Da sowohl die einfachen als auch doppelten Anführungszeichen zur Auszeichnung von Zeichenketten genommen werden können, sind folgende Auszeichnungen möglich. Die als Auszeichnungszeichen gewählten Anführungszeichen müssen innerhalb der auszuzeichnenden Zeichenkette aber maskiert werden, damit sie nicht die Funktion als Auszeichnungszeichen einnehmen:
PHP:
// ungültig
'Andrea fragte mich: "Hast du Grass' 'Blechtrommel' gelesen?"' // "
                                   ^
"Andrea fragte mich: "Hast du Grass' 'Blechtrommel' gelesen?""
                     ^
PHP:
// dagegen gültig
"Andrea fragte mich: \"Hast du Grass' 'Blechtrommel' gelesen?\""
'Andrea fragte mich: "Hast du Grass\' \'Blechtrommel\' gelesen?"'
Ähnliches gilt auch bei anderen Sprachen wie beispielsweise bei MySQL- oder JavaScript-Zeichenkettenauszeichnungen.

In HTML ist es beispielsweise das Kleiner-als-Zeichen, das den Beginn eines HTML-Tags beschreibt. Soll dieses Zeichen nicht diese Funktion haben, muss es maskiert werden und durch eine Zeichenreferenz ersetzt werden.

Man muss also die Regeln und Metazeichen der jeweilige Sprache und des jeweilige Kontextes genau kennen.
 
Wenn du sichergehen willst, das niemand die "URL" die per get übertragen wird bearbeitet würde ich die den "Querystring"
Code:
http://domain.de/datei.php?x=1&y=2
codieren:
Code:
http://domain.de/datei.php?do=ZVd0p3E4IjVvp2/kT0YjSjhULnQyOA==

bei diesen beispiel wurde, von mir ein Crypt Tool und Base64 genutzt.

Dabei würde nach Übertragung von do erst einmal der Inhalt wieder decodiert und decryptet.
Danach werden die Inhalte in einen Array geschrieben.

dadurch habe ich keine Probleme, die Daten der User die ggf. Sql Injection versuchen abzuhalten es zu können. Natürlich würde ich sicherheitshalber, trotzdem, da wo es von Nöten ist escapen, besonders in der Mysql abfrage, da man ja nicht weiß ob doch einer mein Passwort in der Verschlüsselung knackt... das gleiche gilt natürlich auch für Daten die aus der DB gelesen werden (html...).

aber dabei würden nun halt deine "SEO" Funktionen nicht mehr zu tragen kommen ;D
 
...

Man muss also die Regeln und Metazeichen der jeweilige Sprache und des jeweilige Kontextes genau kennen.

Danke für die ausführliche Erklärung! Also bin ich ja mit meinen Maskierungen soweit schon mal ganz gut abgesichert.


aber dabei würden nun halt deine "SEO" Funktionen nicht mehr zu tragen kommen ;D

Genau. Trotzdem danke für deinen Vorschlag. Aber ist das nicht sowieso übertrieben? Wenn ich die GET Parameter bevor ich sie weiterverarbeite, ausgebe oder in einer Datenbank speichere, besteht doch eigentlich kein Bedarf mehr sich noch weiter abzusichern?


Vielen Dank.
 
Zurück