CVE-2023-50917 (PHP, published 2023-12-15T17:15Z)
Description: value: MajorDoMo (aka Major Domestic Module) before 0662e5e allows command execution via thumb.php shell metacharacters. NOTE: this is unrelated to the Majordomo mailing-list manager.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-77 \u2014 Improper Neutralization of Special Elements used in a Command ('Command Injection')
The product constructs all or part of a command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended command when it is sent to a downstream component.
Repository: https://github.com/sergejey/majordomo
Files changed:
modules/thumb/thumb.php
Commit message: Update thumb.php


Vulnerable code:
//$img=($_REQUEST['img']);
//$img=urldecode($_REQUEST['img']);
if (IsSet($url) && $url != '') {
        $cmd = 'fswebcam -r ' . $resolution . ' ' . $img_tmp;
        if ($_GET['debug']) {
if ($_GET['debug']) {
if (IsSet($url) && $url != '') {
    if (preg_match('/^rtsp:/is', $url) || preg_match('/\/dev/',$url)) {
        $stream_options = '-timelimit 15 -y -i "' . $url . '"' . $resize . ' -r 5 -f image2 -vframes 1'; //-ss 00:00:01.500
        if ($_GET['debug']) {
            $stream_options = '-v verbose ' . $stream_options;
        if ($_GET['transport']) {
            $stream_options = '-rtsp_transport ' . $_GET['transport'] . ' ' . $stream_options;
        $cmd = PATH_TO_FFMPEG . ' ' . $stream_options . ' ' . $img;
            if ($_GET['debug']) {
            $url = preg_replace('/\/\/(.+?)@/','//',$url);

                $counter=0;
//$img=str_replace('\\\\', '\\', $img);

//echo $img;exit;

$type = (IsSet($_REQUEST['t']) ? $_REQUEST['t'] : 0);
//$img='./../../'.$img;


    $new_width = (int)$_REQUEST['w'];
    $new_height = (int)$_REQUEST['h'];
        //$cache = _I_CACHE_PATH.md5($img.filemtime($img).$image_width.$image_height).".pic";
            //  $resc=GetImageSize($cache);
            //  list($w_o,$h_o,$t_o) = $resc;
            //  if ($w_o == $image_width && $h_o == $image_height && $t_o == $image_format)
            //  {
            //   }

    // Remove old cached images
    /*
    if ($handle = opendir(_I_CACHE_PATH)) {
       while (false !== ($file = readdir($handle))) {
           if ($file != "." && $file != ".." && time() - filemtime(_I_CACHE_PATH.$file) > _I_CACHE_EXPIRED)
             @unlink(_I_CACHE_PATH.$file);
       }
       closedir($handle);
    }
    */
    //

    //   endof check
//   Header("Content-Type:image/gif");
//   readfile($filename);
//   exit;
// echo("$image_width x $image_height");
    /*imageCopyResized*/
        //if (!file_exists(_I_CACHE_PATH)) {
        // @mkdir(_I_CACHE_PATH, 0777);
        //}

        //@chmod($cache, '0666');
    //   Endof save


Fixed code:
$url = gr('url');
$img = gr('img');
$username = gr('username');
$password = gr('password');
$transport = gr('transport');
$w = gr('w', 'int');
$h = gr('h', 'int');
$live = gr('live', 'int');
$debug_mode = gr('debug', 'int');

if (isset($url) && $url != '') {
        $cmd = 'fswebcam -r ' . escapeshellarg($resolution) . ' ' . escapeshellarg($img_tmp);
        if ($debug_mode) {
if ($debug_mode) {
if (isset($url) && $url != '') {
    if (preg_match('/^rtsp:/is', $url) || preg_match('/\/dev/', $url)) {
        $stream_options = '-timelimit 15 -y -i ' . escapeshellarg($url) . ($resize) . ' -r 5 -f image2 -vframes 1'; //-ss 00:00:01.500
        if ($debug_mode) {
            $stream_options = '-v verbose ' . escapeshellarg($stream_options);
        if ($transport) {
            $stream_options = '-rtsp_transport ' . escapeshellarg($transport) . ' ' . escapeshellarg($stream_options);
        $cmd = PATH_TO_FFMPEG . ' ' . $stream_options . ' ' . escapeshellarg($img);
            if ($debug_mode) {
            $url = preg_replace('/\/\/(.+?)@/', '//', $url);
                $counter = 0;
$type = gr('t', 'int');
    $new_width = $w;
    $new_height = $h;