diff --git a/controllers/C_Document.class.php b/controllers/C_Document.class.php
index a8d82eed6..4c1d83c47 100644
--- a/controllers/C_Document.class.php
+++ b/controllers/C_Document.class.php
@@ -14,6 +14,7 @@
require_once(dirname(__FILE__) . "/../library/forms.inc");
require_once(dirname(__FILE__) . "/../library/formatting.inc.php");
require_once(dirname(__FILE__) . "/../library/classes/postmaster.php" );
+require_once(dirname(__FILE__) . "/../library/sanitize.inc.php" );
class C_Document extends Controller {
@@ -170,6 +171,8 @@ function upload_action_process() {
if ($_FILES['file']['size'][$key] == 0) {
$error .= "The system does not permit uploading files of with size 0.\n";
}
+ } elseif (!isSafeFile($_FILES['file']['tmp_name'][$key])) {
+ $error = xl("The system does not permit uploading files with MIME content type") . " - " . mime_content_type($_FILES['file']['tmp_name'][$key]) . ".\n";
} else {
$tmpfile = fopen($_FILES['file']['tmp_name'][$key], "r");
$filetext = fread($tmpfile, $_FILES['file']['size'][$key]);
diff --git a/interface/billing/edi_history_main.php b/interface/billing/edi_history_main.php
index 1e15f4de5..1195d77f3 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/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/main/main_screen.php b/interface/main/main_screen.php
index e2639250d..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
@@ -41,6 +42,9 @@
session_regenerate_id(false);
}
+//generate csrf token
+$_SESSION['token'] = CsrfToken::generateCsrfToken();
+
$_SESSION["encounter"] = '';
// Fetch the password expiration date
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 = ;