CVE-2023-0048 (PHP, published 2023-01-04T14:15Z)
Description: value: Code Injection in GitHub repository lirantal/daloradius prior to master-branch.
Severity: nan (CVSS v3 base score: 8.8)
Weakness: CWE-94 \u2014 Improper Control of Generation of Code ('Code Injection')
The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
Repository: https://github.com/lirantal/daloradius
Files changed:
config-backup-managebackups.php
config-logging.php
config-mail.php
css/2.css
library/config_read.php
library/config_write.php
library/validation.php
Commit message: Validating/sanitizing user input (#327)

* Better validating log filepath

* improving configuration read/write function

* SMTP configuration parameter validation

* Input validation/sanitization fixes

* minor fix

Vulnerable code:
    $file = (array_key_exists('file', $_POST) && isset($_POST['file'])) ? $_POST['file'] : "";
    $filePath = $configValues['CONFIG_PATH_DALO_VARIABLE_DATA'] . "/backup";
    $fileName = sprintf("%s/%s", $filePath, $file);
            if (!empty($file) && !empty($backupAction) && is_dir($filePath) && is_readable($fileName)) {
    if (is_dir($filePath)) {
        $files = scandir($filePath);
        foreach ($files as $file) {
            if (in_array($file, $skipList)) {
            list($junk, $date, $time) = explode("-", $file);
            $fileSize = filesize($filePath."/".$file);
                                    $file,
                        // this ensures that candidate_log_file does not contain ".."


    if (isset($_REQUEST['submit'])) {
        if (isset($_REQUEST['config_mail_smtpaddr']))
            $configValues['CONFIG_MAIL_SMTPADDR'] = $_REQUEST['config_mail_smtpaddr'];
        
        if (isset($_REQUEST['config_mail_smtpport']))
            $configValues['CONFIG_MAIL_SMTPPORT'] = $_REQUEST['config_mail_smtpport'];
            
        if (isset($_REQUEST['config_mail_smtp_fromemail']))
            $configValues['CONFIG_MAIL_SMTPFROM'] = $_REQUEST['config_mail_smtp_fromemail'];
        
        include ("library/config_write.php");
    }    
    include("library/layout.php");
?>

<form name="mailsettings" method="POST">
    <fieldset>
        <h302><?= t('title','Settings'); ?></h302>
        
        <br/>

        <ul>

            <li class="fieldset">
                <label for="config_mail_smtpaddr" class="form"><?= t('all','SMTPServerAddress') ?></label>
                <input type="text" value="<?= $configValues['CONFIG_MAIL_SMTPADDR'] ?>" name="config_mail_smtpaddr">
            </li>
            <li class="fieldset">
                <label for="config_mail_smtpport" class="form"><?= t('all','SMTPServerPort') ?></label>
                <input type="number" min="0" max="65535" value="<?= $configValues['CONFIG_MAIL_SMTPPORT'] ?>" name="config_mail_smtpport">
            </li>

            <li class="fieldset">
                <label for="config_mail_smtp_fromemail" class="form"><?= t('all','SMTPServerFromEmail') ?></label>
                <input type="text" value="<?= $configValues['CONFIG_MAIL_SMTPFROM'] ?>" name="config_mail_smtp_fromemail">
            </li>


            <li class="fieldset">
                <br/><hr><br/>
                <input type="submit" name="submit" value="<?= t('buttons','apply') ?>" class="button">
            </li>
        </ul>
    </fieldset>
</form>

        </div><!-- #contentnorightbar -->
        
        <div id="footer">
<?php
    include('page-footer.php');
?>
        </div><!-- #footer -->
    </div>
</div>
</body>
</html>
fieldset select {
fieldset select:disabled {
 * Description:
 * 		reads configuration file from daloradius.conf and appends it to the $configValues associated array
 * Authors:	Liran Tal <liran@enginx.com>
 
$_configFile = dirname(__FILE__).'/daloradius.conf.php';
include($_configFile);
/*
****************************************************************************************************
* deprecated for handling the configuration variables as a PHP page for the sake of security
****************************************************************************************************
$_configCommentChar = "#";
$_configFp = fopen($_configFile, "r");
if ($_configFp) {
	while (!feof($_configFp)) {
		$_configLine = trim(fgets($_configFp));
		if ($_configLine && !ereg("^$_configCommentChar", $_configLine)) {
			$_configPieces = explode("=", $_configLine);
			$_configOption = trim($_configPieces[0]);
			$_configValue = trim($_configPieces[1]);
			$configValues[$_configOption] = $_configValue;
		}
	}
	fclose($_configFp);
} else {
	$failureMsg = "Could not open the file for reading:<b> $_configFile </b>
	<br/>Check file permissions. The file should be readable by the webserver's user/group";
****************************************************************************************************
*/
 * Description:
 * 		writes configuration information from the $configValues array to daloradius.conf
 * Authors:	Liran Tal <liran@enginx.com>
$configFile = dirname(__FILE__).'/daloradius.conf.php';
$fp = fopen($configFile, "w");
if ($fp) {
	fwrite($fp, 
		"<?php\n".
		"/*\n".
		" *********************************************************************************************************\n".
		" * daloRADIUS - RADIUS Web Platform\n".
		" * Copyright (C) 2007 - Liran Tal <liran@enginx.com> All Rights Reserved.\n".
		" *\n".
		" * This program is free software; you can redistribute it and/or\n".
		" * modify it under the terms of the GNU General Public License\n".
		" * as published by the Free Software Foundation; either version 2\n".
		" * of the License, or (at your option) any later version.\n".
		" *\n".
		" * You should have received a copy of the GNU General Public License\n".
		" * along with this program; if not, write to the Free Software\n".
		" * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.\n".
		" *\n".
		" *********************************************************************************************************\n".
		" * Description:\n".
		" *              daloRADIUS Configuration File\n".
		" *\n".
		" * Modification Date:\n".
		" *              $date\n".
		" *********************************************************************************************************\n".
		" */\n".
		"\n\n");
	foreach ($configValues as $_configOption => $_configElem) {
		if (is_array($configValues[$_configOption])) {
			$var = "\$configValues['" . $_configOption . "'] = \t\t";
			$var .= var_export($configValues[$_configOption], true);
			$var .= ";\n";
			fwrite($fp, $var);
		} else
	        fwrite($fp, "\$configValues['" . $_configOption . "'] = '" . $configValues[$_configOption] . "';\n");
	}
	fwrite($fp, "\n\n?>");
	fclose($fp);
	$successMsg = "Updated database settings for configuration file";
} else {
	$failureMsg = "Could not open the file for writing: <b>$configFile</b>
	<br/>Check file permissions. The file should be writable by the webserver's user/group";

Fixed code:
    // validate path
    $backup_path_prefix = $configValues['CONFIG_PATH_DALO_VARIABLE_DATA'] . "/backup";
    $backup_file_suffix = ".sql";

    $file = "";
    if (array_key_exists('file', $_POST) && !empty(trim($_POST['file']))) {
        $candidate_backup_file = trim($_POST['file']);
        
        if (
                // this ensures that candidate_backup_file does not contain any ".." sequence
                strpos($candidate_backup_file, "..") === false &&
                
                // this ensures that candidate_backup_file does not contain any "/" char
                strpos($candidate_backup_file, "/") === false &&
                
                // this ensures that candidate_backup_file ends with the backup_file_suffix
                substr($candidate_backup_file, -strlen($backup_file_suffix)) === $backup_file_suffix
           ) {
            
            $file = $candidate_backup_file;
        }
        
    }
    $fileName = sprintf("%s/%s", $backup_path_prefix, $file);
            if (!empty($file) && !empty($backupAction) && is_dir($backup_path_prefix) && is_readable($fileName)) {
            } else {
                $failureMsg = sprintf("The requested action cannot be performed");
                $logAction .= "$failureMsg on page: ";
    if (is_dir($backup_path_prefix)) {
        $files = scandir($backup_path_prefix);
        foreach ($files as $this_file) {
            if (in_array($this_file, $skipList)) {
            list($junk, $date, $time) = explode("-", $this_file);
            $fileSize = filesize(sprintf("%s/%s", $backup_path_prefix, $this_file));
                                    $this_file,
                        // this ensures that candidate_backup_file does not contain any ".." sequence
    
    // init logging variables
    $logAction = "";
    $logDebugSQL = "";
    
    include("library/validation.php");
    include("library/layout.php");
    $param_label = array(
                            'CONFIG_MAIL_SMTPADDR' => t('all','SMTPServerAddress'),
                            'CONFIG_MAIL_SMTPPORT' => t('all','SMTPServerPort'),
                            'CONFIG_MAIL_SMTPFROM' => t('all','SMTPServerFromEmail'),
                        );
    $invalid_input = array();
    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (array_key_exists('csrf_token', $_POST) && isset($_POST['csrf_token']) && dalo_check_csrf_token($_POST['csrf_token'])) {
            
            // validate email
            if (
                    array_key_exists('CONFIG_MAIL_SMTPFROM', $_POST) &&
                    !empty(trim($_POST['CONFIG_MAIL_SMTPFROM'])) &&
                    filter_var(trim($_POST['CONFIG_MAIL_SMTPFROM']), FILTER_VALIDATE_EMAIL)
               ) {
                $configValues['CONFIG_MAIL_SMTPFROM'] = trim($_POST['CONFIG_MAIL_SMTPFROM']);
            } else {
                $invalid_input['CONFIG_MAIL_SMTPFROM'] = $param_label['CONFIG_MAIL_SMTPFROM'];
            }
            
            // validate port
            if (
                    array_key_exists('CONFIG_MAIL_SMTPPORT', $_POST) &&
                    !empty(trim($_POST['CONFIG_MAIL_SMTPPORT'])) &&
                    intval(trim($_POST['CONFIG_MAIL_SMTPPORT'])) >= 0 &&
                    intval(trim($_POST['CONFIG_MAIL_SMTPPORT'])) <= 65535
               ) {
                $configValues['CONFIG_MAIL_SMTPPORT'] = intval(trim($_POST['CONFIG_MAIL_SMTPPORT']));
            } else {
                $invalid_input['CONFIG_MAIL_SMTPPORT'] = $param_label['CONFIG_MAIL_SMTPPORT'];
            }
            
            // validate ip address/hostname
            if (
                    array_key_exists('CONFIG_MAIL_SMTPADDR', $_POST) &&
                    !empty(trim($_POST['CONFIG_MAIL_SMTPADDR'])) &&
                    (
                        preg_match(HOSTNAME_REGEX, trim($_POST['CONFIG_MAIL_SMTPADDR'])) ||
                        preg_match(IP_REGEX, trim($_POST['CONFIG_MAIL_SMTPADDR']))
                    )
               ) {
                $configValues['CONFIG_MAIL_SMTPADDR'] = trim($_POST['CONFIG_MAIL_SMTPADDR']);
            } else {
                $invalid_input['CONFIG_MAIL_SMTPADDR'] = $param_label['CONFIG_MAIL_SMTPADDR'];
            }
            
            if (count($invalid_input) > 0) {
                $failureMsg = sprintf("Invalid input: [%s]", implode(", ", array_values($invalid_input)));
                $logAction .= "$failureMsg on page: ";
            } else {
                include("library/config_write.php");
            }
            
        } else {
            // csrf
            $failureMsg = "CSRF token error";
            $logAction .= "$failureMsg on page: ";
        }
    }
    
    $fieldset0_descriptor = array(
                                    "title" => t('title','Settings')
                                 );
    $input_descriptors0 = array();
    
    
    $input_descriptors0[] = array(
                                        "type" => "text",
                                        "caption" => t('all','SMTPServerAddress'),
                                        "name" => 'CONFIG_MAIL_SMTPADDR',
                                        "value" => (!array_key_exists('CONFIG_MAIL_SMTPADDR', $invalid_input)
                                                    ? $configValues['CONFIG_MAIL_SMTPADDR'] : "")
                                     );
    
    $input_descriptors0[] = array(
                                        "type" => "number",
                                        "caption" => t('all','SMTPServerPort'),
                                        "name" => 'CONFIG_MAIL_SMTPPORT',
                                        "value" => (!array_key_exists('CONFIG_MAIL_SMTPPORT', $invalid_input)
                                                    ? $configValues['CONFIG_MAIL_SMTPPORT'] : ""),
                                        "min" => 0,
                                        "max" => 65535
                                 );
    
    $input_descriptors0[] = array(
                                        "type" => "email",
                                        "caption" => t('all','SMTPServerFromEmail'),
                                        "name" => 'CONFIG_MAIL_SMTPFROM',
                                        "value" => (!array_key_exists('CONFIG_MAIL_SMTPFROM', $invalid_input)
                                                    ? $configValues['CONFIG_MAIL_SMTPFROM'] : ""),
                                     );
    
    $input_descriptors0[] = array(
                                    "name" => "csrf_token",
                                    "type" => "hidden",
                                    "value" => dalo_csrf_token(),
                                 );

    $input_descriptors0[] = array(
                                    'type' => 'submit',
                                    'name' => 'submit',
                                    'value' => t('buttons','apply')
                                 );

    open_form();
    
    // open 0-th fieldset
    open_fieldset($fieldset0_descriptor);
    
    foreach ($input_descriptors0 as $input_descriptor) {
        print_form_component($input_descriptor);
    }
    
    close_fieldset();
    
    close_form();
    
    
    print_footer_and_html_epilogue();
?>
fieldset input[type=email], fieldset select {
fieldset input[type=email]:disabled, fieldset select:disabled {
 * Description:    reads configuration file from daloradius.conf.php and
 *                 loads its contents to the $configValues associated array
 *
 * Authors:        Liran Tal <liran@enginx.com>
 *                 Filippo Lauria <filippo.lauria@iit.cnr.it>
// prevent this file to be directly accessed
if (strpos($_SERVER['PHP_SELF'], '/library/config_read.php') !== false) {
    header("Location: ../index.php");
    exit;
}

$_configFile = dirname(__FILE__) . '/daloradius.conf.php';
include($_configFile);
// strip slashes (if any)
foreach ($configValues as $_configOption => $_configElem) {
    if (is_array($_configElem)) {
        continue;
    }
    
    $configValues[$_configOption] = stripslashes($_configElem);
 * Description:    writes configuration information from the $configValues array
 *                 to the daloradius.conf.php configuration file
 * 
 * Authors:        Liran Tal <liran@enginx.com>
 *                 Filippo Lauria <filippo.lauria@iit.cnr.it>
// prevent this file to be directly accessed
if (strpos($_SERVER['PHP_SELF'], '/library/config_write.php') !== false) {
    header("Location: ../index.php");
    exit;
}

// useful variables
$configFile = dirname(__FILE__) . '/daloradius.conf.php';
//
// generating file contents
//

// 1. open
$fileContents = <<<EOL
<?php
/*
 *********************************************************************************************************
 * daloRADIUS - RADIUS Web Platform
 * Copyright (C) 2007 - Liran Tal <liran@enginx.com> All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 *********************************************************************************************************
 * 
 * Description:          daloRADIUS Configuration File
 *
 * Modification Date:    {$date}
 *
 *********************************************************************************************************
 */

// prevent this file to be directly accessed
if (strpos(\$_SERVER['PHP_SELF'], '/library/daloradius.conf.php') !== false) {
    header("Location: ../index.php");
    exit;
}


EOL;

// 2. body
foreach ($configValues as $_configOption => $_configElem) {
    $fileContents .= sprintf("\$configValues['%s'] =", $_configOption);
    
    if (is_array($configValues[$_configOption])) {
        $fileContents .= str_repeat(" ", 8) . sprintf("%s;\n", var_export($configValues[$_configOption], true));
    } else {
        $fileContents .= sprintf(" '%s';\n", addslashes($configValues[$_configOption]));
    }
// 3. close
$fileContents .= <<<EOL

?>

EOL;

//
// putting contents into file
//
$writtenBytes = intval(file_put_contents($configFile, $fileContents));

if ($writtenBytes > 0) {
    $successMsg = "Configuration file has been successfully updated";
} else {
    $failureMsg = sprintf("Could not open the file for writing: <strong>%s</strong>", $configFile)
                . "<br>Check file permissions. The file should be writable by the webserver's user/group";
} 

define("HOSTNAME_REGEX", '/^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/');