CVE-2019-13239: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: inc/user.class.php in GLPI before 9.4.3 allows XSS via a user picture.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 6.1
Published: 2019-07-04T15:15Z
Repository: https://github.com/glpi-project/glpi
Language: PHP
Files changed: inc/user.class.php
Commit date: 2019-06-20 12:02:37 +0200
Commit message: avoid xss attack on user picture

Diff: diff --git a/inc/user.class.php b/inc/user.class.php
index 096721ce5..b1126f3af 100755
--- a/inc/user.class.php
+++ b/inc/user.class.php
@@ -548,10 +548,15 @@ class User extends CommonDBTM {
          Session::addMessageAfterRedirect(__('The login is not valid. Unable to add the user.'),
                                           false, ERROR);
          return false;
       }
 
+      // avoid xss (picture field is autogenerated)
+      if (isset($input['picture'])) {
+         $input['picture'] = 'NULL';
+      }
+
       if (!isset($input["authtype"])) {
          $input["authtype"] = Auth::DB_GLPI;
       }
 
       if (!isset($input["auths_id"])) {
@@ -679,10 +684,15 @@ class User extends CommonDBTM {
 
 
    function prepareInputForUpdate($input) {
       global $CFG_GLPI;
 
+      // avoid xss (picture field is autogenerated)
+      if (isset($input['picture'])) {
+         $input['picture'] = 'NULL';
+      }
+
       //picture manually uploaded by user
       if (isset($input["_blank_picture"]) && $input["_blank_picture"]) {
          self::dropPictureFiles($this->fields['picture']);
          $input['picture'] = 'NULL';
       } else {
@@ -2002,10 +2012,11 @@ class User extends CommonDBTM {
          echo "<td class='b'>" . $this->fields["name"];
          echo "<input type='hidden' name='name' value=\"" . $this->fields["name"] . "\"></td>";
       }
 
       if (!empty($this->fields["name"])) {
+
          echo "<td rowspan='4'>" . __('Picture') . "</td>";
          echo "<td rowspan='4'>";
          echo "<div class='user_picture_border_small' id='picture$rand'>";
          echo "<img class='user_picture_small' alt=\"".__s('Picture')."\" src='".
                 User::getThumbnailURLForPicture($this->fields['picture'])."'>";
@@ -4851,10 +4862,13 @@ class User extends CommonDBTM {
     * @return string
     */
    static function getURLForPicture($picture) {
       global $CFG_GLPI;
 
+      // prevent xss
+      $picture = Html::cleanInputText($picture);
+
       if (!empty($picture)) {
          return $CFG_GLPI["root_doc"]."/front/document.send.php?file=_pictures/$picture";
       }
       return $CFG_GLPI["root_doc"]."/pics/picture.png";
    }
@@ -4870,10 +4884,13 @@ class User extends CommonDBTM {
     * @return string
     */
    static function getThumbnailURLForPicture($picture) {
       global $CFG_GLPI;
 
+      // prevent xss
+      $picture = Html::cleanInputText($picture);
+
       if (!empty($picture)) {
          $tmp = explode(".", $picture);
          if (count($tmp) ==2) {
             return $CFG_GLPI["root_doc"]."/front/document.send.php?file=_pictures/".$tmp[0].
                    "_min.".$tmp[1];

Fixed code:       // avoid xss (picture field is autogenerated)
      if (isset($input['picture'])) {
         $input['picture'] = 'NULL';
      }

      // avoid xss (picture field is autogenerated)
      if (isset($input['picture'])) {
         $input['picture'] = 'NULL';
      }


      // prevent xss
      $picture = Html::cleanInputText($picture);

      // prevent xss
      $picture = Html::cleanInputText($picture);