The attacker can change the content of configuration file and constructing the dbprefix parameter to replace the TABLES_PREFIX of the configuration file with malicious code. So attacker can run malicious code remotely.
// parse all variables in the above array and fill in whatever is sent via POST
foreach ($post_vars as $var=>$value) {
if (isset($_POST[$var])) {
$post_vars[$var] = trim(stripslashes((string) $_POST[$var]));
}
}
// only mysql driver is available, let's force it
if ($pdo_mysql_available && !$pdo_mssql_available) {
$post_vars['dbdriver'] = 'mysql';
}
// only mysql driver is available, let's force it
if (!$pdo_mysql_available && $pdo_mssql_available) {
$post_vars['dbdriver'] = 'mssql';
}
/**
Check host connection
This function can take a few seconds to respond
*/
if ($pdo_driver_available) {
$dsn = $post_vars['dbdriver'] . ':host=' . $post_vars['dbhost'] . ';dbname=' . $post_vars['dbname'];
try{
$db = new PDO($dsn, $post_vars['dbuser'], $post_vars['dbpassword'], array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION));
$pdo_connected = true;
}
catch(PDOException $ex){
$pdo_connected = false;
}
}
Thanks for your report!
I've just added commit b275af8 which I hope fixes this problem. I've had no problems on my tests.
Can you please try again and let me know if it's fixed for you?
USE CVE-2017-9741
The attacker can change the content of configuration file and constructing the dbprefix parameter to replace the TABLES_PREFIX of the configuration file with malicious code. So attacker can run malicious code remotely.
code: $postvars = array( 'dbdriver' => 'mysql', 'dbname' => 'projectsend', 'dbuser' => 'root', 'dbpassword' => 'root', 'dbhost' => 'localhost', 'dbprefix' => 'tbl', 'dbreuse' => 'no', 'lang' => 'en' );
// parse all variables in the above array and fill in whatever is sent via POST foreach ($post_vars as $var=>$value) { if (isset($_POST[$var])) { $post_vars[$var] = trim(stripslashes((string) $_POST[$var])); } }
//check PDO status $pdo_available_drivers = PDO::getAvailableDrivers(); $pdo_mysql_available = in_array('mysql', $pdo_available_drivers); $pdo_mssql_available = in_array('dblib', $pdo_available_drivers); $pdo_driver_available = $pdo_mysql_available || $pdo_mssql_available;
// only mysql driver is available, let's force it if ($pdo_mysql_available && !$pdo_mssql_available) { $post_vars['dbdriver'] = 'mysql'; }
// only mysql driver is available, let's force it if (!$pdo_mysql_available && $pdo_mssql_available) { $post_vars['dbdriver'] = 'mssql'; }
/**
// names of reserved tables $table_names = array( 'actions_log', 'categories', 'categories_relations', 'downloads', 'files', 'files_relations', 'folders', 'groups', 'members', 'notifications', 'options', 'password_reset', 'users', );
// check if tables exists $table_exists = false; if ($pdo_connected) { foreach ($table_names as $name) { $table_exists = $table_exists || table_exists($db, $post_vars['dbprefix'].$name); } } $reuse_tables = $post_vars['dbreuse'] == 'reuse';
// scan for language files $langs = get_available_languages();
// ok if selected language has a .po file associated $lang_ok = array_key_exists($post_vars['lang'], $langs);
// check file & folders are writable $config_file = ROOT_DIR.'/includes/sys.config.php'; $config_file_writable = is_writable($config_file) || is_writable(dirname($config_file)); $upload_dir = ROOT_DIR.'/upload'; $upload_files_dir = ROOT_DIR.'/upload/files'; $upload_files_dir_writable = is_writable($upload_files_dir) || is_writable($upload_dir); $upload_temp_dir = ROOT_DIR.'/upload/temp'; $upload_temp_dir_writable = is_writable($upload_temp_dir) || is_writable($upload_dir);
// retrieve user data for web server if (function_exists('posix_getpwuid')) { $server_user_data = posix_getpwuid(posix_getuid()); $server_user = $server_user_data['name'] . ' (uid=' . $server_user_data['uid'] . ' gid=' . $server_user_data['gid'] . ')'; } else { $server_user = getenv('USERNAME'); }
// if everything is ok, we can proceed $ready_to_go = $pdo_connected && (!$table_exists || $reuse_tables) && $lang_ok && $config_file_writable && $upload_files_dir_writable && $upload_temp_dir_writable;
// if the user requested to write the config file AND we can proceed, we try to write the new configuration if (isset($_POST['submit-start']) && $ready_to_go) { $template = file_get_contents(ROOT_DIR . '/includes/sys.config.sample.php'); $templatesearch = array( "'mysql'", "'database'", "'localhost'", "'username'", "'password'", "'tbl'", "'en'" ); $template_replace = array( "'" . $post_vars['dbdriver'] . "'", "'" . $post_vars['dbname'] . "'", "'" . $post_vars['dbhost'] . "'", "'" . $post_vars['dbuser'] . "'", "'" . $post_vars['dbpassword'] . "'", "'" . $post_vars['dbprefix'] . "'", "'" . $post_vars['lang'] . "'", ); $template = str_replace( $template_search, $template_replace, $template );