tag:forum.selfhtml.org,2005:/self wiederholtes Absenden Formular – SELFHTML-Forum 2021-09-06T07:24:07Z https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791319?srt=yes#m1791319 claus ginsel 2021-09-03T09:17:27Z 2021-09-03T09:17:27Z wiederholtes Absenden Formular <p>Hallo</p> <p>es geht um ein Formular, in dem ich einen Dateinamen eingebe und die Datei bei Vorliegen aller Voraussetzungen runter geladen wird. Nach dem Download ist das Textfeld mit dem Dateinamen weiterhin gefüllt. Das ist insoweit in Ordnung, ich kann den Download auch wiederholen.</p> <p>Nun habe ich die Empfehlungen des BSI zur Websicherheit berücksichtigen wollen und auch einen CSRF-Schutz eingebaut. Nunmehr wird der 1. Download getätigt, aber weitere scheitern am CSRF-Schutz.</p> <pre><code class="block language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token comment">//...</span> <span class="token function">session_start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//...</span> <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">'form_Download'</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">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token keyword">isset</span><span class="token punctuation">(</span><span class="token variable">$_SESSION</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'CSRF_DL'</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">exit</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">preg_match</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'/^[a-z0-9]{40}$/'</span><span class="token punctuation">,</span> <span class="token variable">$_SESSION</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'CSRF_DL'</span><span class="token punctuation">]</span><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 operator">...</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//diese Zeile ist das Problem bei wiederholten DL, redirect wird ausgeführt!</span> <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</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 variable">$_SESSION</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'CSRF_DL'</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">exit</span><span class="token punctuation">(</span><span class="token operator">...</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//...</span> <span class="token delimiter important">?></span></span> </code></pre> <pre><code class="block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>HTML</span> <span class="token attr-name">lang</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">'</span>de<span class="token punctuation">'</span></span><span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>index.php<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hidden<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span> <?php $_SESSION['CSRF_DL'] = sha1(uniqid('', true)); echo $_SESSION['CSRF_DL']; ?><span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>input_datei<span class="token punctuation">"</span></span> <span class="token attr-name">required</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>form_Download<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>submit<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Bestätigen<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span> ... <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>HTML</span><span class="token punctuation">></span></span> </code></pre> <p>Könnt Ihr mir einen Tipp geben, wie ich mehrfaches Absenden und CSRF unter einen Hut kriege?</p> <p>Bei der Gelegenheit, ich muss zugeben, ich habe den CSRF-Schutz mechanisch zugefügt. Die Beispiele für Gefährdungen sind ja soweit auch einleuchtend, aber ich kann jetzt nicht beurteilen, ob mein spezieller Anwendungsfall durch CSRF gefährdet ist. Was meint Ihr dazu?</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791322?srt=yes#m1791322 dedlfix 2021-09-03T11:05:27Z 2021-09-03T11:05:27Z wiederholtes Absenden Formular <p>Tach!</p> <blockquote> <p>Nun habe ich die Empfehlungen des BSI zur Websicherheit berücksichtigen wollen und auch einen CSRF-Schutz eingebaut. Nunmehr wird der 1. Download getätigt, aber weitere scheitern am CSRF-Schutz.</p> </blockquote> <p>Weil der Token am Server nicht mehr derselbe ist. Du müsstest die Formularseite erneut mit gültigem Token aufrufen.</p> <blockquote> <p>Könnt Ihr mir einen Tipp geben, wie ich mehrfaches Absenden und CSRF unter einen Hut kriege?</p> <p>Bei der Gelegenheit, ich muss zugeben, ich habe den CSRF-Schutz mechanisch zugefügt. Die Beispiele für Gefährdungen sind ja soweit auch einleuchtend, aber ich kann jetzt nicht beurteilen, ob mein spezieller Anwendungsfall durch CSRF gefährdet ist. Was meint Ihr dazu?</p> </blockquote> <p>Das musst du selbst einschätzen. CSRF ist ein Problem, wenn der Request Daten ändert und der Nutzer dafür angemeldet sein muss. Wenn der Download-Request keine Daten ändert, muss er auch nicht gegen CSRF gesichert sein.</p> <p>dedlfix.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791324?srt=yes#m1791324 1unitedpower 2021-09-03T11:38:44Z 2021-09-03T11:38:44Z wiederholtes Absenden Formular <blockquote> <p>Nun habe ich die Empfehlungen des BSI zur Websicherheit berücksichtigen wollen</p> </blockquote> <p>Das ist schon mal sehr löblich.</p> <blockquote> <p>Bei der Gelegenheit, ich muss zugeben, ich habe den CSRF-Schutz mechanisch zugefügt. Die Beispiele für Gefährdungen sind ja soweit auch einleuchtend, aber ich kann jetzt nicht beurteilen, ob mein spezieller Anwendungsfall durch CSRF gefährdet ist. Was meint Ihr dazu?</p> </blockquote> <p>Das ist allerdings eine gefährliche Vorgehensweise. Software-Sicherheit ist ein schwieriges Thema und Halbwissen auf dem Gebiet kann im besten Fall zu einem trügerischen Sicherheitsgefühl beitragen und im schlimmsten Fall mehr Türen für Angreifen öffnen als schließen . Bevor du anfängst etwas zu programmieren, solltest du die Theorie verstanden haben, und auf deinen Anwendungsfall übertragen können. Du solltest auch in der Lage die Vor- und Nachteile gängiger Implementierungen abzuwägen, bevor du selber etwas strickst. Eine gute erste Anlaufstelle zu CSRF ist das <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html" rel="nofollow noopener noreferrer">CSRF Prevention Cheat Sheet</a> der OWASP Foundation.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791332?srt=yes#m1791332 1unitedpower 2021-09-03T12:32:16Z 2021-09-03T12:32:16Z wiederholtes Absenden Formular <blockquote> <pre><code class="block language-php"><span class="token variable">$_SESSION</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'CSRF_DL'</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token function">sha1</span><span class="token punctuation">(</span><span class="token function">uniqid</span><span class="token punctuation">(</span><span class="token string single-quoted-string">''</span><span class="token punctuation">,</span> <span class="token constant boolean">true</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> </code></pre> </blockquote> <p><code>uniqid()</code> ist <a href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#secure-random-number-generation" rel="nofollow noopener noreferrer">kein kryptographisch sicherer Zufallsgenerator</a>, den du für solche Zwecke verwenden solltest.</p> <p>Primitive kryptographische Funktionen sollte man im Allgemeinen besser nicht selber programmieren. Vielleicht guckst du dir mal die <a href="https://github.com/paragonie/anti-csrf" rel="noopener noreferrer">Anti-CSRF Library</a> an, die wird von Sicherheits-Experten entwickelt und getestet.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791335?srt=yes#m1791335 Felix Riesterer https://felix-riesterer.de 2021-09-03T13:53:00Z 2021-09-03T13:53:00Z wiederholtes Absenden Formular <p>Lieber claus,</p> <blockquote> <p>es geht um ein Formular, in dem ich einen Dateinamen eingebe und die Datei bei Vorliegen aller Voraussetzungen runter geladen wird.</p> </blockquote> <p>warum keinen Download-Link, sondern dieses Formular? Wenn Du die Session-ID bei jedem Request änderst, ist ein solcher Download-Link auch gegen CSRF geschützt. Wer Deine Session kapern will, muss vor Dir eine weitere Seite aufrufen, damit er die neueste Session-ID erhält und Du Dich neu anmelden musst.</p> <blockquote> <p>Nach dem Download ist das Textfeld mit dem Dateinamen weiterhin gefüllt.</p> </blockquote> <p>Wozu Tippfehler zumuten? Verwendest Du das Formular rein wegen Gegenmaßnahmen zu CSRF?</p> <p>Liebe Grüße</p> <p>Felix Riesterer</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791326?srt=yes#m1791326 claus ginsel 2021-09-03T11:46:33Z 2021-09-03T11:46:33Z wiederholtes Absenden Formular <p>Aha, besten Dank</p> <p>Also die Seite dient ausschließlich dem Download, also könnte ich auf CSRF-Schutz verzichten ...</p> <p>Eines verstehe ich noch nicht</p> <blockquote> <p>Weil der Token am Server nicht mehr derselbe ist.</p> </blockquote> <p>Aber den, also $_SESSION['CSRF_DL'], setze ich doch nur inline, wenn die Seite index.php auch ausgeliefert wird, das wird sie doch nicht beim Datei-Download, denn dann müsste das Formularfeld ja leer sein </p> <blockquote> <p>Du müsstest die Formularseite erneut mit gültigem Token aufrufen.</p> </blockquote> <p>Genau das krieg ich nicht automatisch hin. Setze ich nach dem Download-Aufruf einen redirect zB auf die Seite index.php, wird der Download auch nicht vollzogen.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791327?srt=yes#m1791327 claus ginsel 2021-09-03T11:50:36Z 2021-09-03T11:50:36Z wiederholtes Absenden Formular <blockquote> <p>Software-Sicherheit ist ein schwieriges Thema</p> </blockquote> <p>da muss ich Dir vollumfänglich zustimmen </p> <p>OWASP steht schon in meinen Favoriten, trotzdem danke für deinen Hinweis</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791329?srt=yes#m1791329 dedlfix 2021-09-03T12:02:54Z 2021-09-03T12:02:54Z wiederholtes Absenden Formular <p>Tach!</p> <blockquote> <blockquote> <p>Weil der Token am Server nicht mehr derselbe ist.</p> </blockquote> <p>Aber den, also $_SESSION['CSRF_DL'], setze ich doch nur inline, wenn die Seite index.php auch ausgeliefert wird, das wird sie doch nicht beim Datei-Download, denn dann müsste das Formularfeld ja leer sein </p> </blockquote> <p>Ich sehe in deinem Code nicht, in welchen Dateien er steht, und damit auch nicht, wie das konkret bei dir abläuft. Wie die Datei ausgeliefert wird, ist gar nicht zu sehen. Wenn der Code nicht mehr gültig ist, muss deine Verarbeitung dort vorbeigekomen sein, wo ein neuer generiert wird. Soweit so logisch.</p> <p>dedlfix.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791331?srt=yes#m1791331 claus ginsel 2021-09-03T12:19:29Z 2021-09-03T12:19:29Z wiederholtes Absenden Formular <p>nur hier wird der token gesetzt:</p> <pre><code class="block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>index.php<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hidden<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span> <?php $_SESSION['CSRF_DL'] = sha1(uniqid('', true)); echo $_SESSION['CSRF_DL']; ?><span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> </code></pre> <p>also nur dann, wenn die Seite index.php ausgeliefert wird, sonst nicht</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791336?srt=yes#m1791336 Felix Riesterer https://felix-riesterer.de 2021-09-03T13:57:12Z 2021-09-03T13:57:55Z wiederholtes Absenden Formular <p>Lieber claus,</p> <blockquote> <pre><code class="block language-html"> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hidden<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span> <?php $_SESSION['CSRF_DL'] = sha1(uniqid('', true)); echo $_SESSION['CSRF_DL']; ?><span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> </code></pre> </blockquote> <p>da fehlt die <a href="https://wiki.selfhtml.org/wiki/Programmiertechnik/Kontextwechsel" rel="nofollow noopener noreferrer">kontextgerechte Behandlung von Daten</a>. Auch wenn der Wert in <code class="language-php"><span class="token variable">$_SESSION</span><span class="token punctuation">[</span><span class="token string single-quoted-string">'CSRF_DL'</span><span class="token punctuation">]</span></code> keine HTML-relevanten Zeichen (< " >) beinhalten mag, so gehört es zu sauberem Programmieren dazu, dass man Daten kontextgerecht behandelt:</p> <pre><code class="block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><?php echo htmlspecialchars($_SESSION['CSRF_DL']); ?><span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> </code></pre> <p>Liebe Grüße</p> <p>Felix Riesterer</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791343?srt=yes#m1791343 dedlfix 2021-09-03T15:43:10Z 2021-09-03T15:43:10Z wiederholtes Absenden Formular <p>Tach!</p> <blockquote> <p>nur hier wird der token gesetzt:</p> <pre><code class="block language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>index.php<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>POST<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> </code></pre> <p>also nur dann, wenn die Seite index.php ausgeliefert wird, sonst nicht</p> </blockquote> <p>Wenn du das Formular absendest, rufst du ebenfalls die index.php auf. Wird dabei der HTML-Teil ausgeklammert oder auch abgearbeitet?</p> <p>dedlfix.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791333?srt=yes#m1791333 claus ginsel 2021-09-03T12:49:34Z 2021-09-03T12:49:34Z wiederholtes Absenden Formular <p>nur mal zu meinem Verständnis:</p> <p>für CSRF bedarf es einiger Voraussetzungen</p> <ul> <li>Session-basierte Anwendung</li> <li>der betreffende User muss angemeldet sein</li> <li>der Angreifer muss den Aufbau der Seite kennen</li> <li>der Angreifer muss dem User die gefälschte Seite unterschieben</li> </ul> <p>Wie oft kann der Angreifer den User dazu veranlassen, die präparierte Seite aufzurufen, so dass der Angreifer verschiedene Werte für den Token ausprobieren kann? Ich denke, nur wenige Male.</p> <p>Weshalb muss dann der Token kryptografisch sicher sein, hab ich einen Denkfehler?</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791346?srt=yes#m1791346 1unitedpower 2021-09-03T22:52:37Z 2021-09-03T22:52:37Z wiederholtes Absenden Formular <blockquote> <p>nur mal zu meinem Verständnis:</p> <p>für CSRF bedarf es einiger Voraussetzungen</p> <ul> <li>Session-basierte Anwendung</li> <li>der betreffende User muss angemeldet sein</li> <li>der Angreifer muss den Aufbau der Seite kennen</li> <li>der Angreifer muss dem User die gefälschte Seite unterschieben</li> </ul> </blockquote> <p>Das stimmt so im Groben und Ganzen.</p> <blockquote> <p>Wie oft kann der Angreifer den User dazu veranlassen, die präparierte Seite aufzurufen, so dass der Angreifer verschiedene Werte für den Token ausprobieren kann? Ich denke, nur wenige Male.</p> </blockquote> <p>Hat der Angreifer sein Opfer einmal auf seine Seite gelockt, kann er beliebig viele Angriffsversuche unternehmen, sofern die Zielseite keine weiteren Gegenmaßnahmen ergreift.</p> <blockquote> <p>Weshalb muss dann der Token kryptografisch sicher sein, hab ich einen Denkfehler?</p> </blockquote> <p>In der Software-Sicherheit gilt eine umgekehrte Beweislast: Du hast du zeigen, dass ein Verfahren hinreichend ist, um gegen einen bestimmten Angriffsvektor abzusichern. Dazu ist es wichtig die Annahmen, unter welchen das Verfahren effektiv schützt, klar zu benennen. Im Falle von Verteidigungen gegen CSRF ist eine übliche Annahme, dass ein CSRF-Token mit einem kryptografisch sicheren Zufallsgenerator generiert wird. Ohne diese Annahme gilt schlicht die Argumentationslinie nicht, mit der das Verfahren als hinreichend sicher eingestuft werden kann. Du kannst natürlich versuchen zu zeigen, dass ein Verfahren auch mit der schwächeren Vorbedingung eines nicht kryptografisch sicheren Zufallsgenerators hinreichend sicher ist. Aber das wird schwierig. Kryptografisch unsicherer Zufall ist ein kontraintuitives Gebilde. Aus kryptographischer Sicht gibt es nur ein paar wenige, verhältnismäßig einfach zu bestimmendende Parameter, die den "Zufall" vollständig vorhersehbar machen. Um die Probleme von unsicherem Zufall sichtbar zu machen, hilft es sich vorzustellen der Zufallswert sei immer konstant und bekannt. Das offenbart sehr deutlich wo die Schwachstellen liegen. Das mag nach einer starken Vereinfachung klingen, aber es hat schon so viele erfolgreiche Angriffe auf unsichere Zufallsgeneratoren gegeben, dass es sich dabei inzwischen um eine gängige Arbeitshypothese handelt. Und es bleibt natürlich die Frage, wieso das Risiko eingehen, wenn ein kryptografisch sicheres Zufallsverfahren verfügbar ist?</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791338?srt=yes#m1791338 claus ginsel 2021-09-03T14:30:09Z 2021-09-03T14:30:09Z wiederholtes Absenden Formular <p>Hi Felix</p> <blockquote> <p>Verwendest Du das Formular rein wegen Gegenmaßnahmen zu CSRF?</p> </blockquote> <p>Nein, nur für diesen Download. CSRF hab ich nachträglich ergänzt.</p> <p>Die Idee mit dem Download-Link gefällt mir auch in anderer Hinsicht. ZZ krieg ich für jede Datei, die mir zugestellt werden soll, eine Mail mit dem Dateinamen, den ich dann ins Formularfeld rein kopiere (deshalb mehrfaches Absenden des Formulars). Warum nicht gleich einen Link auf die Dateien in die Seite einfügen </p> <p>Was den Kontextwechsel angeht, da hab ich an der Stelle lange drüber nachgedacht, ob das Ergebnis einer php-Funktion auch als Benutzereingabe zu betrachten ist. Ich denke nein. Aber ich lass mich gern eines besseren belehren.</p> <p>Danke Dir und Gruß</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791347?srt=yes#m1791347 1unitedpower 2021-09-03T23:30:23Z 2021-09-03T23:30:23Z wiederholtes Absenden Formular <blockquote> <p>Wenn Du die Session-ID bei jedem Request änderst, ist ein solcher Download-Link auch gegen CSRF geschützt. Wer Deine Session kapern will, muss vor Dir eine weitere Seite aufrufen</p> </blockquote> <p>Dieses Verfahren wird häufig in Verbindung mit Session-Fixation-Angriffen genannt, aber es hat leider bekannte Schwachstellen.</p> <p>Zum einen entsteht dadurch eine Race-Condition: Wem gelingt es zuerst einen Request abzusetzen, um einen neue Session-ID zu generieren, dem Angreifer oder dem Nutzer? Die Startbedingungen stehen besser für den Angreifer, da er die Abfrage automatisiert stellen kann. So kann der Angreifende das Opfer von der Nutzung der Seite aussperren, indem er schneller als das Opfer neue Session-IDs generiert.</p> <p>Zum anderen wird der Server ggf. anfällig für DOS-Angriffe: Wenn der Server einen Hardware-getriebenen Zufallsgenerator benutzt, muss der Server erst genügend Umgebungs-Entropie sammeln, um Session-IDs zu generieren. Ein Angreifer kann das ausnutzen: er kann in sehr hoher Frequenz Anfragen an den Server schicken, die ihn zwingen neue Session-IDs zu erzeugen. Bei jedem Request wird der Entropie-Buffer wieder geleert und der Server muss warten, bis er wieder genügend befüllt ist, um die nächste ID zu generieren. Macht er das in einer ausreichend hohen Frequenz, dann hat der Server keine Ressourcen mehr übrig, um die Anfragen legitimer Besucher:innen zu bedienen.</p> <p>Die gängige Praxis ist es, die Session-ID nicht bei jeder Anfrage neu zu vergeben, sondern nur bei Änderungen der Nutzer-Priviligen, zum Beispiel wenn der Nutzer sich ein- oder ausloggt. Außerdem sollten veraltete Session-IDs ungültig gemacht werden und nach angemessener Lebensdauer automatisch verworfen werden. Auch zu diesem Thema gibt es ein <a href="https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html" rel="nofollow noopener noreferrer">Cheat Sheet von OWASP</a>.</p> <p>Das ist aber ein anderes Thema. Ich verstehe auch nicht, wie das Erneuern der Session-ID vor CSRF-Angriffen schützen sollte.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791341?srt=yes#m1791341 Felix Riesterer https://felix-riesterer.de 2021-09-03T15:11:24Z 2021-09-03T15:11:24Z wiederholtes Absenden Formular <p>Lieber claus,</p> <blockquote> <p>Was den Kontextwechsel angeht, da hab ich an der Stelle lange drüber nachgedacht, ob das Ergebnis einer php-Funktion auch als Benutzereingabe zu betrachten ist. Ich denke nein.</p> </blockquote> <p>da ist er schon der Fehler! Du sollst nicht nach <code>$ist_benutzereingabe</code> unterscheiden! Das ist Blödsinn, weil es den Blick auf das Wesentliche versperrt: Den Kontext. Um allein den geht es. Das <a href="https://wiki.selfhtml.org/wiki/Programmiertechnik/Kontextwechsel" rel="nofollow noopener noreferrer">Kapitel zum Kontextwechsel</a> solltest Du Dir unbedingt zeitnah verinnerlichen!</p> <p>Liebe Grüße</p> <p>Felix Riesterer</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791344?srt=yes#m1791344 claus ginsel 2021-09-03T19:02:20Z 2021-09-03T19:02:20Z wiederholtes Absenden Formular <p>moin noch mal zum späten Abend</p> <blockquote> <p>Wenn du das Formular absendest, rufst du ebenfalls die index.php auf.</p> </blockquote> <p>ja, dann kommt php, prüft die Session, prüft auf POST-Variablen vom Formular, in dem Fall existieren diese, sendet die Datei, danach ist Schluss!!</p> <blockquote> <p>Wird dabei der HTML-Teil ausgeklammert oder auch abgearbeitet?</p> </blockquote> <p>Meiner Meinung nach wird der nicht mehr abgearbeitet. Denn die Formularfelder bleiben gefüllt. Ich hatte mal nach dem Senden der Datei zum Testen echos eingebaut, die wurden nicht mehr ausgegeben. Allerdings ein nachfolgender Redirect wurde ausgeführt, jedoch unterbleibt dann das Senden der Datei. Und da der HTML-Teil eben nicht mehr ausgegeben wird, wird auch der Token nicht verändert. So ein HTTP-Request kann wohl nicht zwei Sachen gleichzeitig senden, deshalb entweder das Action-Script mit leeren Formularfeldern oder die Datei.</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791365?srt=yes#m1791365 Der Martin 2021-09-04T13:35:27Z 2021-09-04T13:35:27Z wiederholtes Absenden Formular <p>Hallo Claus,</p> <blockquote> <blockquote> <p>Wird dabei der HTML-Teil ausgeklammert oder auch abgearbeitet?</p> </blockquote> <p>Meiner Meinung nach wird der nicht mehr abgearbeitet. Denn die Formularfelder bleiben gefüllt.</p> </blockquote> <p>wenn im PHP-Teil ausdrücklich eine Anweisung steht, die das Script beendet (z.B. ein exit), dann hast du recht. Wenn nicht, wird es interessant: Wie übermittelst du die Datei zum Download an den Client?<br> Direkt durch das PHP-Script mit readfile() und vorher dem korrekten Content-Type- und dem zur Dateigröße passenden Content-Length-Header? Dann würde alles, was nach dem PHP-Block (also nach dem ?>) noch folgt, ebenfalls übertragen, aber vom Client ignoriert, weil es über die angekündigte Content-Length hinausgeht.<br> Oder durch ein Redirect (301 oder 302) auf die angeforderte Datei? Dann hättest du zwar recht, aber der eigentliche Download erfolgt dann, indem der Client dem Redirect folgt und einen zweiten HTTP-Request absetzt, der die Ressource direkt abruft.</p> <blockquote> <p>Ich hatte mal nach dem Senden der Datei zum Testen echos eingebaut, die wurden nicht mehr ausgegeben. Allerdings ein nachfolgender Redirect wurde ausgeführt, jedoch unterbleibt dann das Senden der Datei.</p> </blockquote> <p>Das ist allerdings sehr mysteriös. Nicht das übliche Verhalten. Es deutet darauf hin, dass du sehr ungewöhnliche Methoden verwendest, die ich mir im Moment nicht vorstellen kann - vielleicht Output Buffering?</p> <p>Und ja, wenn der Client sich entschließt, dem Redirect zu folgen, ignoriert er den eigentlichen Inhalt (den Response Body) der HTTP-Antwort. Das ist korrekt so.</p> <blockquote> <p>So ein HTTP-Request kann wohl nicht zwei Sachen gleichzeitig senden</p> </blockquote> <p>Richtig, so funktioniert HTTP: Eine Anfrage, eine Antwort. Je nachdem, wie die Antwort ausfällt, kann sie den Client dazu bringen, eine weitere Anfrage zu senden - etwa beim Redirect.</p> <p>Live long and <s>pros</s> healthy,<br>  Martin</p> <div class="signature">-- <br> Klein φ macht auch Mist. </div> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791355?srt=yes#m1791355 claus ginsel 2021-09-04T08:36:46Z 2021-09-04T08:36:46Z wiederholtes Absenden Formular <p>Guten Morgen in die Runde</p> <p>Ich bin echt positiv überrascht über eure Beteiligung hier im forum. Ich weiß ja selbst, dass ich noch an der Oberfläche rum kratze. Umso bemerkenswerter, dass ihr nicht lehrmeisterhaft daher kommt, wie ich das in anderen Foren erlebt habe.</p> <p>Dafür gibt's ein Daumen hoch </p> <p>1unitedpower, danke für die ausführlichen Infos, das schaue ich mir in Ruhe an.</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791397?srt=yes#m1791397 claus ginsel 2021-09-06T07:06:42Z 2021-09-06T07:06:42Z wiederholtes Absenden Formular <p>Moin Martin,</p> <p>wie Du das so schreibst, wird das Verhalten klar</p> <pre><code class="block language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">function</span> <span class="token function-definition function">makeDownload</span><span class="token punctuation">(</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">,</span> <span class="token variable">$Datei_Pfad</span><span class="token punctuation">,</span> <span class="token variable">$Datei_MIME</span><span class="token punctuation">,</span> <span class="token variable">$Dateiname_Client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'X-Content-Type-Options: nosniff'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Type: "</span><span class="token operator">.</span><span class="token variable">$Datei_MIME</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Disposition: attachment; filename="</span><span class="token operator">.</span><span class="token variable">$Dateiname_Client</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Length: "</span><span class="token operator">.</span><span class="token function">filesize</span><span class="token punctuation">(</span><span class="token variable">$Datei_Pfad</span><span class="token operator">.</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readfile</span><span class="token punctuation">(</span><span class="token variable">$Datei_Pfad</span><span class="token operator">.</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter important">?></span></span> </code></pre> <p>readfile ist die letzte Anweisung in php, es gibt nichts mehr wie exit, also wird der HTML-Teil auch übertragen, nur vom Browser wegen Content-Length nicht berücksichtigt.</p> <p>Angenommen, ich würde Content-Length um den Betrag der Index.php erhöhen, dann würde diese mit ausgegeben. Allerdings durch Content-Disposition vom Browser nicht als gerendertes HTML, sondern die Quelldaten von Index.php an die Download-Datei rangehängt. Das wäre im Ergebnis so, als würde ich vor Absenden der Header eine Ausgabe tätigen, worauf ich früher auch mal reingefallen bin.</p> <p>Falls aus</p> <blockquote> <p>Allerdings ein nachfolgender Redirect wurde ausgeführt, jedoch ...</p> </blockquote> <p>ein Missverständnis erwachsen sein sollte: Ich habe den Begriff Redirect für jegliche Weiterleitung über header(Location: ...) benutzt. Möglicherweise versteht Ihr darunter lediglich die Statuscode 301 und 302?</p> <p>Besten Dank für die erhellenden Infos</p> <p>Gruß Claus</p> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791398?srt=yes#m1791398 Der Martin 2021-09-06T07:22:24Z 2021-09-06T07:22:24Z wiederholtes Absenden Formular <p>Hallo,</p> <blockquote> <pre><code class="block language-php"><span class="token php language-php"><span class="token delimiter important"><?php</span> <span class="token keyword">function</span> <span class="token function-definition function">makeDownload</span><span class="token punctuation">(</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">,</span> <span class="token variable">$Datei_Pfad</span><span class="token punctuation">,</span> <span class="token variable">$Datei_MIME</span><span class="token punctuation">,</span> <span class="token variable">$Dateiname_Client</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string single-quoted-string">'X-Content-Type-Options: nosniff'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Type: "</span><span class="token operator">.</span><span class="token variable">$Datei_MIME</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Disposition: attachment; filename="</span><span class="token operator">.</span><span class="token variable">$Dateiname_Client</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">header</span><span class="token punctuation">(</span><span class="token string double-quoted-string">"Content-Length: "</span><span class="token operator">.</span><span class="token function">filesize</span><span class="token punctuation">(</span><span class="token variable">$Datei_Pfad</span><span class="token operator">.</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readfile</span><span class="token punctuation">(</span><span class="token variable">$Datei_Pfad</span><span class="token operator">.</span><span class="token variable">$Dateiname_Server</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token delimiter important">?></span></span> </code></pre> <p>readfile ist die letzte Anweisung in php, es gibt nichts mehr wie exit, also wird der HTML-Teil auch übertragen, nur vom Browser wegen Content-Length nicht berücksichtigt.</p> </blockquote> <p>genau das wollte ich damit sagen.</p> <blockquote> <p>Angenommen, ich würde Content-Length um den Betrag der Index.php erhöhen, dann würde diese mit ausgegeben. Allerdings durch Content-Disposition vom Browser nicht als gerendertes HTML, sondern die Quelldaten von Index.php an die Download-Datei rangehängt.</p> </blockquote> <p>Korrekt.</p> <blockquote> <p>Das wäre im Ergebnis so, als würde ich vor Absenden der Header eine Ausgabe tätigen, worauf ich früher auch mal reingefallen bin.</p> </blockquote> <p>Nein, mit der ersten Ausgabe (purer HTML-Code odere PHP-Ausgaben, z.B. print oder echo) werden alle bis dahin vorgemerkten HTTP-Header gesendet. Eine später folgende header-Anweisung kann dann nicht mehr berücksichtigt werden<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>. Versucht man es trotzdem, bekommt man von PHP die Meldung <em>Cannot modify header information - headers already sent</em>.</p> <blockquote> <p>Falls aus</p> <blockquote> <p>Allerdings ein nachfolgender Redirect wurde ausgeführt, jedoch ... ein Missverständnis erwachsen sein sollte: Ich habe den Begriff Redirect für jegliche Weiterleitung über header(Location: ...) benutzt. Möglicherweise versteht Ihr darunter lediglich die Statuscode 301 und 302?</p> </blockquote> </blockquote> <p>Ja. Ein HTTP-Redirect, wie du ihn beschreibst, setzt automatisch auch einen der beiden Statuscodes 301 oder 302. Einer von beiden bedeutet eine kurzzeitige Umleitung, z.B. bei Wartungsarbeiten, der andere eine dauerhafte (nur die Zuordnung kann ich mir nie merken).</p> <p>Live long and <s>pros</s> healthy,<br>  Martin</p> <div class="signature">-- <br> Klein φ macht auch Mist. </div> <hr class="footnotes-sep"> <section class="footnotes"> <ol class="footnotes-list"> <li id="fn1" class="footnote-item"><p>Es sei denn man aktiviert Output Buffering. Dabei wird die Ausgabe bis zum Schluss des Scripts in einem Puffer gesammelt und erst dann ausgegeben. <a href="#fnref1" class="footnote-backref">↩︎</a></p> </li> </ol> </section> https://forum.selfhtml.org/self/2021/sep/03/wiederholtes-absenden-formular/1791399?srt=yes#m1791399 claus ginsel 2021-09-06T07:24:07Z 2021-09-06T07:24:07Z wiederholtes Absenden Formular <p>Der Ausgangspunkt meiner Anfrage war ja ein anderer, der sich mit Martins Antwort aber nun auch auflöst: Wenn also der HTML-Teil entgegen meiner Annahme doch ausgeführt wird, dann wird ja auch $_SESSION['CSRF_DL'] und damit der CSRF-Token verändert, aber das Formular im Browser enthält weiterhin das Feld mit dem alten Wert.</p> <p>Damit hab ich eigentlich alles. Ich werde, wie dedlfix anregte, beim reinen Download auf eine CSRF-Prüfung verzichten. Und ich werde Felix seinen Tipp, statt mit Eingaben in ein Textfeld mit Links auf die Dateien zu arbeiten, umsetzen. Spart mir am Ende Arbeit </p> <p>Ich danke allen für die Hinweise</p> <p>bis zu nächsten Mal</p> <p>Gruß Claus</p>