VYPR
Unrated severityOSV Advisory· Published Aug 6, 2018· Updated Aug 5, 2024

CVE-2018-14857

CVE-2018-14857

Description

Unrestricted file upload (with remote code execution) in require/mail/NotificationMail.php in Webconsole in OCS Inventory NG OCS Inventory Server through 2.5 allows a privileged user to gain access to the server via a template file containing PHP code, because file extensions other than .html are permitted.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Privileged users can upload arbitrary PHP files via notification templates in OCS Inventory Server ≤2.5, leading to remote code execution.

Vulnerability

In OCS Inventory NG OCS Inventory Server through version 2.5, the require/mail/NotificationMail.php file in the Webconsole component allows unrestricted file upload. The code does not restrict file extensions to .html only, enabling a privileged user to upload a template file containing arbitrary PHP code. The upload is performed via the notification template feature, and the file is later executed on the server. The commit at [1] introduced a constant HTML_EXT and validation, but prior to that fix, any file extension was accepted.

Exploitation

An attacker must have a privileged account (e.g., administrative access) on the OCS Inventory Server to access the Webconsole and upload custom notification templates. The attacker uploads a file with a .php (or other executable) extension containing malicious PHP code. The file is stored on the server and can be accessed directly via the web server, leading to code execution. The attack requires no special network position beyond valid credentials and network access to the Webconsole.

Impact

Successful exploitation allows the attacker to execute arbitrary PHP code on the server, potentially leading to full compromise of the OCS Inventory Server and access to sensitive inventory data. The attacker can achieve remote code execution with the privileges of the web server user, enabling data theft, further lateral movement, or denial of service.

Mitigation

The vulnerability is fixed in commit [1] which enforces that only .html files are uploaded as notification templates. Users should upgrade to a version that includes this fix (release 2.6 or later). As a workaround, administrators can restrict file upload permissions or deploy a web application firewall to block suspicious file extensions. No workaround is available for versions prior to the fix.

AI Insight generated on May 26, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

2

Patches

1
cc572819e373

Merge pull request #525 from OCSInventory-NG/notification-improvement

5 files changed · +68 16
  • plugins/language/en_GB/en_GB.txt+2 0 modified
    @@ -1543,3 +1543,5 @@
     8017 This file is not an html file
     8018 Subject
     8019 Notification OCSInventory
    +8020 WARNING : Mail template file not found
    +8021 The uploaded file need to have .html extension to be valid
    \ No newline at end of file
    
  • plugins/language/fr_FR/fr_FR.txt+2 0 modified
    @@ -1541,3 +1541,5 @@
     8016 Ici vous pouvez télécharger votre modèle de notification personnalisé:</br>• Le fichier doit être un fichier html.</br></br>Informations:</br>• Pour avoir les traduction mettez {{g.(numéro de la traduction)}} dans votre code html - Exemple: {{g.49}} = Nom</br>• Pour le moment vous disposez de deux choix de rapport d'inventaire: </br> {{Report.Software}} - Nombre de logiciels par catégorie de logiciel </br> {{Report.Asset}} - Nombre de machines par catégorie d'actifs
     8017 Ce fichier n'est pas un fichier html
     8018 Sujet
    +8020 WARNING : Fichier de template personnalisé non trouvé
    +8021 Le fichier upload doit avoir pour extension .html
    
  • plugins/main_sections/ms_config/ms_notification.php+4 1 modified
    @@ -192,10 +192,13 @@
     
         //Perso
         $info = $mail->get_all_information('PERSO');
    +    $output = $mail->replace_value($mail->get_template_perso(), 'PERSO');
    +    if(!$output){
    +        $output = $l->g(8020);
    +    }
         echo "<div id=perso_mail ".$style_perso.">";
         echo "<div class='form-group'><label class='control-label col-sm-2' for='subject'>".$l->g(8018)."</label><div class='col-sm-8'>
               <input type='text' class='form-control' id='subject' name='subject' size='50' maxlength='255' value='".$info['PERSO']['SUBJECT']."'/></div></div>";
    -    $output = $mail->replace_value($mail->get_template_perso(), 'PERSO');
         echo $output;
         echo "</div>";
     
    
  • require/mail/NotificationMail.php+49 15 modified
    @@ -48,6 +48,8 @@ class NotificationMail
                             );
           private $week = array('MON' => 'MON', 'TUE' => 'TUE', 'WED' => 'WED', 'THURS' => 'THURS', 'FRI' => 'FRI', 'SAT' => 'SAT', 'SUN' => 'SUN');
     
    +      const HTML_EXT = 'html';
    +      
           public function __construct($language){
             global $l;
             $l = new language($language);
    @@ -180,20 +182,27 @@ public function config_mailer(){
            * @return void
            */
          public function send_notification($subject, $body, $altBody = '', $selected, $isHtml = false ){
    -          $body = $this->replace_value($body, $selected);
    -          try{
    -             // Content
    -             $this->notif->isHTML(false);
    -             $this->notif->Subject = $subject;
    -             $this->notif->Body    = $body;
    -             $this->notif->AltBody = $altBody;
    -
    -             $this->notif->send();
    -             error_log('Message has been sent');
    -         } catch (Exception $e) {
    -             $msg = 'Message could not be sent. Mailer Error: '. $mail->ErrorInfo;
    -             error_log($msg);
    -         }
    +            
    +            $body = $this->replace_value($body, $selected);
    +         
    +            if(!$body){
    +                error_log('Error reading custom template');
    +                return false;
    +            }
    +            
    +            try{
    +               // Content
    +               $this->notif->isHTML(false);
    +               $this->notif->Subject = $subject;
    +               $this->notif->Body    = $body;
    +               $this->notif->AltBody = $altBody;
    +
    +               $this->notif->send();
    +               error_log('Message has been sent');
    +           } catch (Exception $e) {
    +               $msg = 'Message could not be sent. Mailer Error: '. $mail->ErrorInfo;
    +               error_log($msg);
    +           }
           }
     
           /**
    @@ -214,7 +223,11 @@ public function replace_value($file, $selected){
               if($selected == 'DEFAULT'){
                 $template = file_get_contents(TEMPLATE.'OCS_template.html', true);
               }else{
    -            $template = file_get_contents($file, true);
    +            if(file_exists($file)){
    +                $template = file_get_contents($file, true); 
    +            }else{
    +                return false;
    +            }
               }
     
               if(strpos($template, "{{") !== false){
    @@ -263,6 +276,11 @@ public function replace_value($file, $selected){
           public function upload_file($file, $subject){
               global $l;
               $uploadFile = TEMPLATE . basename($file['template']['name']);
    +          
    +          if(!$this->is_html_extension($uploadFile)){
    +              msg_error($l->g(8021));
    +              return false;
    +          }
     
               if($file['template']['type'] == 'text/html'){
                 if (move_uploaded_file($_FILES['template']['tmp_name'], $uploadFile)) {
    @@ -280,6 +298,22 @@ public function upload_file($file, $subject){
                 return false;
               }
           }
    +      
    +      /**
    +       * Check if file respect naming convention
    +       * And have extension .html
    +       * 
    +       * @param array $uploaded_file
    +       */
    +      private function is_html_extension($uploaded_file_name){
    +          $ext = end((explode(".", $uploaded_file_name)));
    +          var_dump($ext);
    +          if($ext == self::HTML_EXT){
    +              return true;
    +          }else{
    +              return false;
    +          }
    +      }
     
           /**
            * Get directory template perso
    
  • templates/.htaccess+11 0 added
    @@ -0,0 +1,11 @@
    +# Prevent direct access to folder
    +
    +# Apache 2.2
    +<IfModule !mod_authz_core.c>
    +    Deny from all
    +</IfModule>
    +
    +# Apache 2.4
    +<IfModule mod_authz_core.c>
    +    Require all denied
    +</IfModule>
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

3

News mentions

0

No linked articles in our index yet.