From 60b0f3666d84614320d24b85b179cad5cf891488 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Mon, 29 Jun 2020 02:54:16 +0100 Subject: [PATCH 01/10] begin work on csrf fixes --- interface/main/main_screen.php | 3 +++ interface/patient_file/letter.php | 9 +++++++++ library/sanitize.inc.php | 29 +++++++++++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/interface/main/main_screen.php b/interface/main/main_screen.php index e2639250d..e27f5dbba 100644 --- a/interface/main/main_screen.php +++ b/interface/main/main_screen.php @@ -41,6 +41,9 @@ session_regenerate_id(false); } +//generate csrf token +$_SESSION['token'] = generateCsrfToken(); + $_SESSION["encounter"] = ''; // Fetch the password expiration date diff --git a/interface/patient_file/letter.php b/interface/patient_file/letter.php index f3c4cd232..c009a0534 100644 --- a/interface/patient_file/letter.php +++ b/interface/patient_file/letter.php @@ -90,6 +90,14 @@ $alertmsg = ''; // anything here pops up in an alert box +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A Post detected with not csrf token found'); + die('Authentication failed.'); + } else if (!hash_equals(hash_hmac('sha256', '/letter.php.theform', $_SESSION['token']), $_POST['token'])) { + die('Authentication failed.'); + } +} // If the Generate button was clicked... if ($_POST['formaction']=="generate") { @@ -430,6 +438,7 @@ function insertAtCursor(myField, myValue) {
+

diff --git a/library/sanitize.inc.php b/library/sanitize.inc.php index f61283315..c60f84397 100644 --- a/library/sanitize.inc.php +++ b/library/sanitize.inc.php @@ -55,5 +55,34 @@ function image_has_right_size($size) { return $size < 20971520; } +// Generate csrf token for authentication +function generateCsrfToken() +{ + if (!extension_loaded('openssl')) { + error_log("ERROR: openssl extension not enabled, needed for proper functioning of LibreHealth"); + die("Error: Systems needs openssl."); + } + + $csrfToken = bin2hex(openssl_random_pseudo_bytes(32)); + + if (empty($csrfToken)) { + error_log("ERROR : Token generation failed"); + die("Error : Unable to correctly generate token"); + } + + return $csrfToken; +} + +// Function to verify a csrf token +function verifyCsrfToken($token) +{ + if (hash_equals($_SESSION['token'], $token)) { + return true; + } else { + error_log("WARNING : Malicious attempt encountered"); + return false; + } +} + ?> From 763382559cfd80f8389b5e83499f02abeedc0357 Mon Sep 17 00:00:00 2001 From: Maggie Negm Date: Thu, 2 Jul 2020 19:06:22 -0400 Subject: [PATCH 02/10] Created CsrfToken class --- interface/main/main_screen.php | 3 ++- interface/patient_file/letter.php | 2 +- library/CsrfToken.php | 35 +++++++++++++++++++++++++++++++ library/sanitize.inc.php | 30 -------------------------- 4 files changed, 38 insertions(+), 32 deletions(-) create mode 100644 library/CsrfToken.php diff --git a/interface/main/main_screen.php b/interface/main/main_screen.php index e27f5dbba..c91262a29 100644 --- a/interface/main/main_screen.php +++ b/interface/main/main_screen.php @@ -24,6 +24,7 @@ /* Include our required headers */ require_once('../globals.php'); require_once("$srcdir/formdata.inc.php"); +require_once("../../library/CsrfToken.php"); // Creates a new session id when load this outer frame // (allows creations of separate LibreHealth EHR frames to view patients concurrently @@ -42,7 +43,7 @@ } //generate csrf token -$_SESSION['token'] = generateCsrfToken(); +$_SESSION['token'] = CsrfToken::generateCsrfToken(); $_SESSION["encounter"] = ''; diff --git a/interface/patient_file/letter.php b/interface/patient_file/letter.php index c009a0534..b88ca03c9 100644 --- a/interface/patient_file/letter.php +++ b/interface/patient_file/letter.php @@ -92,7 +92,7 @@ if (!empty($_POST)) { if (!isset($_POST['token'])) { - error_log('WARNING: A Post detected with not csrf token found'); + error_log('WARNING: A POST request detected with no csrf token found'); die('Authentication failed.'); } else if (!hash_equals(hash_hmac('sha256', '/letter.php.theform', $_SESSION['token']), $_POST['token'])) { die('Authentication failed.'); diff --git a/library/CsrfToken.php b/library/CsrfToken.php new file mode 100644 index 000000000..d616d3e2a --- /dev/null +++ b/library/CsrfToken.php @@ -0,0 +1,35 @@ + \ No newline at end of file diff --git a/library/sanitize.inc.php b/library/sanitize.inc.php index c60f84397..c63981780 100644 --- a/library/sanitize.inc.php +++ b/library/sanitize.inc.php @@ -55,34 +55,4 @@ function image_has_right_size($size) { return $size < 20971520; } -// Generate csrf token for authentication -function generateCsrfToken() -{ - if (!extension_loaded('openssl')) { - error_log("ERROR: openssl extension not enabled, needed for proper functioning of LibreHealth"); - die("Error: Systems needs openssl."); - } - - $csrfToken = bin2hex(openssl_random_pseudo_bytes(32)); - - if (empty($csrfToken)) { - error_log("ERROR : Token generation failed"); - die("Error : Unable to correctly generate token"); - } - - return $csrfToken; -} - -// Function to verify a csrf token -function verifyCsrfToken($token) -{ - if (hash_equals($_SESSION['token'], $token)) { - return true; - } else { - error_log("WARNING : Malicious attempt encountered"); - return false; - } -} - - ?> From a7102ca2ed309ce14f46c99ab05ab158efa1a94d Mon Sep 17 00:00:00 2001 From: elizabeth Date: Wed, 15 Jul 2020 16:03:08 +0100 Subject: [PATCH 03/10] fix remote code execution in on history and import template modules --- interface/billing/edi_history_main.php | 9 +++++++++ interface/billing/edih_view.php | 9 +++++++++ library/CsrfToken.php | 10 ++++++++++ patient_portal/import_template.php | 9 +++++++++ patient_portal/import_template_ui.php | 3 ++- 5 files changed, 39 insertions(+), 1 deletion(-) diff --git a/interface/billing/edi_history_main.php b/interface/billing/edi_history_main.php index 1e15f4de5..434de427f 100644 --- a/interface/billing/edi_history_main.php +++ b/interface/billing/edi_history_main.php @@ -70,6 +70,7 @@ require_once("$srcdir/edihistory/ibr_ack_read.php"); //dirname(__FILE__) . "/edihist/ibr_ack_read.php"); require_once("$srcdir/edihistory/ibr_uploads.php"); //dirname(__FILE__) . "/edihist/ibr_uploads.php"); require_once("$srcdir/edihistory/ibr_io.php"); //dirname(__FILE__) . "/edihist/ibr_io.php"); +require_once("../../library/CsrfToken.php"); // // php may output line endings if include files are utf-8 ob_clean(); @@ -100,6 +101,14 @@ */ if (strtolower($_SERVER['REQUEST_METHOD']) == 'post') { + if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfToken($_POST['token'])) { + die('Authentication failed.'); + } + } // if ( isset($_POST['NewFiles']) ) { // process new files button clicked diff --git a/interface/billing/edih_view.php b/interface/billing/edih_view.php index dc76f7b7e..af5a45458 100644 --- a/interface/billing/edih_view.php +++ b/interface/billing/edih_view.php @@ -75,6 +75,7 @@ " /> + @@ -87,6 +88,7 @@ " /> + @@ -159,6 +161,7 @@ --> + " /> @@ -220,6 +223,7 @@ " /> + @@ -236,6 +240,7 @@ " /> + @@ -253,6 +258,7 @@ " /> + @@ -263,6 +269,7 @@ " /> + @@ -275,6 +282,7 @@ " /> + @@ -309,6 +317,7 @@ " /> " /> + diff --git a/library/CsrfToken.php b/library/CsrfToken.php index d616d3e2a..6210ef67a 100644 --- a/library/CsrfToken.php +++ b/library/CsrfToken.php @@ -30,6 +30,16 @@ function verifyCsrfToken($token) return false; } } + // Function to verify a csrf token using with second token + function verifyCsrfTokenAndCompareHash($secondToken) + { + if (hash_equals(hash_hmac('sha256', '/letter.php.theform', $_SESSION['token']), $_POST['token'])) { + return true; + } else { + error_log("WARNING : Malicious attempt encountered"); + return false; + } + } } ?> \ No newline at end of file diff --git a/patient_portal/import_template.php b/patient_portal/import_template.php index 8dace706c..2ade0db97 100644 --- a/patient_portal/import_template.php +++ b/patient_portal/import_template.php @@ -19,7 +19,16 @@ $sanitize_all_escapes=true; $fake_register_globals=false; require_once("../interface/globals.php"); +require_once("../library/CsrfToken.php"); +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfToken($_POST['token'])) { + die('Authentication failed.'); + } +} if($_POST['mode'] == 'get'){ echo file_get_contents($_POST['docid']); exit; diff --git a/patient_portal/import_template_ui.php b/patient_portal/import_template_ui.php index de651c248..c970b053a 100644 --- a/patient_portal/import_template_ui.php +++ b/patient_portal/import_template_ui.php @@ -120,7 +120,7 @@ function getDocument(docname, mode, content){ $.ajax({ type: "POST", url: liburl, - data: {docid: docname, mode: mode,content: content}, + data: {docid: docname, mode: mode,content: content, token: }, beforeSend: function(xhr){ console.log("Please wait..."+content); }, @@ -192,6 +192,7 @@ function getDocument(docname, mode, content){ + From c702fa1fb0b75cfbf257f6743d6cae609abbe735 Mon Sep 17 00:00:00 2001 From: Maggie Negm Date: Fri, 31 Jul 2020 23:34:58 -0400 Subject: [PATCH 04/10] Added csrf protection in vulnerable files with forms --- interface/super/edit_globals.php | 12 ++++++++++++ interface/super/edit_layout.php | 11 +++++++++++ interface/super/edit_list.php | 11 +++++++++++ interface/super/load_codes.php | 14 +++++++++++++- interface/super/manage_document_templates.php | 14 +++++++++++++- interface/super/manage_site_files.php | 13 ++++++++++++- library/CsrfToken.php | 6 +++--- 7 files changed, 75 insertions(+), 6 deletions(-) diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index 4f7b9ed37..e67942308 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -36,6 +36,7 @@ require_once("$srcdir/user.inc"); require_once("$srcdir/classes/CouchDB.class.php"); require_once("$srcdir/calendar.inc"); +require_once("../../library/CsrfToken.php"); if ($_GET['mode'] != "user") { // Check authorization. @@ -43,6 +44,15 @@ if (!$thisauth) die(xlt('Not authorized')); } +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfTokenAndCompareHash($_POST['token'], '/edit_globals.php.theform'))) { + die('Authentication failed.'); + } +} + function checkCreateCDB(){ $globalsres = sqlStatement("SELECT gl_name, gl_index, gl_value FROM globals WHERE gl_name IN ('couchdb_host','couchdb_user','couchdb_pass','couchdb_port','couchdb_dbase','document_storage_method')"); @@ -393,6 +403,8 @@ function checkBackgroundServices(){

+ +

diff --git a/interface/super/edit_layout.php b/interface/super/edit_layout.php index 7fa21de45..b648a4d5d 100644 --- a/interface/super/edit_layout.php +++ b/interface/super/edit_layout.php @@ -27,6 +27,7 @@ require_once("$srcdir/log.inc"); require_once("$srcdir/formdata.inc.php"); require_once("$srcdir/headers.inc.php"); +require_once("../../library/CsrfToken.php"); $layouts = array( 'DEM' => xl('Demographics'), @@ -137,6 +138,15 @@ function addOrDeleteColumn($layout_id, $field_id, $add=TRUE) { $thisauth = acl_check('admin', 'super'); if (!$thisauth) die(xl('Not authorized')); +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfTokenAndCompareHash($_POST['token'], '/edit_layout.php.theform'))) { + die('Authentication failed.'); + } +} + // The layout ID identifies the layout to be edited. $layout_id = empty($_REQUEST['layout_id']) ? '' : $_REQUEST['layout_id']; @@ -975,6 +985,7 @@ function cidChanged(lino, seq) { +

:  +

: 

diff --git a/interface/super/manage_document_templates.php b/interface/super/manage_document_templates.php index 0799e8bfc..fd57e89d5 100644 --- a/interface/super/manage_document_templates.php +++ b/interface/super/manage_document_templates.php @@ -29,8 +29,19 @@ require_once($GLOBALS['srcdir'].'/htmlspecialchars.inc.php'); require_once($GLOBALS['srcdir'].'/formdata.inc.php'); require_once("$srcdir/headers.inc.php"); +require_once("../../library/CsrfToken.php"); + if (!acl_check('admin', 'super')) die(htmlspecialchars(xl('Not authorized'))); +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfTokenAndCompareHash($_POST['token'], '/manage_document_templates.php.theform'))) { + die('Authentication failed.'); + } +} + $form_filename = strip_escape_custom($_REQUEST['form_filename']); $templatedir = "$OE_SITE_DIR/documents/doctemplates"; @@ -104,7 +115,8 @@ + id="theform" name="theform" onsubmit='return top.restoreSession()'> +
diff --git a/interface/super/manage_site_files.php b/interface/super/manage_site_files.php index 4e9b92db7..af7c9d9d8 100644 --- a/interface/super/manage_site_files.php +++ b/interface/super/manage_site_files.php @@ -19,9 +19,19 @@ /* for formData() */ require_once($GLOBALS['srcdir'].'/formdata.inc.php'); require_once("$srcdir/headers.inc.php"); +require_once("../../library/CsrfToken.php"); if (!acl_check('admin', 'super')) die(htmlspecialchars(xl('Not authorized'))); +if (!empty($_POST)) { + if (!isset($_POST['token'])) { + error_log('WARNING: A POST request detected with no csrf token found'); + die('Authentication failed.'); + } else if (!(CsrfToken::verifyCsrfTokenAndCompareHash($_POST['token'], '/manage_site_files.php.theform'))) { + die('Authentication failed.'); + } +} + // Prepare array of names of editable files, relative to the site directory. $my_files = array( 'config.php', @@ -143,7 +153,8 @@ function msfFileChanged() { + id="theform" name="theform" onsubmit='return top.restoreSession()'> +
diff --git a/library/CsrfToken.php b/library/CsrfToken.php index 6210ef67a..ebb886e30 100644 --- a/library/CsrfToken.php +++ b/library/CsrfToken.php @@ -1,7 +1,7 @@ Date: Sun, 2 Aug 2020 20:24:10 -0400 Subject: [PATCH 05/10] Type cast input for hash_hmac() --- interface/billing/edi_history_main.php | 2 +- interface/patient_file/letter.php | 4 ++-- interface/super/edit_globals.php | 2 +- interface/super/edit_layout.php | 2 +- interface/super/edit_list.php | 2 +- interface/super/load_codes.php | 3 +-- interface/super/manage_document_templates.php | 2 +- interface/super/manage_site_files.php | 2 +- library/CsrfToken.php | 2 +- patient_portal/import_template.php | 2 +- 10 files changed, 11 insertions(+), 12 deletions(-) diff --git a/interface/billing/edi_history_main.php b/interface/billing/edi_history_main.php index 434de427f..1195d77f3 100644 --- a/interface/billing/edi_history_main.php +++ b/interface/billing/edi_history_main.php @@ -105,7 +105,7 @@ if (!isset($_POST['token'])) { error_log('WARNING: A POST request detected with no csrf token found'); die('Authentication failed.'); - } else if (!(CsrfToken::verifyCsrfToken($_POST['token'])) { + } else if (!(CsrfToken::verifyCsrfToken($_POST['token']))) { die('Authentication failed.'); } } diff --git a/interface/patient_file/letter.php b/interface/patient_file/letter.php index b88ca03c9..15b69d50e 100644 --- a/interface/patient_file/letter.php +++ b/interface/patient_file/letter.php @@ -94,7 +94,7 @@ if (!isset($_POST['token'])) { error_log('WARNING: A POST request detected with no csrf token found'); die('Authentication failed.'); - } else if (!hash_equals(hash_hmac('sha256', '/letter.php.theform', $_SESSION['token']), $_POST['token'])) { + } else if (!(CsrfToken::verifyCsrfTokenAndCompareHash($_POST['token'], '/letter.php.theform'))) { die('Authentication failed.'); } } @@ -438,7 +438,7 @@ function insertAtCursor(myField, myValue) { - +

diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index e67942308..162eb94cb 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -403,7 +403,7 @@ function checkBackgroundServices(){ - +

diff --git a/interface/super/edit_layout.php b/interface/super/edit_layout.php index b648a4d5d..3fde42a0a 100644 --- a/interface/super/edit_layout.php +++ b/interface/super/edit_layout.php @@ -985,7 +985,7 @@ function cidChanged(lino, seq) { - +

:  - +

:  +

diff --git a/interface/super/manage_document_templates.php b/interface/super/manage_document_templates.php index fd57e89d5..207eafbcb 100644 --- a/interface/super/manage_document_templates.php +++ b/interface/super/manage_document_templates.php @@ -116,7 +116,7 @@ - +
diff --git a/interface/super/manage_site_files.php b/interface/super/manage_site_files.php index af7c9d9d8..ade47f55f 100644 --- a/interface/super/manage_site_files.php +++ b/interface/super/manage_site_files.php @@ -154,7 +154,7 @@ function msfFileChanged() { - +
diff --git a/library/CsrfToken.php b/library/CsrfToken.php index ebb886e30..9f5b2d8f4 100644 --- a/library/CsrfToken.php +++ b/library/CsrfToken.php @@ -33,7 +33,7 @@ function verifyCsrfToken($token) // Function to verify a csrf token using with second token function verifyCsrfTokenAndCompareHash($token, $secondToken) { - if (hash_equals(hash_hmac('sha256', $secondToken, $_SESSION['token']), $token)) { + if (hash_equals(hash_hmac('sha256', (string) $secondToken, (string) $_SESSION['token']), $token)) { return true; } else { error_log("WARNING : Malicious attempt encountered"); diff --git a/patient_portal/import_template.php b/patient_portal/import_template.php index 2ade0db97..056041115 100644 --- a/patient_portal/import_template.php +++ b/patient_portal/import_template.php @@ -25,7 +25,7 @@ if (!isset($_POST['token'])) { error_log('WARNING: A POST request detected with no csrf token found'); die('Authentication failed.'); - } else if (!(CsrfToken::verifyCsrfToken($_POST['token'])) { + } else if (!(CsrfToken::verifyCsrfToken($_POST['token']))) { die('Authentication failed.'); } } From 381004f31818461ec05709b34ee7a5118cb20b9d Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Sat, 8 Aug 2020 16:57:15 +0100 Subject: [PATCH 06/10] fix remote code execution vulnerabilities system --- interface/billing/sl_eob_search.php | 4 +-- interface/fax/fax_dispatch.php | 46 +++++++++++++---------------- interface/fax/faxq.php | 4 +-- interface/super/edit_globals.php | 2 +- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/interface/billing/sl_eob_search.php b/interface/billing/sl_eob_search.php index 9180b8a80..949d4ba2f 100644 --- a/interface/billing/sl_eob_search.php +++ b/interface/billing/sl_eob_search.php @@ -470,7 +470,7 @@ function upload_file_to_client_pdf($file_to_send) { if ($DEBUG) { $alertmsg = xl("Printing skipped; see test output in") .' '. $STMT_TEMP_FILE; } else { - exec("$STMT_PRINT_CMD $STMT_TEMP_FILE"); + exec(escapeshellcmd($STMT_PRINT_CMD) . " " . escapeshellarg($STMT_TEMP_FILE)); if ($_POST['form_without']) { $alertmsg = xl('Now printing') .' '. $stmt_count .' '. xl('statements; invoices will not be updated.'); } else { @@ -665,7 +665,7 @@ function npopup(pid) { // Handle .zip extension if present. Probably won't work on Windows. if (strtolower(substr($_FILES['form_erafile']['name'], -4)) == '.zip') { rename($tmp_name, "$tmp_name.zip"); - exec("unzip -p $tmp_name.zip > $tmp_name"); + exec("unzip -p " . escapeshellarg($tmp_name . ".zip") . " > " . escapeshellarg($tmp_name)); unlink("$tmp_name.zip"); } diff --git a/interface/fax/fax_dispatch.php b/interface/fax/fax_dispatch.php index e66863fe6..72190abff 100644 --- a/interface/fax/fax_dispatch.php +++ b/interface/fax/fax_dispatch.php @@ -64,7 +64,7 @@ // function getKittens($catid, $catstring, &$categories) { $cres = sqlStatement("SELECT id, name FROM categories " . - "WHERE parent = $catid ORDER BY name"); + "WHERE parent = ? ORDER BY name", array($catid)); $childcount = 0; while ($crow = sqlFetchArray($cres)) { ++$childcount; @@ -88,7 +88,7 @@ function mergeTiffs() { $inames .= ' ' . escapeshellarg("$inbase.tif"); } if (!$inames) die(xl("Internal error - no pages were selected!")); - $tmp0 = exec("cd '$faxcache'; tiffcp $inames temp.tif", $tmp1, $tmp2); + $tmp0 = exec("cd " . escapeshellarg($faxcache) . "; tiffcp $inames temp.tif", $tmp1, $tmp2); if ($tmp2) { $msg .= "tiffcp returned $tmp2: $tmp0 "; } @@ -107,7 +107,7 @@ function mergeTiffs() { if (!$patient_id) die(xl('Internal error - patient ID was not provided!')); // Compute the name of the target directory and make sure it exists. $docdir = $GLOBALS['OE_SITE_DIR'] . "/documents/$patient_id"; - exec("mkdir -p '$docdir'"); + exec("mkdir -p " . escapeshellarg($docdir)); // If copying to patient documents... // @@ -134,7 +134,7 @@ function mergeTiffs() { $info_msg .= mergeTiffs(); // The -j option here requires that libtiff is configured with libjpeg. // It could be omitted, but the output PDFs would then be quite large. - $tmp0 = exec("tiff2pdf -j -p letter -o '$target' '$faxcache/temp.tif'", $tmp1, $tmp2); + $tmp0 = exec("tiff2pdf -j -p letter -o " . escapeshellarg($target) . " " . escapeshellarg($faxcache . '/temp.tif'), $tmp1, $tmp2); if ($tmp2) { $info_msg .= "tiff2pdf returned $tmp2: $tmp0 "; @@ -153,10 +153,8 @@ function mergeTiffs() { sqlStatement($query); $query = "INSERT INTO categories_to_documents ( " . "category_id, document_id" . - " ) VALUES ( " . - "'$catid', '$newid' " . - ")"; - sqlStatement($query); + " ) VALUES (?, ?)"; + sqlStatement($query, array($catid, $newid)); } // end not error // If we are posting a note... @@ -165,7 +163,7 @@ function mergeTiffs() { // See pnotes_full.php which uses this to auto-display the document. $note = "$ffname$ffmod$ffsuff"; for ($tmp = $catid; $tmp;) { - $catrow = sqlQuery("SELECT name, parent FROM categories WHERE id = '$tmp'"); + $catrow = sqlQuery("SELECT name, parent FROM categories WHERE id = ?", array($tmp)); $note = $catrow['name'] . "/$note"; $tmp = $catrow['parent']; } @@ -203,24 +201,22 @@ function mergeTiffs() { // scanned notes must be installed, and does not natively exist. $query = "INSERT INTO form_scanned_notes ( " . "notes " . - ") VALUES ( " . - "'" . $_POST['form_copy_sn_comments'] . "' " . - ")"; - $formid = sqlInsert($query); + ") VALUES (?)"; + $formid = sqlInsert($query, array($_POST['form_copy_sn_comments'])); addForm($encounter_id, "Scanned Notes", $formid, "scanned_notes", $patient_id, $userauthorized); // $imagedir = $GLOBALS['OE_SITE_DIR'] . "/documents/$patient_id/encounters"; $imagepath = "$imagedir/${encounter_id}_$formid.jpg"; if (! is_dir($imagedir)) { - $tmp0 = exec('mkdir -p "' . $imagedir . '"', $tmp1, $tmp2); + $tmp0 = exec('mkdir -p ' . escapeshellarg($imagedir), $tmp1, $tmp2); if ($tmp2) die("mkdir returned $tmp2: $tmp0"); - exec("touch '$imagedir/index.html'"); + exec("touch " . escapeshellarg($imagedir . "/index.html")); } if (is_file($imagepath)) unlink($imagepath); // TBD: There may be a faster way to create this file, given that // we already have a jpeg for each page in faxcache. - $cmd = "convert -resize 800 -density 96 '$tmp_name' -append '$imagepath'"; + $cmd = "convert -resize 800 -density 96 " . escapeshellarg($tmp_name) . " -append " . escapeshellarg($imagepath); $tmp0 = exec($cmd, $tmp1, $tmp2); if ($tmp2) die("\"$cmd\" returned $tmp2: $tmp0"); } @@ -271,8 +267,8 @@ function mergeTiffs() { $cpstring = str_replace('{MESSAGE}' , $form_message , $cpstring); fwrite($tmph, $cpstring); fclose($tmph); - $tmp0 = exec("cd $webserver_root/custom; " . $GLOBALS['hylafax_enscript'] . - " -o $tmpfn2 $tmpfn1", $tmp1, $tmp2); + $tmp0 = exec("cd " . escapeshellarg($webserver_root . '/custom') . "; " . escapeshellcmd($GLOBALS['hylafax_enscript']) . + " -o " . escapeshellarg($tmpfn2) . " " . escapeshellarg($tmpfn1), $tmp1, $tmp2); if ($tmp2) { $info_msg .= "enscript returned $tmp2: $tmp0 "; } @@ -280,8 +276,8 @@ function mergeTiffs() { // Send the fax as the cover page followed by the selected pages. $info_msg .= mergeTiffs(); - $tmp0 = exec("sendfax -A -n $form_finemode -d " . - escapeshellarg($form_fax) . " $tmpfn2 '$faxcache/temp.tif'", + $tmp0 = exec("sendfax -A -n " . escapeshellarg($form_finemode) . " -d " . + escapeshellarg($form_fax) . " " . escapeshellarg($tmpfn2) . " " . escapeshellarg($faxcache . '/temp.tif'), $tmp1, $tmp2); if ($tmp2) { $info_msg .= "sendfax returned $tmp2: $tmp0 "; @@ -356,21 +352,21 @@ function mergeTiffs() { // This will contain a .tif image as well as a .jpg image for each page. // if (! is_dir($faxcache)) { - $tmp0 = exec('mkdir -p "' . $faxcache . '"', $tmp1, $tmp2); + $tmp0 = exec('mkdir -p ' . escapeshellarg($faxcache), $tmp1, $tmp2); if ($tmp2) die("mkdir returned $tmp2: $tmp0"); if (strtolower($ext) != '.tif') { // convert's default density for PDF-to-TIFF conversion is 72 dpi which is // not very good, so we upgrade it to "fine mode" fax quality. It's really // better and faster if the scanner produces TIFFs instead of PDFs. - $tmp0 = exec("convert -density 203x196 '$filepath' '$faxcache/deleteme.tif'", $tmp1, $tmp2); + $tmp0 = exec("convert -density 203x196 " . escapeshellarg($filepath) . " " . escapeshellarg($faxcache . '/deleteme.tif'), $tmp1, $tmp2); if ($tmp2) die("convert returned $tmp2: $tmp0"); - $tmp0 = exec("cd '$faxcache'; tiffsplit 'deleteme.tif'; rm -f 'deleteme.tif'", $tmp1, $tmp2); + $tmp0 = exec("cd " . escapeshellarg($faxcache) . "; tiffsplit 'deleteme.tif'; rm -f 'deleteme.tif'", $tmp1, $tmp2); if ($tmp2) die("tiffsplit/rm returned $tmp2: $tmp0"); } else { - $tmp0 = exec("cd '$faxcache'; tiffsplit '$filepath'", $tmp1, $tmp2); + $tmp0 = exec("cd " . escapeshellarg($faxcache) . "; tiffsplit " . escapeshellarg($filepath), $tmp1, $tmp2); if ($tmp2) die("tiffsplit returned $tmp2: $tmp0"); } - $tmp0 = exec("cd '$faxcache'; mogrify -resize 750x970 -format jpg *.tif", $tmp1, $tmp2); + $tmp0 = exec("cd " . escapeshellarg($faxcache) . "; mogrify -resize 750x970 -format jpg *.tif", $tmp1, $tmp2); if ($tmp2) die("mogrify returned $tmp2: $tmp0; ext is '$ext'; filepath is '$filepath'"); } diff --git a/interface/fax/faxq.php b/interface/fax/faxq.php index 31b2e2954..523211f4e 100644 --- a/interface/fax/faxq.php +++ b/interface/fax/faxq.php @@ -27,7 +27,7 @@ if ($GLOBALS['enable_hylafax']) { // Get the recvq entries, parse and sort by filename. $statlines = array(); - exec("faxstat -r -l -h " . $GLOBALS['hylafax_server'], $statlines); + exec("faxstat -r -l -h " . escapeshellarg($GLOBALS['hylafax_server']), $statlines); foreach ($statlines as $line) { // This gets pagecount, sender, time, filename. We are expecting the // string to start with "-rw-rw-" so as to exclude faxes not yet fully @@ -46,7 +46,7 @@ 154 124 F nobody 6153551807 0:1 4:12 No carrier detected */ $donelines = array(); - exec("faxstat -s -d -l -h " . $GLOBALS['hylafax_server'], $donelines); + exec("faxstat -s -d -l -h " . escapeshellarg($GLOBALS['hylafax_server']), $donelines); foreach ($donelines as $line) { // This gets jobid, priority, statchar, owner, phone, pages, dials and tts/status. if (preg_match('/^(\d+)\s+(\d+)\s+(\S)\s+(\S+)\s+(\S+)\s+(\d+:\d+)\s+(\d+:\d+)(.*)$/', $line, $matches)) { diff --git a/interface/super/edit_globals.php b/interface/super/edit_globals.php index 162eb94cb..c1ca7586c 100644 --- a/interface/super/edit_globals.php +++ b/interface/super/edit_globals.php @@ -36,7 +36,7 @@ require_once("$srcdir/user.inc"); require_once("$srcdir/classes/CouchDB.class.php"); require_once("$srcdir/calendar.inc"); -require_once("../../library/CsrfToken.php"); +require_once("$srcdir/CsrfToken.php"); if ($_GET['mode'] != "user") { // Check authorization. From 728bf9f8475e5e09266abc64417edae3e2c66759 Mon Sep 17 00:00:00 2001 From: Elizabeth Date: Sat, 8 Aug 2020 23:40:06 +0100 Subject: [PATCH 07/10] fix csrf vulnerabilities --- interface/main/tabs/js/tabs_view_model.js | 2 +- interface/main/tabs/main.php | 2 ++ interface/patient_file/encounter/forms.php | 4 ++++ interface/patient_file/letter.php | 3 ++- .../patient_file/reminder/clinical_reminders.php | 9 ++++++--- .../patient_file/reminder/patient_reminders.php | 6 ++++-- interface/patient_file/summary/demographics.php | 4 ++-- .../patient_file/transaction/record_request.php | 1 + interface/patient_tracker/patient_tracker.php | 1 + .../clinical_stats_by_demographics_report.php | 3 ++- .../reports/lab_stats_by_demographics_report.php | 3 ++- interface/reports/username_report.php | 11 ++++++++--- interface/super/edit_layout.php | 7 ++++--- interface/super/field_id_popup.php | 10 +++++++++- interface/super/layout_listitems_ajax.php | 9 +++++++++ interface/super/show_groups_popup.php | 11 ++++++++++- interface/super/show_lists_popup.php | 10 ++++++++++ interface/usergroup/adminacl.php | 5 +++++ library/CsrfToken.php | 6 ++++++ library/ajax/addlistitem.php | 12 ++++++++++++ library/ajax/adminacl_ajax.php | 10 ++++++++-- library/ajax/amc_misc_data.php | 7 +++++++ library/ajax/ccr_import_ajax.php | 6 ++++++ ..._and_lab_stats_by_demographics_report_ajax.php | 10 ++++++++-- library/ajax/collect_new_report_id.php | 9 +++++++++ library/ajax/dated_reminders_counter.php | 10 ++++++++++ library/ajax/drug_screen_completed.php | 9 +++++++++ library/ajax/execute_background_services.php | 15 ++++++++++++++- library/ajax/payment_ajax.php | 9 +++++++++ library/ajax/payment_ajax_jav.inc.php | 3 ++- library/ajax/plan_setting.php | 8 ++++++++ library/ajax/prescription_drugname_lookup.php | 9 +++++++++ library/ajax/rule_setting.php | 9 +++++++++ library/ajax/status_report.php | 8 ++++++++ library/ajax/unset_session_ajax.php | 8 ++++++++ library/ajax/user_settings.php | 9 +++++++++ library/ajax/username_report_ajax.php | 10 ++++++++++ library/options_listadd.inc | 1 + modules/MIPS/clinical_measures.php | 3 ++- modules/nation_notes/nn_super_edit_layout.inc | 7 ++++--- templates/documents/general_view.php | 1 + templates/prescription/general_edit.php | 2 +- 42 files changed, 252 insertions(+), 30 deletions(-) diff --git a/interface/main/tabs/js/tabs_view_model.js b/interface/main/tabs/js/tabs_view_model.js index 7bfcf58c9..fb87f9c82 100644 --- a/interface/main/tabs/js/tabs_view_model.js +++ b/interface/main/tabs/js/tabs_view_model.js @@ -249,7 +249,7 @@ function clearPatient() $.ajax({ type: "POST", url: webroot_url+"/library/ajax/unset_session_ajax.php", - data: { func: "unset_pid"}, + data: { func: "unset_pid", token: jsCsrfToken}, success:function( msg ) { diff --git a/interface/main/tabs/main.php b/interface/main/tabs/main.php index 4806526b9..1226e160d 100644 --- a/interface/main/tabs/main.php +++ b/interface/main/tabs/main.php @@ -122,6 +122,8 @@ function isEncounterLocked( encounterId ) { .',' . json_encode($userQuery['fname']) .',' . json_encode($userQuery['lname']) .',' . json_encode($_SESSION['authGroup']); ?>)); + // Set the csrf token used in js/tabs_view_model.js script + var jsCsrfToken = ;