CVE-2022-4397 (published 2022-12-10T19:15Z)

A vulnerability was found in morontt zend-blog-number-2. It has been classified as problematic. Affected is an unknown function of the file application/forms/Comment.php of the component Comment Handler. The manipulation leads to cross-site request forgery. It is possible to launch the attack remotely. The name of the patch is 36b2d4abe20a6245e4f8df7a4b14e130b24d429d. It is recommended to apply a patch to fix this issue. VDB-215250 is the identifier assigned to this vulnerability.

CVSS v3 base score: 6.5, MEDIUM (CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:N/I:H/A:N)

Weakness information:
cwe_id: CWE-352
cwe_name: Cross-Site Request Forgery (CSRF)
description: The web application does not, or can not, sufficiently verify whether a well-formed, valid, consistent request was intentionally provided by the user who submitted the request.
extended_description: When a web server is designed to receive a request from a client without any mechanism for verifying that it was intentionally sent, then it might be possible for an attacker to trick a client into making an unintentional request to the web server which will be treated as an authentic request. This can be done via a URL, image load, XMLHttpRequest, etc. and can result in exposure of data or unintended code execution.
         

Fix information:
repo_url: https://github.com/morontt/zend-blog-number-2
commit_details: repo_url: https://github.com/morontt/zend-blog-number-2
author: Alexander Harchenko
author_date: 2022-06-23 20:26:53+03:00
msg: Add CSRF-token for comments
repository: repo_url: https://github.com/morontt/zend-blog-number-2
repo_name: morontt/zend-blog-number-2
description: Zend Framework Blog
repo_language: PHP
owner: morontt
file_changes: filename: IndexController.php
change_type: ModificationType.MODIFY
diff: @@ -154,6 +154,7 @@ class IndexController extends Zend_Controller_Action
 
         $form = new Application_Form_Comment();
         $form->topicId->setValue($post->id);
+        $form->getElement('csrfToken')->setValue($this->generateCommentToken());
 
         $this->view->form = $form;
 
@@ -234,7 +235,10 @@ RAW;
             if ($form->isValid($this->getRequest()->getPost())) {
                 $formData = $form->getValues();
 
-                $this->saveComment($topicId, $url, $formData);
+                if ($this->validCommentToken($formData['csrfToken'])) {
+                    $this->saveComment($topicId, $url, $formData);
+                }
+
                 $result['valid'] = true;
             } else {
                 $formView = new Zend_View;
@@ -413,4 +417,29 @@ RAW;
             && (stripos($_SERVER['HTTP_VIA'], 'BunnyCDN') !== false
                 || strpos($_SERVER['HTTP_VIA'], 'cdn77') !== false);
     }
+
+    private function generateCommentToken($time = null): string
+    {
+        $time = $time ?? time();
+        $userAgent = $_SERVER['HTTP_USER_AGENT'] ?? '';
+
+        return base64_encode($time . ':' . hash('md5', 'MD5_' . $userAgent . $time, true));
+    }
+
+    private function validCommentToken($token): bool
+    {
+        $raw = base64_decode($token, true);
+        if ($raw === false) {
+            return false;
+        }
+
+        $position = strpos($raw, ':');
+        if ($position === false) {
+            return false;
+        }
+
+        $time = substr($raw, 0, $position);
+
+        return hash_equals($this->generateCommentToken($time), $token);
+    }
 }

programming_language: PHP
filename: Comment.php
change_type: ModificationType.MODIFY
diff: @@ -85,6 +85,10 @@ class Application_Form_Comment extends Zend_Form
             $this->checkCookie();
         }
 
+        $csrfToken = new Zend_Form_Element_Hidden('csrfToken');
+        $csrfToken->addValidator('NotEmpty');
+        $this->addElement($csrfToken);
+
         $this->setElementDecorators($this->elementDecorators);
     }
 

programming_language: PHP
filename: formcomment.phtml
change_type: ModificationType.MODIFY
diff: @@ -17,6 +17,7 @@
         <?php echo $this->form->topicId; ?>
         <?php echo $this->form->parentId; ?>
         <?php echo $this->form->cookie; ?>
+        <?php echo $this->form->csrfToken; ?>
     </div>
     <div class="ym-fbox-button">
         <button type="submit" class="ym-button ym-add" id="submit" name="submit">Добавить комментарий</button>

programming_language: PHP