Sim: Sichere übergabe von Formalurdaten aus MySQL

Hallo an alle,

bezüglich Formularsicherheit habe ich da eine frage an euch und hoffe dass Ihr mir ein paar Tipps geben könntet!

Folgendes habe ich vor:

1. Daten werden per feste abfrage aus der MySQL Datenbank ausgegeben.
2. Die ausgegebenen Daten beinhalten ID, Name, Kategorie und einen Link.
3. Der Link ist nachher maßgebend wohin man weitergeleitet wird, ob zu einer meiner Seiten wo die Daten ID, Name und Kategorie weiterverarbeitet werden oder einfach nur zur Homepage desjenigen der in der Datenbank eingetragen ist.

Beispiel:

$id=mysql_result($resultabfrage,$i,"id");
$name=mysql_result($resultabfrage,$i,"name");
$kategorie=mysql_result($resultabfrage,$i,"kategorie");
$link=mysql_result($resultabfrage,$i,"linkverweis");

Ausgegebener Link ist beispielsweise mal: http://forum.de.selfhtml.org/

<form action="<?php if (isset($link)) echo htmlspecialchars(trim($link), ENT_QUOTES); ?>" method="post">

<input type="hidden" name="id" value="<?php if (isset($id)) echo htmlspecialchars(trim($id), ENT_QUOTES); ?>">

<input type="hidden" name="name" value="<?php if (isset($name)) echo htmlspecialchars(trim($name), ENT_QUOTES); ?>">

<input type="hidden" name="kategorie" value="<?php if (isset($kategorie)) echo htmlspecialchars(trim($kategorie), ENT_QUOTES); ?>">

Zu meiner frage, ist das Sicher oder habe ich noch etwas Wichtiges vergessen?

Danke für eure Antworten und freundliche Grüße,

Sim

  1. hallo

    Zu meiner frage, ist das Sicher oder habe ich noch etwas Wichtiges vergessen?

    Bei der Sicherheit kommt es eher darauf an, wie du die Daten auswertest, die du über Usereingaben bekommst und benutzen willst.
     Lässt du diese sicher in die Datenbank schreiben, ist eine erneute Sicherung bei der Ausgabe unnötig. (behaupte ich jetzt mal frech)

    <input type="hidden" name="id" value="<?php if (isset($id)) echo htmlspecialchars(trim($id), ENT_QUOTES); ?>">

    mal abgesehen von der Unnötigkeit, ids sind ja meistens nur Zahlen. Da reicht es auch vollkommen, sie mit intval() zu prüfen. diese Funktion gibt entweder die Zahl oder 0 zurück.

    --
    "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
    1. Hi!

      Zu meiner frage, ist das Sicher oder habe ich noch etwas Wichtiges vergessen?

      Sicherheit gibt es nicht in absoluter Ausführung. Bei Sicherheit muss immer gefragt werden, was oder wovor konkret abgesichert werden soll.

      Bei der Sicherheit kommt es eher darauf an, wie du die Daten auswertest, die du über Usereingaben bekommst und benutzen willst.
      Lässt du diese sicher in die Datenbank schreiben, ist eine erneute Sicherung bei der Ausgabe unnötig. (behaupte ich jetzt mal frech)

      Meinst du, dass es ausreicht, mysql_real_escape_string() oder ähnliches anzuwenden und gut ist? Oder meintest du, dass die Daten gleich für das irgendwann später mal verwendete Ausgabemedium aufbereitet in der Datenbank stehen sollen?

      Ersteres reicht nicht, weil für einen SQL-String andere Zeichen eine Sonderbedeutung haben als in einem HTML-Dokument oder einer URL. Das zweite ist im Allgemeinen ungünstig, weil die für die Maskierung im HTML- oder URL-Kontext zusätzlich eingefügten Zeichen als ganz normale Zeichen aus der Sicht der Datenbank gelten, und somit eine Sortierung oder andere Form der Stringverarbeitung beeinflussen.

      Es ist beser, eine Behandlung nur für den aktuellen Kontext vorzunehmen und im Gegenzug diese auch konsequent anzuwenden, als irgendwann in der Vergangenheit für irgendeine Verarbeitung oder Ausgabe in der Zukunft etwas vorzubereiten, von der man nicht unbedingt weiß, ob diese sich nicht vielleicht mal ändert. Benötigt man die Daten später in anderem Kontext, hat man sie in falscher Form vorliegen und muss erst umkodieren. Das ist der allgemeinen Übersicht nicht sonderlich dienlich, wenn man nun ständig aufpassen muss, wo welche Daten herkommen und wie diese bereits vorbereitet sind oder nicht.

      Lo!

      1. hallo,

        Meinst du, dass es ausreicht, mysql_real_escape_string() oder ähnliches anzuwenden und gut ist? Oder meintest du, dass die Daten gleich für das irgendwann später mal verwendete Ausgabemedium aufbereitet in der Datenbank stehen sollen?

        zweiteres.. nein. Ersteres schon eher. Wichtig ist dabei nur, die zu speichernden Daten so einfach wie möglich zu halten und ggf. mit Ids zu spicken, damit geregelt ist, wo es auftauchen soll. Nutzereingaben sollten nur als solche gespeichert werden, ohne HTML/PHP/JS/etc.-Klimbim drumherum oder mittendrin. Die Darstellung dessen wird dann mit PHP o.ä. zusammengesetzt und mit HTML angezeigt.
        Den Kontext zu wechseln sollte dann nicht mehr so schwer fallen.

        bis dann

        --
        "Sir! We are surrounded!" - "Excellent! We can attack in any direction!"
        1. Moin!

          Meinst du, dass es ausreicht, mysql_real_escape_string() oder ähnliches anzuwenden und gut ist? Oder meintest du, dass die Daten gleich für das irgendwann später mal verwendete Ausgabemedium aufbereitet in der Datenbank stehen sollen?

          zweiteres.. nein. Ersteres schon eher. Wichtig ist dabei nur, die zu speichernden Daten so einfach wie möglich zu halten und ggf. mit Ids zu spicken, damit geregelt ist, wo es auftauchen soll.

          Nein - deine Argumentation ist nicht nachvollziehbar und geht vollkommen in die falschr Richtung, würde ich meinen.

          Nutzereingaben sollten nur als solche gespeichert werden, ohne HTML/PHP/JS/etc.-Klimbim drumherum oder mittendrin. Die Darstellung dessen wird dann mit PHP o.ä. zusammengesetzt und mit HTML angezeigt.

          Nutzereingaben könnten Zeichen enthalten, die in HTML eine besondere Bedeutung haben.

          Den Kontext zu wechseln sollte dann nicht mehr so schwer fallen.

          Den Wechsel des Kontextes kann man sich nicht aussuchen, der ist einfach da aufgrund der Situation. Wenn man reinen Text in der Datenbank hat, und die Ausgabe in HTML erfolgen soll, wechselt der Kontext - Punkt. Man ist gezwungen, das zu berücksichtigen.

          - Sven Rautenberg

          1. Ein freundliches hallo an alle die mir geantwortet haben!

            Ich bedanke mich nachträglich für eure Anregungen, Hinweise, Kritiken und Tipps!!!

            Gruß,

            Sim

  2. Hi Sim.

    1. Die ausgegebenen Daten beinhalten ID, Name, Kategorie und einen Link.
    2. Der Link ist nachher maßgebend wohin man weitergeleitet wird, ob zu einer meiner Seiten wo die Daten ID, Name und Kategorie weiterverarbeitet werden oder einfach nur zur Homepage desjenigen der in der Datenbank eingetragen ist.

    Darf ich mal aus Interesse nach dem Zweck fragen? Einen Post-Request mit fest gewählten Parametern an vershiedene externe Ziele zu senden, scheint mir auf den ersten Blick nicht sinnvoll zu sein.

    $id=mysql_result($resultabfrage,$i,"id");
    $name=mysql_result($resultabfrage,$i,"name");
    $kategorie=mysql_result($resultabfrage,$i,"kategorie");
    $link=mysql_result($resultabfrage,$i,"linkverweis");

    Der Zugriff auf diese Daten geht effizienter als mit mysql_result, dazu würde ich also nicht raten.

    Ausgegebener Link ist beispielsweise mal: http://forum.de.selfhtml.org/

    Das ist ein URL, kein Link! Ein Link ist (in diesem Zusammenhang) ein Element eines HTML-Dokumentes. Dementsprechend sollte am besten Deine obige PHP-Variable auch nicht $link heißen, und das Datenbankfeld schon gar nicht Linkverweis. Dieses Wort gibt es meiner Kenntnis nach nicht mal.

    <form action="<?php if (isset($link)) echo htmlspecialchars(trim($link), ENT_QUOTES); ?>" method="post">

    Steht in der Datenbank bereits ein gültiger URL, sprich: eine URL-kodierte Zeichenkette? Wenn ja, dann brauchst Du hier nicht zu trimmen, weil diese keine Whitespace-Zeichen enthält. Wenn nein (und das wäre besser), dann musst Du

    • den String bei der Ausgabe URL-kodieren
    • Dir gut überlegen, ob Du ihn vorher trimmen willst. Wenn der URL einen Query-String (sprich: GET-Parameter) enthalten darf, dann kann die nicht url-kodierte Zeichenkette durchaus mit Leerzeichen aufhören, die Du nicht abschneiden solltest.

    <input type="hidden" name="id" value="<?php if (isset($id)) echo htmlspecialchars(trim($id), ENT_QUOTES); ?>">

    <input type="hidden" name="name" value="<?php if (isset($name)) echo htmlspecialchars(trim($name), ENT_QUOTES); ?>">

    <input type="hidden" name="kategorie" value="<?php if (isset($kategorie)) echo htmlspecialchars(trim($kategorie), ENT_QUOTES);

    Zu dieser Trimmerei mal ganz allgemein: Entwerder ein Wert darf mit Whitespace-Zeichen anfangen oder aufhören, oder er darf es nicht. Wenn ja, dann solltest Du sie auch nicht abschneiden, wenn nein, dann sollte auch erst gar kein String, der solche Zeichen hat, in der Datenbank gespeichert werden, sondern das Trimmen ggf. beim Speichern bereits erledigt werden. Bei Deinen Feldern ist wahrscheinlich eher letzteres der Fall, aber das musst Du wissen. So oder so solltest Du bei der Ausgabe nichts trimmen (müssen).

    Zu meiner frage, ist das Sicher oder habe ich noch etwas Wichtiges vergessen?

    Im Hinblick auf welche Gefahren soll es denn sicher sein?

    Viele Grüße
    der Bademeister

  3. Hi!

    1. Daten werden per feste abfrage aus der MySQL Datenbank ausgegeben.

    Was muss man sich unter einer festen Abfrage vorstellen?

    1. Die ausgegebenen Daten beinhalten ID, Name, Kategorie und einen Link.

    Die Bedeutung der Inhalte ist aus Programmsicht eher unwichtig (nur wenn man ein Konzept diskutiert braucht man auch die Bedeutung). Vielmehr interessiert hier ihr Typ oder Datenformat oder der konkrete Inhalt (zum Beispiel String mit möglicherweise Leerzeichen am Ende).

    1. Der Link ist nachher maßgebend wohin man weitergeleitet wird, ob zu einer meiner Seiten wo die Daten ID, Name und Kategorie weiterverarbeitet werden oder einfach nur zur Homepage desjenigen der in der Datenbank eingetragen ist.

    Das ist auch unwichtig. Wichtig ist hier nur, dass ob es ein Link oder besser gesagt eine URL ist oder Daten, die in eine solche eingefügt werden sollen.

    $id=mysql_result($resultabfrage,$i,"id");
    <input type="hidden" name="id" value="<?php if (isset($id)) echo htmlspecialchars(trim($id), ENT_QUOTES); ?>">

    Wenn man das so sieht, könnte man denken, der Programmierer hat ein defektes Kurzzeitgedächtnis. Eben setzt er die Variable $id und gleich darauf fragt er ab, ob sie existiert. Natürlich existiert sie, du hast sie gerade angelegt. Ein Sonderfall wäre, wenn aus der Datenbankabfrage ein null zurückgeliefert wird und das abgefangen werden soll. isset() spielt hier zwar mit, weil es auch eine zwar existierende aber mit null gefüllte Variable als nicht existent ansieht. Besser wäre es, auf null zu testen, damit man gleich die Intention sieht und nicht um diese Besonderheit isset()s wissen muss. if ($id != null) ...

    Wenn allerdings dein Abfragevorgang so gestaltet ist, dass die Variablen nur bei nicht leerer Ergebnismenge überhaupt angelegt werden, so wäre der Ablauf des Programms generell zu überdenken. Ohne Ergebnismenge braucht es keine Ausgabe eines Formulars, also hätte die Ausgabe besser in Abhängigkeit vom Vorhandensein eines Ergebnisses zu erfolgen.

    Lo!