<?xml version="1.0" encoding="utf-8" ?>

<rss version="2.0" 
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/"
   xmlns:content="http://purl.org/rss/1.0/modules/content/"
   >
<channel>
    <title>Octavians Nutwerk - ZendFramework</title>
    <link>http://nutwerk.de/</link>
    <description>&quot;Oh Nutwerk. Wo der grilbe Wakwak-Vogel zirbelt grell wie Tee-Service. Des wachen Mundes arg geschlauchter Gartenkohl, von Honigmoehnchen kandelabert, a.&quot; - Switch</description>
    <dc:language>de</dc:language>
    <generator>Serendipity 1.5.3 - http://www.s9y.org/</generator>
    <pubDate>Sun, 28 Mar 2010 00:56:53 GMT</pubDate>

    <image>
        <url>http://nutwerk.de/templates/square/img/s9y_banner_small.png</url>
        <title>RSS: Octavians Nutwerk - ZendFramework - &quot;Oh Nutwerk. Wo der grilbe Wakwak-Vogel zirbelt grell wie Tee-Service. Des wachen Mundes arg geschlauchter Gartenkohl, von Honigmoehnchen kandelabert, a.&quot; - Switch</title>
        <link>http://nutwerk.de/</link>
        <width>100</width>
        <height>21</height>
    </image>

<item>
    <title>CSRF Protection (Updated)</title>
    <link>http://nutwerk.de/archives/15-CSRF-Protection-Updated.html</link>
            <category>todoyo.de</category>
            <category>ZendFramework</category>
    
    <comments>http://nutwerk.de/archives/15-CSRF-Protection-Updated.html#comments</comments>
    <wfw:comment>http://nutwerk.de/wfwcomment.php?cid=15</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://nutwerk.de/rss.php?version=2.0&amp;type=comments&amp;cid=15</wfw:commentRss>
    

    <author>nospam@example.com (Marc Jakubowski)</author>
    <content:encoded>
    Nachdem &lt;a href=&quot;http://blog.fukami.io/&quot;&gt;fukami&lt;/a&gt; beim letzten Bonner &lt;a href=&quot;http://www.webmontag.de/doku.php?id=07.04.2008_bonn&quot;&gt;WebMontag&lt;/a&gt; erläutert hatte was &lt;a href=&quot;http://de.wikipedia.org/wiki/CSRF&quot;&gt;CSRF&lt;/a&gt; ist und was man alles damit anrichten kann, war mir zunächst nicht ganz klar, wie so etwas in der Praxis ausgenutzt wird und welche Schutzmaßnahmen man dagegen implementieren kann.&lt;br /&gt;
&lt;br /&gt;
Netterweise demonstrierte mir mein Kollege &lt;a href=&quot;http://usrportage.de/&quot;&gt;Lary Strojny&lt;/a&gt; anhand meines Projekts &lt;a href=&quot;http://todoyo.de&quot;&gt;todoyo.de&lt;/a&gt; wie so etwas genau aussieht. Er schickte mir einen unscheinbaren Link, den ich natürlich sofort öffnete und gelangte auf eine einfache Seite mit 3 Images, welche allerdings nicht richtig geladen wurden. Die Bilderpfade lauteten in etwa &quot;http://todoyo.de/task/delete/id/1234&quot;. Wäre ich nun bei todoyo eingeloggt gewesen, wären ohne, dass ich etwas gemerkt hätte, einige meiner Aufgaben gelöscht worden. Die IDs der Aufgaben besorgte er sich aus der öffentlichen todoyo-Entwicklerliste. Glücklicherweise war ich nicht eingeloggt &lt;img src=&quot;http://nutwerk.de/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
Dadurch wurde mir schlagartig klar, wie CSRF Angriffe funktionieren und welchen Schaden man damit alles anrichten kann, wenn die Seite nicht entsprechend geschützt ist.&lt;br /&gt;
&lt;br /&gt;
Wie sehen nun die Gegenmaßnahmen aus, um so etwas zu verhindern? Folgende Schritte habe ich unternommen: - Aufgaben-IDs aus öffentlichen Listen entfernt&lt;br /&gt;&lt;br /&gt;
- Bei allen Formularen POST Requests erzwungen&lt;br /&gt;&lt;br /&gt;
- und anschließend nur POST Variablen auswerten&lt;br /&gt;&lt;br /&gt;
- Tokens in jedes Formular eingebaut&lt;br /&gt;&lt;br /&gt;
- Tokens auch für Links zu Datenänderungen benutzen (z.B. einfaches Löschen von Aufgaben per Link statt per Formular)&lt;br /&gt;
&lt;br /&gt;
Im Code sieht das Ganze jetzt so aus:&lt;br /&gt;
&lt;br /&gt;
[geshi lang=php]&lt;br /&gt;
&lt;?php&lt;br /&gt;
// Todoyo/View/Helper/CsrfKey.php&lt;br /&gt;
class Todoyo_View_Helper_CsrfKey&lt;br /&gt;
{&lt;br /&gt;
    protected $_token = &#039;&#039;;&lt;br /&gt;
&lt;br /&gt;
    public function csrfKey()&lt;br /&gt;
    {&lt;br /&gt;
        if (empty($_SESSION[&#039;tokens&#039;])) {&lt;br /&gt;
            $_SESSION[&#039;tokens&#039;] = array();&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        if (empty($this-&gt;_token)) {&lt;br /&gt;
            $this-&gt;_token = md5(uniqid(rand(), TRUE));&lt;br /&gt;
            $_SESSION[&#039;tokens&#039;][] = $this-&gt;_token;&lt;br /&gt;
            $_SESSION[&#039;tokens&#039;] = array_slice($_SESSION[&#039;tokens&#039;], -100);&lt;br /&gt;
        }&lt;br /&gt;
        return $this-&gt;_token;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Todoyo/Controller/Action.php&lt;br /&gt;
class Todoyo_Controller_Action extends Zend_Controller_Action&lt;br /&gt;
{&lt;br /&gt;
    // Prüft ob aktuelle Action geschützt ist und ob CSRF Key gültig ist&lt;br /&gt;
    public function checkCsrfKey($actions)&lt;br /&gt;
    {&lt;br /&gt;
        // Keine CSRF geschützen Actions? Weiter&lt;br /&gt;
        if (empty($actions)) {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        // Action nicht eine der CSRF geschützen Actions? Weiter&lt;br /&gt;
        if (!in_array($this-&gt;_request-&gt;getActionName(), $actions)) {&lt;br /&gt;
            return true;&lt;br /&gt;
    	}&lt;br /&gt;
&lt;br /&gt;
        $token = $this-&gt;_getParam(&#039;x&#039;);&lt;br /&gt;
&lt;br /&gt;
        // Kein Token oder Token nicht in Session? Abbruch!&lt;br /&gt;
        if (empty($token) or !in_array($token, (array) $_SESSION[&#039;tokens&#039;])) {&lt;br /&gt;
            $this-&gt;_flash-&gt;addMessage(&#039;Unerlaubte Aktion&#039;);&lt;br /&gt;
            $this-&gt;_redirect(&#039;/&#039;);&lt;br /&gt;
            return false;&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Token war gültig? Token löschen und weiter&lt;br /&gt;
        $pos = array_search($token, $_SESSION[&#039;tokens&#039;]);&lt;br /&gt;
        unset($_SESSION[&#039;tokens&#039;][$pos]);&lt;br /&gt;
        return true;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // Prupft ob für aktuelle Action POST erzwungen wurde und wirklich POST ist&lt;br /&gt;
    public function checkPost($actions)&lt;br /&gt;
    {&lt;br /&gt;
        // Keine POST Actions erzwungen? Weiter&lt;br /&gt;
        if (empty($actions)) {&lt;br /&gt;
            return true;&lt;br /&gt;
        }&lt;br /&gt;
        // Action keine erzwungene POST Action? Weiter&lt;br /&gt;
        if (!in_array($this-&gt;_request-&gt;getActionName(), $actions)) {&lt;br /&gt;
            return true;&lt;br /&gt;
    	}&lt;br /&gt;
&lt;br /&gt;
    	// Action ist kein POST? Abbruch!&lt;br /&gt;
    	if (!$this-&gt;_request-&gt;isPost()) {&lt;br /&gt;
            $this-&gt;_flash-&gt;addMessage(&#039;Fehler beim Verarbeiten der Formulareingaben&#039;);&lt;br /&gt;
            $this-&gt;_redirect(&#039;/&#039;);&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return $this-&gt;checkCsrfKey($actions);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// TaskController.php&lt;br /&gt;
class TaskController extends Todoyo_Controller_Action&lt;br /&gt;
{&lt;br /&gt;
    public function init()&lt;br /&gt;
    {&lt;br /&gt;
    	parent::init();&lt;br /&gt;
    	$this-&gt;checkCsrfKey(array(&#039;insert&#039;, &#039;delete&#039;));&lt;br /&gt;
    	$this-&gt;checkPost(array(&#039;insert&#039;));&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// index/index.phtml&lt;br /&gt;
&lt;form action=&quot;/task/insert&quot; method=&quot;post&quot;&gt;&lt;br /&gt;
    &lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;&quot;&gt;&lt;br /&gt;
    &lt;input type=&quot;hidden&quot; name=&quot;x&quot; value=&quot;&lt;?=$this-&gt;csrfKey()?&gt;&quot;&gt;&lt;br /&gt;
    &lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;Speichern&quot;&gt;&lt;br /&gt;
&lt;/form&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;a href=/task/delete/id/1234/x/&lt;?=$this-&gt;csrfKey()?&gt;&gt;Aufgabe löschen&lt;/a&gt;&lt;br /&gt;
[/geshi]&lt;br /&gt;
&lt;br /&gt;
Was geschieht im Detail?&lt;br /&gt;
&lt;br /&gt;
Im Template wird nun bei jeder Aktion, die geschützt werden soll, ein CSRF Key (Token) entweder als Hidden Input Feld eingefügt, oder bei Links mit an die URL angehangen.&lt;br /&gt;
Der CsrfKey-View-Helper liefert bei jedem Aufruf einen neuen zufälligen String, der in der Session gespeichert wird. Pro Seitenaufruf wird ein einziger Token erzeugt und für alle Elemente verwendet. Die Anzahl der gültigen Tokens wurde auf 100 beschränkt, um die Session nicht unnötig aufzublähen und dennoch gültige Requests bei mehreren Tabs/Seiten zu ermöglichen.&lt;br /&gt;
&lt;br /&gt;
Nach dem Abschicken eines Formulars, wird bevor die eigentliche Action ausgeführt wird, geprüft, ob die Aktion durch einen POST-Request entstanden sein muss, was bei Formularen klar der Fall ist. Der Methode &quot;checkPost&quot; werden also alle Actions übergeben, bei denen wir POST erzwingen wollen. Zusätzlich wir bei definierten Actions geprüft, ob sie einen CSRF Key besitzen müssen, und falls ja, ob dieser auch gültig ist (=in der Session vorhanden ist). Wenn ja, dann wird der benutzte Token aus der Session gelöscht und die Action wir ausgeführt. Bei der Verwendung von &quot;checkPost()&quot; wird automatisch auch der CSRF Key überprüft, weil alle Formulare zwingend einen gültigen Token haben müssen, URLs hingegen nur bei Bedarf.&lt;br /&gt;
&lt;br /&gt;
Somit kann man für jeden Controller ganz einfach definieren, welche Actions ausschließlich per POST aufgerufen werden dürfen und welche durch CSRF geschützt werden sollen. In der Regeln ist dies bei allen Aktionen der Fall, bei denen Daten geändert werden (insert, update, delete,...). Bei Anzeige-Aktionen legt man eher Wert auf schöne URLs ohne einen Token.&lt;br /&gt;
&lt;br /&gt;
Für weitere Verbesserungsvorschläge oder Fehlerhinweise wäre ich sehr dankbar &lt;img src=&quot;http://nutwerk.de/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;&lt;br /&gt;
&lt;br /&gt;
&lt;strong&gt;UPDATE:&lt;/strong&gt;&lt;br /&gt;
&lt;br /&gt;
Im &lt;a href=&quot;http://www.zfforum.de/showthread.php?t=1808&quot;&gt;deutschen Zend Framework Forum&lt;/a&gt; wurden ein paar Vorschläge geäußert:&lt;br /&gt;
&lt;br /&gt;
- Auslagerung der &quot;checkPost()&quot; und &quot;checkCsrf()&quot; Funktionalität in einen eigenen &lt;a href=&quot;http://framework.zend.com/manual/de/zend.controller.actionhelpers.html#zend.controller.actionhelper.writingyourown&quot;&gt;ActionHelper&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;
- Nutzung von &lt;a href=&quot;http://framework.zend.com/manual/de/zend.session.html&quot;&gt;Zend_Session_Namespace&lt;/a&gt; zum Zugriff auf die Session Tokens&lt;br /&gt;&lt;br /&gt;
- Erstellung eines &lt;a href=&quot;http://framework.zend.com/manual/de/zend.form.elements.html#zend.form.elements.custom&quot;&gt;Zend_Form_Element&lt;/a&gt; um z.B. automatisch bei jedem Form das Hidden Token Element hinzuzufügen&lt;br /&gt; 
    </content:encoded>

    <pubDate>Tue, 22 Apr 2008 13:12:00 +0200</pubDate>
    <guid isPermaLink="false">http://nutwerk.de/archives/15-guid.html</guid>
    
</item>
<item>
    <title>Deutsches ZendFramework Forum</title>
    <link>http://nutwerk.de/archives/6-Deutsches-ZendFramework-Forum.html</link>
            <category>ZendFramework</category>
    
    <comments>http://nutwerk.de/archives/6-Deutsches-ZendFramework-Forum.html#comments</comments>
    <wfw:comment>http://nutwerk.de/wfwcomment.php?cid=6</wfw:comment>

    <slash:comments>0</slash:comments>
    <wfw:commentRss>http://nutwerk.de/rss.php?version=2.0&amp;type=comments&amp;cid=6</wfw:commentRss>
    

    <author>nospam@example.com (Marc Jakubowski)</author>
    <content:encoded>
    Seit kurzem gibt es unter &lt;a href=&quot;http://www.zfforum.de&quot;  title=&quot;zfforum&quot;&gt;zfforum.de&lt;/a&gt; endlich ein deutschsprachiges Forum, welches das &lt;a href=&quot;http://framework.zend.com&quot;  title=&quot;ZF&quot;&gt;ZendFramework&lt;/a&gt; zum Thema hat.&lt;br /&gt;
Bis dato spielte sich die Kommunikation lediglich über die &lt;a href=&quot;http://framework.zend.com/wiki/display/ZFDEV/Contributing+to+Zend+Framework#ContributingtoZendFramework-Subscribetotheappropriatemailinglists&quot;  title=&quot;ZF Mailinglisten&quot;&gt;ZF-Mailinglisten&lt;/a&gt; ab, wobei dort jedoch ausschließlich auf Englisch geschrieben wird und der Zugang für ZF-Einsteiger und Mailinglisten-Unerfahrene doch etwas umständlich ist.&lt;br /&gt;
&lt;br /&gt;
Aber das ist ja jetzt vorbei &lt;img src=&quot;http://nutwerk.de/templates/default/img/emoticons/wink.png&quot; alt=&quot;;-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt; &lt;br /&gt;
Nachdem bis letzte Woche noch am Aufbau der Kategorien und Foren gefeilt wurde, ist die Seite nun seit einer Woche offiziell online und es wurden bereits viele interessante Themen behandelt, seien es Einsteigerproblemchen oder spezielle Fragestellungen zu den einzelnen Komponenten. Qualifizierte Schreiber sind auf jeden Fall genug an Bord, so dass eigentlich keine Frage unbeantwortet bleiben dürfte.&lt;br /&gt;
&lt;br /&gt;
Wer sich also mit dem ZendFramework beschäftigt und sich mit anderen Entwicklern austauschen möchte, der ist dort bestens aufgehoben &lt;img src=&quot;http://nutwerk.de/templates/default/img/emoticons/smile.png&quot; alt=&quot;:-)&quot; style=&quot;display: inline; vertical-align: bottom;&quot; class=&quot;emoticon&quot; /&gt;  
    </content:encoded>

    <pubDate>Thu, 28 Dec 2006 16:31:00 +0100</pubDate>
    <guid isPermaLink="false">http://nutwerk.de/archives/6-guid.html</guid>
    
</item>

</channel>
</rss>