tag:forum.selfhtml.org,2005:/self Wie prüft man ein Checkbox-Feld serverseitig effizient? – SELFHTML-Forum 2021-12-03T14:37:37Z https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794183#m1794183 claus ginsel 2021-12-03T10:17:56Z 2021-12-03T10:47:13Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Hallo</p> <p>für eine Auswahlliste möchte ich auf Checkboxen zurückgreifen, dabei stellt sich mir ausgehend von einem Zitat bei php.de</p> <blockquote> <p>Achtung! Häufig gemachter Fehler:<br> Für Auswahlfelder und -listen werden die Gefahren von XSS oftmals unterschätzt, weil sie im Gegensatz zu Textfeldern keine direkte Eingabe von Schadcode ermöglichen. In Anbetracht der Tatsache, dass in einem gefälschten Formular allein die richtige Angabe des name-Attributs ausreicht, um beliebige Werte und Werttypen für beliebige Elemente übermitteln zu können, ist die Annahme jedoch haltlos und damit besonders gefährlich.</p> </blockquote> <p>die Frage, wie man das sinnvollerweise anstellt.</p> <p>Bisher habe ich, von einem Checkbox-Feld ausgehend, folgendes:</p> <pre><code class="block language-php"> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span> <span class="token keyword">as</span> <span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//if(preg_match('/^[a-zA-ZäöüÄÖÜß\-]{3,40}$/', $name)==false) exit(header('Location: ...'));</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">array_key_exists</span><span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">,</span> array_Recip<span class="token punctuation">)</span><span class="token operator">==</span><span class="token constant boolean">false</span><span class="token punctuation">)</span> <span class="token keyword">exit</span><span class="token punctuation">(</span><span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Location: ...'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> <p>Was aber, wenn andere gleichbenannte Formularelemente kommen, wie ließe sich das umfassend lösen?</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794184#m1794184 dedlfix 2021-12-03T10:32:01Z 2021-12-03T10:32:01Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Tach!</p> <p>Bei dem zitierten Text geht es im Werte. Deine Frage bezieht sich aber anscheinend auf Keys.</p> <blockquote> <p>Bisher habe ich, von einem Checkbox-Feld ausgehend, folgendes:</p> <pre><code class="block language-php"> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span> <span class="token keyword">as</span> <span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//if(preg_match('/^[a-zA-ZäöüÄÖÜß\-]{3,40}$/', $name)==false) exit(header('Location: ...'));</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">array_key_exists</span><span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">,</span> array_Recip<span class="token punctuation">)</span><span class="token operator">==</span><span class="token constant boolean">false</span><span class="token punctuation">)</span> <span class="token keyword">exit</span><span class="token punctuation">(</span><span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Location: ...'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> </blockquote> <p>Die sinnvollere Methode finde ich, dass man eine Liste der erwarteten Felder hat und durch diese laufend schaut, ob dazu Eingaben vorliegen. Überzählige Keys im $_POST ignoriert man.</p> <blockquote> <p>Was aber, wenn andere gleichbenannte Formularelemente kommen, wie ließe sich das umfassend lösen?</p> </blockquote> <p>In einem PHP-Array können Keys nicht mehrfach auftreten, auch nicht in $_POST. Bei gleich benannten Formularfeldern gewinnt das spätere.</p> <p>Zu beachten ist, wenn der Name ein <code>[]</code> am Ende hat, dann gibt es zwar auch nur einen Key, aber der Wert ist kein Skalar sondern ein Array.</p> <p>dedlfix.</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794185#m1794185 Raketenbürokrat 2021-12-03T10:36:36Z 2021-12-03T10:36:36Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <blockquote> <p>Was aber, wenn andere gleichbenannte Formularelemente kommen, wie ließe sich das umfassend lösen?</p> </blockquote> <p>Also in $_GET oder $_POST tauchen identisch benannte Formularelemente nicht auf. Genau genommen stets nur das letzte.</p> <p>Es sei denn, der Name enthalte den Hinweis, dass es ein Array sei: <code><input name="test[]"></code>, dann erhältst Du ein Array.</p> <p>Alternativ kannst Du z.B. <code>$_SERVER['QUERY_STRING']</code> selbst zerlegen...</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794192#m1794192 Robert B. 2021-12-03T11:27:54Z 2021-12-03T11:27:54Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Moin Claus,</p> <blockquote> <p>für eine Auswahlliste möchte ich auf Checkboxen zurückgreifen, dabei stellt sich mir ausgehend von einem Zitat bei php.de</p> <blockquote> <p>Achtung! Häufig gemachter Fehler:<br> Für Auswahlfelder und -listen werden die Gefahren von XSS oftmals unterschätzt, weil sie im Gegensatz zu Textfeldern keine direkte Eingabe von Schadcode ermöglichen. In Anbetracht der Tatsache, dass in einem gefälschten Formular allein die richtige Angabe des name-Attributs ausreicht, um beliebige Werte und Werttypen für beliebige Elemente übermitteln zu können, ist die Annahme jedoch haltlos und damit besonders gefährlich.</p> </blockquote> <p>die Frage, wie man das sinnvollerweise anstellt.</p> </blockquote> <p>Du musst prüfen, ob der vom Auswahlfeld übermittelte Wert dem entspricht, was du erwartest – stell dir dabei vor, dass jemand das Auswahlfeld oder die Auswahlliste durch eine <code>textarea</code> ersetzt hätte.</p> <blockquote> <p>Bisher habe ich, von einem Checkbox-Feld ausgehend, folgendes:</p> <pre><code class="block language-php"> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">foreach</span> <span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span> <span class="token keyword">as</span> <span class="token variable">$name</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//if(preg_match('/^[a-zA-ZäöüÄÖÜß\-]{3,40}$/', $name)==false) exit(header('Location: ...'));</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">array_key_exists</span><span class="token punctuation">(</span><span class="token variable">$name</span><span class="token punctuation">,</span> array_Recip<span class="token punctuation">)</span><span class="token operator">==</span><span class="token constant boolean">false</span><span class="token punctuation">)</span> <span class="token keyword">exit</span><span class="token punctuation">(</span><span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'Location: ...'</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </code></pre> </blockquote> <p>Was ist denn <code>array_Recip</code> für eine Konstante?</p> <blockquote> <p>Was aber, wenn andere gleichbenannte Formularelemente kommen, wie ließe sich das umfassend lösen?</p> </blockquote> <p>Du erwartest, dass <code>MailRecip</code> ein Array enthält. Was passiert denn im <code class="lang-php">foreach</code>, wenn das nicht der Fall ist?</p> <p>Viele Grüße<br> Robert</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794198#m1794198 claus ginsel 2021-12-03T14:37:37Z 2021-12-03T14:37:37Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Besten Dank in die Runde</p> <p>Ein schönes Wochenende</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794193#m1794193 Rolf B 2021-12-03T11:31:48Z 2021-12-03T11:31:48Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Hallo dedlfix,</p> <p>das Statement <code>foreach ($_POST['MailRecip'] as $name)</code> kann nur funktionieren, wenn im HTML name="MailRecip[]" mit unterschiedlichen Values notiert ist.</p> <p>Wäre das anders, wäre Claus niemals bis zu dem Punkt gekommen, an dem er jetzt seine Frage stellt.</p> <p>Die Problemstellung ist doch, wie man mit der Warnung umgehen sollte, die php.da da gibt.</p> <p>Prinzipiell ist sie richtig. Man kann in den values eines Buttons oder eine Checkbox allen möglichen Schabernack, bis hin zu schönen Grüßen von Little Bobby Tables, eintragen und darf sie deshalb nicht blindlings in ein SQL einbauen oder wieder auf den Bildschirm schreiben.</p> <p>Wenn also in den value-Attributen der Checkboxen bereits die Mailadressen stehen, die Du anschreiben willst, dann könnte es passieren, dass ein böser Mensch das HTML editiert und da Fremdadressen eintippt. Oder einfach die Mailadressen absaugt und als Spam-Target verkauft. Lösung: Möglichst keine abgreifbaren oder fälschbaren Informationen auf die Webseite bringen, sondern nur unschädliche Referenzen auf diese Informationen. Den Bezug zwischen Referenz und eigentlichem Wert stellst Du über eine Tabelle in der Session her. In diesem Fall sähe das so aus: Nicht die Mailadressen oder deren DB-ID eintragen, sondern nur eine laufende Nummer. Und in der Session speicherst Du, welche laufenden Nummern Du für Mailadressen auf der Seite hast und stellst die Mailadresse (oder die DB-ID) daraus her. Ggf. passt es in der Session nicht. Dann könntest Du auch ein hidden input verwenden (anderswo ViewState oder PageState genannt), aber DAS muss zufallsgesalzen, prüfgesummt und mit einem serverseitig gespeicherten Key verschlüsselt werden, so dass keine Known Plaintext Attacke und keine Fälschung möglich ist. Session ist einfacher, kann aber schiefgehen wenn der User mehrere Fenster zur gleichen Session öffnet.</p> <p>Die Frage, die sich Claus stellt, ist aber eine andere. Was tun, wenn im Formular zwei Elemente den gleichen Name haben und sich gegenseitig überschreiben. Im Falle der Checkboxliste könnte es sogar passieren, dass es außer den Checkboxen mit name="MailRecip[]" noch ein Input-Feld mit name="MailRecip" gibt - in dem Fall würde der foreach auf die Nase fallen.</p> <p>Das ist dann eigentlich keine Frage der Security, sondern der Robustheit. Die Situation kann durch fehlerhaft geschriebenes HTML entstehen. Die auf den Produktionsserver geladene Version der Seite sollte solche Programmierfehler nicht mehr enthalten, das muss im Test auffallen. Ein Fatal Error ist besonders auffällig dafür und deshalb eine gute Antwort auf die Situation.</p> <p>Oder ein Script Kiddie postet seine Attacke fehlerhaft, auch in dann ist ein Fatal Error mit stumpfem HTTP 500 Abschluss des Requests die passende Antwort. Den Absturzgrund schreibt man in den Serverlog.</p> <p>Man ist geneigt, technische Fehler vom User möglichst fernzuhalten. Bestimmte Dinge müssen in einer Anwendung aber einfach passen, um sie produktiv schalten zu dürfen. Dazu gehört, dass der PHP Code alle Requests aus der HTML-Seite, die er zuvor hinausgeschickt hat, technisch auch verarbeiten kann. Kann er das nicht, MUSS es deutlich und katastrophal auffallen, sowas darf sich nicht im Log verstecken. Dass man mit bestimmten Benutzereingaben nicht klarkommt ist etwas anderes. Benutzereingaben sind von Programmen als grundsätzlich falsch, unsinnig und destruktiv vorauszusetzen. Das führt dazu, dass man als Programmierer eine gewisse Grundparanoia als Geisteshaltung entwickelt und überall erstmal die potenziellen Fehler sucht. Die muss man zügeln. "Du siehst immer alles nur negativ" - ist sonst der Satz, den man zu hören bekommt.</p> <p>Dass die eigentlichen Werte aus dem erwarteten Wertebereich kommen (sprich: numerisch oder ein existierender Key in die Referenztabelle in der Session), ist dann die Nachfolgeprüfung. Aber wenn ich einen Wert nur verwende, um damit einen Array-Eintrag auszulesen, reicht array_key_exists vollkommen als Validierung.</p> <p><em>Rolf</em></p> <div class="signature">-- <br> sumpsi - posui - obstruxi </div> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794187#m1794187 claus ginsel 2021-12-03T10:59:02Z 2021-12-03T10:59:02Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Also ich habe das Zitat von php.de so verstanden, dass ein Angreifer ein Formular nachbaut und darin statt Checkboxen zB ein Textfeld mit 'MailRecip' einfügt, um damit irgendwas unerwünschtes zu erwirken.</p> <blockquote> <p>Die sinnvollere Methode finde ich, dass man eine Liste der erwarteten Felder hat und durch diese laufend schaut, ob dazu Eingaben vorliegen</p> </blockquote> <p>Das mach ich doch, ich schaue, ob der Key in einem Array (als Konstante) existiert.</p> <p>Könnte das die Lösung sein:</p> <pre><code class="block language-php"><span class="token function">is_array</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> </code></pre> <p>bevor ich die Werte prüfe, ein Textfeld als 'MailRecip' müsste dann ja auffallen?</p> <p>Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794189#m1794189 claus ginsel 2021-12-03T11:11:18Z 2021-12-03T11:11:18Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>dedlfix, mit Liste der Felder meinst Du die Formularfelder?</p> <p>das mach ich doch mit</p> <pre><code>if(isset($_POST['MailRecip'])) </code></pre> <p>mehr Felder gibt es nicht.</p> <p>Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794190#m1794190 Der Martin 2021-12-03T11:13:38Z 2021-12-03T11:13:38Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Hallo Claus,</p> <blockquote> <p>Also ich habe das Zitat von php.de so verstanden, dass ein Angreifer ein Formular nachbaut und darin statt Checkboxen zB ein Textfeld mit 'MailRecip' einfügt, um damit irgendwas unerwünschtes zu erwirken.</p> </blockquote> <p>nenee, vergiss mal für einen Moment, dass es ein Formular gibt. Ein Angreifer in Spiellaune kann auch ohne Formular und ohne Browser einen HTTP-Request an dein Script absetzen, z.B. mit dem Kommandozeilentool <strong>wget</strong>.</p> <p>Und damit kann ich dann beliebige Parameter übergeben - beliebig, sowohl was deren Namen angeht, als auch die Werte.</p> <blockquote> <blockquote> <p>Die sinnvollere Methode finde ich, dass man eine Liste der erwarteten Felder hat und durch diese laufend schaut, ob dazu Eingaben vorliegen</p> </blockquote> <p>Das mach ich doch, ich schaue, ob der Key in einem Array (als Konstante) existiert.</p> </blockquote> <p>Ein guter Ansatz, wobei die von dedlfix angedeutete Methode, unerwartete Parameter einfach zu ignorieren, auch in Ordnung ist<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>.<br> Und dann solltest du zu jedem erlaubten Parameter prüfen, ob auch der gelieferte Wert plausibel und vom richtigen Typ ist.</p> <blockquote> <p>Könnte das die Lösung sein:</p> <pre><code class="block language-php"><span class="token function">is_array</span><span class="token punctuation">(</span><span class="token variable">$_POST</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'MailRecip'</span><span class="token punctuation">]</span><span class="token punctuation">)</span> </code></pre> <p>bevor ich die Werte prüfe, ein Textfeld als 'MailRecip' müsste dann ja auffallen?</p> </blockquote> <p>In diesem Beispiel bestimmt vernünftig. Denn wenn dein Script ein Array erwartet, stattdessen aber nur einen einzelnen String bekommt, wird es einen Scriptfehler beim Zugriff auf ein Arrayelement geben.</p> <p>May the Schwartz be with you<br>  Martin</p> <div class="signature">-- <br> Ein Student ist im Begriff, sich in der Mensa zu einem Professor an den Tisch zu setzen.<br> Professor: Seit wann essen denn Adler und Schwein an einem Tisch?<br> Student: Okay, dann flieg' ich halt einen Tisch weiter. </div> <hr class="footnotes-sep"> <section class="footnotes"> <ol class="footnotes-list"> <li id="fn1" class="footnote-item"><p>Wobei man sich fragen kann, ob es sich lohnt, den Request überhaupt weiter zu bearbeiten, wenn er offensichtlich fake ist, oder ob man dann lieber das Script kontrolliert abbricht (z.B. mit Status 400). <a href="#fnref1" class="footnote-backref">↩︎</a></p> </li> </ol> </section> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794191#m1794191 dedlfix 2021-12-03T11:22:49Z 2021-12-03T11:22:49Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Tach!</p> <blockquote></blockquote> <p>Die Frage ist für mich, ob es sich lohnt, sowas zu untersuchen. Kann man machen, wenn man will. Aber man bekommt auch mit ordnungsgemäßen Requests Werte rein, die man nicht haben möchte, und die man nicht unbedingt mit technischen Mitteln finden kann, oder wo der Aufwand zu hoch ist, diese zu erkennen. Man muss also auch so ein Auge auf seine Daten haben.</p> <p>Ich würde nur nehmen, was mich interessiert und den Rest ignorieren. Wenn das verwendete Framework eine Erkennung unangeforderter Keys enthält, dann ok, sonst mach ich mir den Aufwand nicht, ohne dass ein konkreter Angriff das als wirksame Gegenmaßnahme erzwingt.</p> <p>dedlfix.</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794194#m1794194 claus ginsel 2021-12-03T11:38:23Z 2021-12-03T11:38:23Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <blockquote> <p>Wobei man sich fragen kann, ob es sich lohnt, den Request überhaupt weiter zu bearbeiten, wenn er offensichtlich fake ist, oder ob man dann lieber das Script kontrolliert abbricht (z.B. mit Status 400)</p> </blockquote> <p>Ich breche ab mittels Umleitung auf Fehlerseite.</p> <p>Student und Prof treffen sich am Pissoir. Student: dass wir uns hier mal treffen als ebenbürtige Personen :) Prof: und schon haben Sie wieder den kürzeren gezogen ;)</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794195#m1794195 claus ginsel 2021-12-03T11:48:23Z 2021-12-03T11:48:23Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <p>Moin Robert</p> <blockquote> <p>Was ist denn array_Recip für eine Konstante?</p> </blockquote> <p>das ist ein Array mit Name => Mailadresse, ausgelagert in eine Datei und included, relativ unveränderbar, sprich es gibt selten Änderungen und wenn, dann mach ich das über direkten Zugriff auf die Datei.</p> <p>Allerdings sind nicht immer alle Personen zu adressieren, dafür braucht der User ein Auswahlformular.</p> <blockquote> <p>Du erwartest, dass MailRecip ein Array enthält. Was passiert denn im foreach, wenn das nicht der Fall ist?</p> </blockquote> <p>Das war der Ausgangspunkt der Frage. Ich hatte foreach zum Test mal angewendet auf eine String-Variable, und da gab es dann einen Fehler.</p> <p>Claus</p> https://forum.selfhtml.org/self/2021/dec/03/wie-pruft-man-ein-checkbox-feld-serverseitig-effizient/1794196#m1794196 claus ginsel 2021-12-03T11:53:55Z 2021-12-03T11:53:55Z Wie prüft man ein Checkbox-Feld serverseitig effizient? <blockquote> <p>Du musst prüfen, ob der vom Auswahlfeld übermittelte Wert dem entspricht, was du erwartest – stell dir dabei vor, dass jemand das Auswahlfeld oder die Auswahlliste durch eine textarea ersetzt hätte.</p> </blockquote> <p>Ja, genau. Das war mein Problem.</p> <p>Das werde ich vorab mit is_array ausschließen.</p> <p>Gruß Claus</p>