Vulnerability: inc/user.class.php in GLPI before 9.4.3 allows XSS via a user picture.
Vulnerability ID: CVE-2019-13239
CWE: CWE-79
Severity score: 2.9
Project: https://github.com/glpi-project/glpi
Published: 2019-07-04
File: inc/user.class.php
Commit message: avoid xss attack on user picture
Commit author: Alexandre Delaunay

Vulnerable version (before fix):
 function prepareInputForAdd($input) {          return false;       }        if (!isset($input["authtype"])) {          $input["authtype"] = Auth::DB_GLPI;       } function post_addItem() {    function prepareInputForUpdate($input) {       global $CFG_GLPI;        //picture manually uploaded by user       if (isset($input["_blank_picture"]) && $input["_blank_picture"]) {          self::dropPictureFiles($this->fields['picture']); function showForm($ID, array $options = []) {       }        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'>"; static function checkDefaultPasswords() {    static function getURLForPicture($picture) {       global $CFG_GLPI;        if (!empty($picture)) {          return $CFG_GLPI["root_doc"]."/front/document.send.php?file=_pictures/$picture";       } static function getURLForPicture($picture) {    static function getThumbnailURLForPicture($picture) {       global $CFG_GLPI;        if (!empty($picture)) {          $tmp = explode(".", $picture);          if (count($tmp) ==2) {

Fixed version (after fix):
 function prepareInputForAdd($input) {          return false;       }        // avoid xss (picture field is autogenerated)       if (isset($input['picture'])) {          $input['picture'] = 'NULL';       }        if (!isset($input["authtype"])) {          $input["authtype"] = Auth::DB_GLPI;       } function post_addItem() {    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']); function showForm($ID, array $options = []) {       }        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'>"; static function checkDefaultPasswords() {    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";       } static function getURLForPicture($picture) {    static function getThumbnailURLForPicture($picture) {       global $CFG_GLPI;        // prevent xss       $picture = Html::cleanInputText($picture);        if (!empty($picture)) {          $tmp = explode(".", $picture);          if (count($tmp) ==2) {

Patch:
patch: @@ -550,6 +550,11 @@ function prepareInputForAdd($input) {
          return false;
       }
 
+      // avoid xss (picture field is autogenerated)
+      if (isset($input['picture'])) {
+         $input['picture'] = 'NULL';
+      }
+
       if (!isset($input["authtype"])) {
          $input["authtype"] = Auth::DB_GLPI;
       }
@@ -681,6 +686,11 @@ function post_addItem() {
    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']);
@@ -2004,6 +2014,7 @@ function showForm($ID, array $options = []) {
       }
 
       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'>";
@@ -4853,6 +4864,9 @@ static function checkDefaultPasswords() {
    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";
       }
@@ -4872,6 +4886,9 @@ static function getURLForPicture($picture) {
    static function getThumbnailURLForPicture($picture) {
       global $CFG_GLPI;
 
+      // prevent xss
+      $picture = Html::cleanInputText($picture);
+
       if (!empty($picture)) {
          $tmp = explode(".", $picture);
          if (count($tmp) ==2) {
path: inc/user.class.php