mirror of
https://github.com/fusionpbx/fusionpbx.git
synced 2025-12-30 00:53:50 +00:00
Fix security vulnerability when using openai
- Security update required for those using text-to-speech with openai - Improved overall sanitization of the filename - Remove more characters with str_replace and - Use an array to define the characters to remove with str_replace. - Add | and ` to the str_replace - Added escapeshellarg for additional protection
This commit is contained in:
@@ -17,7 +17,7 @@
|
||||
|
||||
The Initial Developer of the Original Code is
|
||||
Mark J Crane <markjcrane@fusionpbx.com>
|
||||
Portions created by the Initial Developer are Copyright (C) 2008-2024
|
||||
Portions created by the Initial Developer are Copyright (C) 2008-2025
|
||||
the Initial Developer. All Rights Reserved.
|
||||
|
||||
Contributor(s):
|
||||
@@ -99,20 +99,25 @@
|
||||
$recording_voice = $_POST["recording_voice"];
|
||||
$recording_message = $_POST["recording_message"];
|
||||
$recording_description = $_POST["recording_description"];
|
||||
//sanitize recording filename and name
|
||||
|
||||
//sanitize: recording_filename
|
||||
if (!empty($recording_filename)) {
|
||||
$recording_filename_ext = strtolower(pathinfo($recording_filename, PATHINFO_EXTENSION));
|
||||
if (!in_array($recording_filename_ext, ['wav','mp3','ogg'])) {
|
||||
$recording_filename = pathinfo($recording_filename, PATHINFO_FILENAME);
|
||||
$recording_filename = str_replace('.', '', $recording_filename);
|
||||
}
|
||||
$recording_filename = str_replace("\\", '', $recording_filename);
|
||||
$recording_filename = str_replace('/', '', $recording_filename);
|
||||
$recording_filename = str_replace('..', '', $recording_filename);
|
||||
$replace = ['\\', '|', '/', '..', "`", "'"];
|
||||
$recording_filename = str_replace($replace, '', $recording_filename);
|
||||
$recording_filename = str_replace(' ', '-', $recording_filename);
|
||||
$recording_filename = str_replace("'", '', $recording_filename);
|
||||
}
|
||||
$recording_name = str_replace("'", '', $recording_name);
|
||||
|
||||
//sanitize: recording_filename_original
|
||||
if (!empty($recording_filename_original)) {
|
||||
$replace = ['\\', '|', '/', '..', "`", "'"];
|
||||
$recording_filename_original = str_replace($replace, '', $recording_filename_original);
|
||||
$recording_filename_original = str_replace(' ', '-', $recording_filename_original);
|
||||
}
|
||||
}
|
||||
|
||||
//process the HTTP POST
|
||||
@@ -179,22 +184,14 @@
|
||||
//set the recording format
|
||||
$recording_format = $recording_format ?? 'wav';
|
||||
|
||||
//if file name is not the same then rename the file
|
||||
if (!empty($recording_filename) && !empty($recording_filename_original) && $recording_filename != $recording_filename_original) {
|
||||
rename($_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename_original, $_SESSION['switch']['recordings']['dir'].'/'.$_SESSION['domain_name'].'/'.$recording_filename);
|
||||
}
|
||||
|
||||
//build the setting object and get the recording path
|
||||
$recording_path = $settings->get('switch', 'recordings').'/'.$_SESSION['domain_name'];
|
||||
|
||||
//create the file name
|
||||
if (empty($recording_filename)) {
|
||||
$recording_filename = $recording_name.'.'.$recording_format;
|
||||
$recording_filename = str_replace("\\", '', $recording_filename);
|
||||
$recording_filename = str_replace('/', '', $recording_filename);
|
||||
$recording_filename = str_replace('..', '', $recording_filename);
|
||||
$recording_filename = str_replace(' ', '-', $recording_filename);
|
||||
$recording_filename = str_replace("'", '', $recording_filename);
|
||||
//if file name is not the same then rename the file
|
||||
if (!empty($recording_filename) && !empty($recording_filename_original)
|
||||
&& file_exists($recording_path.'/'.$recording_filename_original)
|
||||
&& $recording_filename != $recording_filename_original) {
|
||||
rename($recording_path.'/'.$recording_filename_original, $recording_path.'/'.$recording_filename);
|
||||
}
|
||||
|
||||
//determine whether to create the recording
|
||||
@@ -223,9 +220,11 @@
|
||||
//fix invalid riff & data header lengths in generated wave file
|
||||
if ($speech_engine == 'openai') {
|
||||
$recording_filename_temp = str_replace('.'.$recording_format, '.tmp.'.$recording_format, $recording_filename);
|
||||
exec('sox --ignore-length '.$recording_path.'/'.$recording_filename.' '.$recording_path.'/'.$recording_filename_temp);
|
||||
if (file_exists($recording_path.'/'.$recording_filename)) {
|
||||
exec('sox --ignore-length '.escapeshellarg($recording_path.'/'.$recording_filename).' '.escapeshellarg($recording_path.'/'.$recording_filename_temp));
|
||||
}
|
||||
if (file_exists($recording_path.'/'.$recording_filename_temp)) {
|
||||
exec('rm -f '.$recording_path.'/'.$recording_filename.' && mv '.$recording_path.'/'.$recording_filename_temp.' '.$recording_path.'/'.$recording_filename);
|
||||
exec('rm -f '.escapeshellarg($recording_path.'/'.$recording_filename).' && mv '.escapeshellarg($recording_path.'/'.$recording_filename_temp).' '.escapeshellarg($recording_path.'/'.$recording_filename));
|
||||
}
|
||||
unset($recording_filename_temp);
|
||||
}
|
||||
@@ -243,6 +242,10 @@
|
||||
$array['recordings'][0]['recording_uuid'] = $recording_uuid;
|
||||
$array['recordings'][0]['recording_filename'] = $recording_filename;
|
||||
$array['recordings'][0]['recording_name'] = $recording_name;
|
||||
if ($settings->get('recordings', 'storage_type', '') == 'base64'
|
||||
&& file_exists($recording_path.'/'.$recording_filename)) {
|
||||
$array['recordings'][0]['recording_base64'] = base64_encode(file_get_contents($recording_path.'/'.$recording_filename));
|
||||
}
|
||||
if ($speech_enabled || $transcribe_enabled) {
|
||||
$array['recordings'][0]['recording_voice'] = $recording_voice;
|
||||
$array['recordings'][0]['recording_message'] = $recording_message;
|
||||
@@ -300,11 +303,11 @@
|
||||
echo "<div class='action_bar' id='action_bar'>\n";
|
||||
echo " <div class='heading'><b>".$text['title-edit']."</b></div>\n";
|
||||
echo " <div class='actions'>\n";
|
||||
echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$_SESSION['theme']['button_icon_back'],'id'=>'btn_back','style'=>'margin-right: 15px;','link'=>'recordings.php']);
|
||||
echo button::create(['type'=>'button','label'=>$text['button-back'],'icon'=>$settings->get('theme', 'button_icon_back'),'id'=>'btn_back','style'=>'margin-right: 15px;','link'=>'recordings.php']);
|
||||
if (permission_exists('recording_delete') && !empty($recording_uuid) && is_uuid($recording_uuid)) {
|
||||
echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$_SESSION['theme']['button_icon_delete'],'name'=>'btn_delete','style'=>'margin-right: 15px;','onclick'=>"modal_open('modal-delete','btn_delete');"]);
|
||||
echo button::create(['type'=>'button','label'=>$text['button-delete'],'icon'=>$settings->get('theme', 'button_icon_delete'),'name'=>'btn_delete','style'=>'margin-right: 15px;','onclick'=>"modal_open('modal-delete','btn_delete');"]);
|
||||
}
|
||||
echo button::create(['type'=>'submit','label'=>$text['button-save'],'icon'=>$_SESSION['theme']['button_icon_save'],'id'=>'btn_save']);
|
||||
echo button::create(['type'=>'submit','label'=>$text['button-save'],'icon'=>$settings->get('theme', 'button_icon_save'),'id'=>'btn_save']);
|
||||
echo " </div>\n";
|
||||
echo " <div style='clear: both;'></div>\n";
|
||||
echo "</div>\n";
|
||||
@@ -440,7 +443,7 @@
|
||||
echo " ".$text['label-message']."\n";
|
||||
echo "</td>\n";
|
||||
echo "<td class='vtable' align='left'>\n";
|
||||
echo " <textarea class='formfld' name='recording_message' style='width: 300px; height: 150px;'>".htmlspecialchars($recording_message, ENT_QUOTES, 'UTF-8')."</textarea>\n";
|
||||
echo " <textarea class='formfld' name='recording_message' style='width: 300px; height: 150px;'>".escape_textarea($recording_message)."</textarea>\n";
|
||||
echo "<br />\n";
|
||||
echo $text['description-message']."\n";
|
||||
echo "</td>\n";
|
||||
|
||||
Reference in New Issue
Block a user