]> git.agnieray.net Git - galette.git/commitdiff
Fix XSS, prevent their storage
authorJohan Cwiklinski <johan@x-tnd.be>
Tue, 9 Nov 2021 07:35:51 +0000 (08:35 +0100)
committerJohan Cwiklinski <trasher@x-tnd.be>
Tue, 9 Nov 2021 21:51:39 +0000 (22:51 +0100)
Use HTML purifier lib to sanitize preferences footer

galette/composer.json
galette/composer.lock
galette/lib/Galette/Controllers/Crud/PaymentTypeController.php
galette/lib/Galette/Core/Preferences.php
galette/lib/Galette/Entity/Entitled.php
galette/lib/Galette/Entity/Title.php
galette/lib/Galette/Entity/Transaction.php
galette/templates/default/gestion_intitule_content.tpl
galette/templates/default/gestion_titres.tpl
galette/templates/default/gestion_transactions.tpl

index 7188763d5a1eeda862b1a773d5e9fb4a3bc6bc7e..f33d8d0058ffe551de593e1e72b8eb7d4ed273ee 100644 (file)
@@ -49,7 +49,8 @@
         "php-di/slim-bridge": "2.0.0",
         "doctrine/annotations": "^1.8",
         "laminas/laminas-servicemanager": "3.7",
-        "symfony/polyfill-php80": "^1.23"
+        "symfony/polyfill-php80": "^1.23",
+        "ezyang/htmlpurifier": "^4.13"
     },
     "require-dev": {
         "atoum/atoum": "dev-master",
index 41ae74895e43de5277edfe6ee7943101e2d42f89..79e9819a4e3fa41a916ec577219a14c04dd4a7c3 100644 (file)
@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
     ],
-    "content-hash": "abdb30cee5eeb0dad05c159a1c10880d",
+    "content-hash": "47d56d47701d9038105bd93cf3b44a02",
     "packages": [
         {
             "name": "akrabat/rka-slim-session-middleware",
             ],
             "time": "2020-05-25T17:44:05+00:00"
         },
+        {
+            "name": "ezyang/htmlpurifier",
+            "version": "v4.13.0",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/ezyang/htmlpurifier.git",
+                "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
+                "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=5.2"
+            },
+            "require-dev": {
+                "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-0": {
+                    "HTMLPurifier": "library/"
+                },
+                "files": [
+                    "library/HTMLPurifier.composer.php"
+                ],
+                "exclude-from-classmap": [
+                    "/library/HTMLPurifier/Language/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "LGPL-2.1-or-later"
+            ],
+            "authors": [
+                {
+                    "name": "Edward Z. Yang",
+                    "email": "admin@htmlpurifier.org",
+                    "homepage": "http://ezyang.com"
+                }
+            ],
+            "description": "Standards compliant HTML filter written in PHP",
+            "homepage": "http://htmlpurifier.org/",
+            "keywords": [
+                "html"
+            ],
+            "support": {
+                "issues": "https://github.com/ezyang/htmlpurifier/issues",
+                "source": "https://github.com/ezyang/htmlpurifier/tree/master"
+            },
+            "time": "2020-06-29T00:56:53+00:00"
+        },
         {
             "name": "laminas/laminas-cache",
             "version": "2.13.0",
index f5072d48a5714c974f7fcc6d499f675043129a4a..af1796e71b3e7b09b1305654b091228d47703188 100644 (file)
@@ -7,7 +7,7 @@
  *
  * PHP version 5
  *
- * Copyright © 2019-2020 The Galette Team
+ * Copyright © 2019-2021 The Galette Team
  *
  * This file is part of Galette (http://galette.tuxfamily.org).
  *
@@ -28,7 +28,7 @@
  * @package   Galette
  *
  * @author    Johan Cwiklinski <johan@x-tnd.be>
- * @copyright 2019-2020 The Galette Team
+ * @copyright 2019-2021 The Galette Team
  * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
  * @link      http://galette.tuxfamily.org
  * @since     Available since 0.9.4dev - 2019-12-09
@@ -50,7 +50,7 @@ use Analog\Analog;
  * @name      PaymentTypeController
  * @package   Galette
  * @author    Johan Cwiklinski <johan@x-tnd.be>
- * @copyright 2019-2020 The Galette Team
+ * @copyright 2019-2021 The Galette Team
  * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
  * @link      http://galette.tuxfamily.org
  * @since     Available since 0.9.4dev - 2019-12-09
@@ -205,7 +205,7 @@ class PaymentTypeController extends CrudController
                     'error_detected',
                     preg_replace(
                         '(%s)',
-                        $ptype->name,
+                        $ptype->getName(),
                         _T("Payment type '%s' has not been added!")
                     )
                 );
@@ -214,7 +214,7 @@ class PaymentTypeController extends CrudController
                     'error_detected',
                     preg_replace(
                         '(%s)',
-                        $ptype->name,
+                        $ptype->getName(),
                         _T("Payment type '%s' has not been modified!")
                     )
                 );
@@ -227,7 +227,7 @@ class PaymentTypeController extends CrudController
                     'success_detected',
                     preg_replace(
                         '(%s)',
-                        $ptype->name,
+                        $ptype->getName(),
                         _T("Payment type '%s' has been successfully added.")
                     )
                 );
@@ -236,7 +236,7 @@ class PaymentTypeController extends CrudController
                     'success_detected',
                     preg_replace(
                         '(%s)',
-                        $ptype->name,
+                        $ptype->getName(),
                         _T("Payment type '%s' has been successfully modified.")
                     )
                 );
index 66395fa14d119900df283421716208ae6dd2fb8e..e488c4c8ce656dabfb25e583c528066db648893d 100644 (file)
@@ -755,6 +755,9 @@ class Preferences
                     $this->errors[] = _T("- Invalid year for cards.");
                 }
                 break;
+            case 'pref_footer':
+                $value = $this->cleanHtmlValue($value);
+                break;
         }
 
         return $value;
@@ -961,6 +964,8 @@ class Preferences
                 && $name == 'pref_mail_method'
             ) {
                 return GaletteMail::METHOD_DISABLED;
+            } elseif ($name == 'pref_footer') {
+                return $this->cleanHtmlValue($this->prefs[$name]);
             } else {
                 if ($name == 'pref_adhesion_form' && $this->prefs[$name] == '') {
                     $this->prefs[$name] = self::$defaults['pref_adhesion_form'];
@@ -1294,4 +1299,19 @@ class Preferences
 
         return $this;
     }
+
+    /**
+     * Purify HTML value
+     *
+     * @param string $value Value to clean
+     *
+     * @return string
+     */
+    public function cleanHtmlValue(string $value): string
+    {
+        $config = \HTMLPurifier_Config::createDefault();
+        $config->set('Cache.SerializerPath', GALETTE_CACHE_DIR);
+        $purifier = new \HTMLPurifier($config);
+        return $purifier->purify($value);
+    }
 }
index 20e71edbb5261c94e0c1d63166c285ce343c5632..b4671a28dc03615c1dc2d9675711b5607fb7aeeb 100644 (file)
@@ -429,6 +429,7 @@ abstract class Entitled
     public function add($label, $extra)
     {
         // Avoid duplicates.
+        $label = strip_tags($label);
         $ret = $this->getIdByLabel($label);
 
         if ($ret !== false) {
@@ -489,6 +490,7 @@ abstract class Entitled
      */
     public function update($id, $label, $extra)
     {
+        $label = strip_tags($label);
         $ret = $this->get($id);
         if (!$ret) {
             /* get() already logged and set $this->error. */
index 3218522f0947e7e95223b0e178abae090ad6ba17..dfdc2d174a76c1a7324cad6a3d13e63a25f0ffe5 100644 (file)
@@ -139,8 +139,8 @@ class Title
     public function store($zdb)
     {
         $data = array(
-            'short_label'   => $this->short,
-            'long_label'    => $this->long
+            'short_label'   => strip_tags($this->short),
+            'long_label'    => strip_tags($this->long)
         );
         try {
             if ($this->id !== null && $this->id > 0) {
index 08caee36c5379e7b7f0d4c35dbddfb66bd67c704..799d5e91af87891ff235b523489821fb31a382f5 100644 (file)
@@ -357,7 +357,7 @@ class Transaction
                             break;
                         case 'trans_desc':
                             /** TODO: retrieve field length from database and check that */
-                            $this->_description = $value;
+                            $this->_description = strip_tags($value);
                             if (mb_strlen($value) > 150) {
                                 $this->errors[] = _T("- Transaction description must be 150 characters long maximum.");
                             }
index ee9f05a0995d0e9e61300214a847166b09f5ef10..a6cfa2a85eb696b6302ceb83f95cd9650a40f35e 100644 (file)
@@ -57,7 +57,7 @@
                     {$eid}
                     <span class="row-title">
                         <a href="{path_for name="editEntitled" data=["class" => $url_class, "action" => "edit", "id" => $eid]}">
-                            {_T string="%s field" pattern="/%s/" replace=$entry.name}
+                            {_T string="%s field" pattern="/%s/" replace=$entry.name|escape}
                         </a>
                     </span>
                 </td>
                         class="action tooltip"
                     >
                         <i class="fas fa-edit fa-fw"></i>
-                        <span class="sr-only">{_T string="Edit '%s' field" pattern="/%s/" replace=$entry.name}</span>
+                        <span class="sr-only">{_T string="Edit '%s' field" pattern="/%s/" replace=$entry.name|escape}</span>
                     </a>
                     <a
                         href="{path_for name="removeEntitled" data=["class" => $url_class, "id" => $eid]}"
                         class="delete tooltip"
                     >
                         <i class="fas fa-trash fa-fw"></i>
-                        <span class="sr-only">{_T string="Delete '%s' field" pattern="/%s/" replace=$entry.name}</span>
+                        <span class="sr-only">{_T string="Delete '%s' field" pattern="/%s/" replace=$entry.name|escape}</span>
                     </a>
                 </td>
             </tr>
index 52ed939c85f36731fe9e941cbf44ef1c8209aa40..762e32dea2ee52a49f59475b7deba5e468f3c2bd 100644 (file)
     {/if}
                                 <span class="row-title">
                                     <a href="{path_for name="editTitle" data=["id" => $title->id]}">
-                                        {_T string="%s title" pattern="/%s/" replace=$title->short}
+                                        {_T string="%s title" pattern="/%s/" replace=$title->short|escape}
                                     </a>
                                 </span>
                             </td>
-                            <td class="left" data-title="{_T string="Short form"}">{$title->short}</td>
-                            <td class="left" data-title="{_T string="Long form"}">{$title->long}</td>
+                            <td class="left" data-title="{_T string="Short form"}">{$title->short|escape}</td>
+                            <td class="left" data-title="{_T string="Long form"}">{$title->long|escape}</td>
                             <td class="center actions_row">
                                 <a
                                     href="{path_for name="editTitle" data=["id" => $title->id]}"
                                     class="tooltip action"
                                 >
                                     <i class="fas fa-edit fa-fw"></i>
-                                    <span class="sr-only">{_T string="Edit '%s' title" pattern="/%s/" replace=$title->short}</span>
+                                    <span class="sr-only">{_T string="Edit '%s' title" pattern="/%s/" replace=$title->short|escape}</span>
                                 </a>
                 {if $title->id eq 1 or $title->id eq 2}
                                 <img src="{base_url}/{$template_subdir}images/icon-empty.png" alt="" width="16px" height="16px"/>
@@ -66,7 +66,7 @@
                                     class="delete tooltip"
                                 >
                                     <i class="fa fa-trash fa-fw"></i>
-                                    <span class="sr-only">{_T string="Delete '%s' title" pattern="/%s/" replace=$title->short}</span>
+                                    <span class="sr-only">{_T string="Delete '%s' title" pattern="/%s/" replace=$title->short|escape}</span>
                                 </a>
                 {/if}
                             </td>
index b812baf43b6e3762da9d4161bd3ee0d7becb15fc..69273777eb0e4b779d9115e04161efbcc85932fc 100644 (file)
                             </a>
                         </td>
                     {/if}
-                    <td class="{$cclass} nowrap" data-title="{_T string="Description"}">{$transaction->description}</td>
+                    <td class="{$cclass} nowrap" data-title="{_T string="Description"}">{$transaction->description|escape}</td>
 {if $login->isAdmin() or $login->isStaff()}
                     <td class="{$cclass}" data-title="{_T string="Originator"}">
     {if $filters->filtre_cotis_adh eq ""}