Browse Source

Security: fix SQL injection, XSS, and remove debug logging

SQL injection:
- progress.php, payment_request.php: cast $drg to int from GET
- client-brief.php: cast $drg to int from GET; cast $crm_id, $response['id'], $dealId inline before queries

XSS:
- dashboard.php: htmlspecialchars on all echoed DB row values (name, address, build_type, IDs)
- client-brief.php: htmlspecialchars on $_POST['firstname'/'lastname'] in CRM alert messages; escape $quid and $client in deal alerts
- progress.php: htmlspecialchars on description/paid/value in input value attributes
- payment_request.php: htmlspecialchars on description/paid/value in inputs and data attributes

Debug logging:
- planbuild.php: remove file_put_contents debug call that was logging all uploaded files and POST data

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Benjamin Harris 2 weeks ago
parent
commit
a4a2c5486b

+ 9 - 9
internal/client-brief.php

@@ -19,7 +19,7 @@ $csrf = $_SESSION['csrf'];
 $accessToken = getenv('HUBSPOT_TOKEN') ?: '';
 
 #$enquiry_date = date("l dS M \'y");
-$drg = isset($_GET['drg']) ? $_GET['drg'] : '';
+$drg = isset($_GET['drg']) ? (int)$_GET['drg'] : 0;
 
 if (!empty($_GET['drg'])) {
     include "table.php";
@@ -629,12 +629,12 @@ if (!empty($drg) and !empty($_POST['add_client_to_crm']) and empty($contactId))
 
             if ($createdContact['id'] > 0) {
                 $crm_id = intval($createdContact['id']);
-                $result = mysqli_query($con, "UPDATE details SET crm_id = '{$crm_id}' WHERE drg = '{$drg}'");
+                $result = mysqli_query($con, "UPDATE details SET crm_id = " . (int)$crm_id . " WHERE drg = " . (int)$drg);
                 if (!$result) {
                     printf("Error: %s\n", mysqli_error($con));
                     exit();
                 } else {
-                    echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: {$_POST['firstname']} {$_POST['lastname']} added to crm, with id: {$crm_id}</h4></div>";
+                    echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: " . htmlspecialchars($_POST['firstname'], ENT_QUOTES, 'UTF-8') . " " . htmlspecialchars($_POST['lastname'], ENT_QUOTES, 'UTF-8') . " added to crm, with id: " . (int)$crm_id . "</h4></div>";
                     $isHideDismissableAlert = 1;
                 }
             }
@@ -695,13 +695,13 @@ if (!empty($drg) and !empty($_POST['add_client_to_crm']) and empty($contactId))
 
         if ($response['total'] > 0) {
             $response = updateContact($contactId, $data);
-            $result = mysqli_query($con, "UPDATE details SET crm_id = '{$response['id']}' WHERE drg = '{$drg}'");
+            $result = mysqli_query($con, "UPDATE details SET crm_id = " . (int)$response['id'] . " WHERE drg = " . (int)$drg);
             file_put_contents("crmupdate.log", $response);
 
             $response = json_decode($response, true);
 
             if ($response['id'] > 0) {
-                echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: {$_POST['firstname']} {$_POST['lastname']} updated in crm</h4></div>";
+                echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: " . htmlspecialchars($_POST['firstname'], ENT_QUOTES, 'UTF-8') . " " . htmlspecialchars($_POST['lastname'], ENT_QUOTES, 'UTF-8') . " updated in crm</h4></div>";
                 $isHideDismissableAlert = 1;
             }
         } else {
@@ -712,7 +712,7 @@ if (!empty($drg) and !empty($_POST['add_client_to_crm']) and empty($contactId))
             if ($createdContact['id'] > 0) {
                 $crm_id = intval($createdContact['id']);
 
-                echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: {$_POST['firstname']} {$_POST['lastname']} added to crm, with id: {$crm_id}</h4></div>";
+                echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Customer: " . htmlspecialchars($_POST['firstname'], ENT_QUOTES, 'UTF-8') . " " . htmlspecialchars($_POST['lastname'], ENT_QUOTES, 'UTF-8') . " added to crm, with id: " . (int)$crm_id . "</h4></div>";
                 $isHideDismissableAlert = 1;
             }
         }
@@ -770,8 +770,8 @@ if (!empty($quid) and !empty($_POST['add_deal_to_hubspot']) and empty($dealId))
 
         if ($createdDeal['id'] > 0) {
             $dealId = intval($createdDeal['id']);
-            $result = mysqli_query($con, "UPDATE details SET dealId = '{$dealId}' WHERE drg = '{$drg}'");
-            echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Deal: {$quid} - {$client} added to hubspot</h4></div>";
+            $result = mysqli_query($con, "UPDATE details SET dealId = " . (int)$dealId . " WHERE drg = " . (int)$drg);
+            echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Deal: " . htmlspecialchars((string)$quid, ENT_QUOTES, 'UTF-8') . " - " . htmlspecialchars((string)$client, ENT_QUOTES, 'UTF-8') . " added to hubspot</h4></div>";
             $isHideDismissableAlert = 1;
 
         }
@@ -809,7 +809,7 @@ if (!empty($quid) and !empty($_POST['add_deal_to_hubspot']) and empty($dealId))
 
         if ($updatedDeal['id'] > 0) {
             $dealId = intval($updatedDeal['id']);
-            echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Deal: {$quid} - {$client} added to hubspot</h4></div>";
+            echo "<div class='container alert alert-success alert-dismissible d-print-none' role='alert'><a href='#' class='close' data-dismiss='alert' aria-label='close'>&times;</a><h4 style=\"text-align: center;\">Deal: " . htmlspecialchars((string)$quid, ENT_QUOTES, 'UTF-8') . " - " . htmlspecialchars((string)$client, ENT_QUOTES, 'UTF-8') . " added to hubspot</h4></div>";
             $isHideDismissableAlert = 1;
 
         }

+ 4 - 4
internal/dashboard.php

@@ -107,11 +107,11 @@ $not_required = "<i class='h2 bi bi-dash-circle-fill'></i>";
 
                                 echo "<tr class='border-bottom border-dark'>";
                                 echo "<th scope='row' class='border-end text-center'><a class='brown-three text-decoration-none' href='client-brief.php?drg=$drg'>" . $drg . "</a></th>";
-                                echo "<td><span class='fw-bold'>" . $row['firstname'] . " " . $row['lastname'] . '</span><br><span class="small">' . $row['site_address_street'] . ', ' . $row['site_address_town'] . "</span></td>";
-                                echo "<td>" . $row['build_type'] . "</td>";
+                                echo "<td><span class='fw-bold'>" . htmlspecialchars($row['firstname'], ENT_QUOTES, 'UTF-8') . " " . htmlspecialchars($row['lastname'], ENT_QUOTES, 'UTF-8') . '</span><br><span class="small">' . htmlspecialchars($row['site_address_street'], ENT_QUOTES, 'UTF-8') . ', ' . htmlspecialchars($row['site_address_town'], ENT_QUOTES, 'UTF-8') . "</span></td>";
+                                echo "<td>" . htmlspecialchars($row['build_type'], ENT_QUOTES, 'UTF-8') . "</td>";
                             	echo "<td class='text-center'>" . $site_visit . "</td>";
-                                echo "<td>" . $row['property_id'] . "</td>";
-                                echo "<td class='border-end' >" . $row['title_id'] . "</td>";
+                                echo "<td>" . htmlspecialchars($row['property_id'], ENT_QUOTES, 'UTF-8') . "</td>";
+                                echo "<td class='border-end' >" . htmlspecialchars($row['title_id'], ENT_QUOTES, 'UTF-8') . "</td>";
 
                             	echo "<td class='text-center'><a class='brown-three text-decoration-none' href='../contracts/edit_application.php?id=$drg'><i class='h2 bi bi-speedometer'></i></a></td>";
                             	

+ 11 - 7
internal/payment_request.php

@@ -12,7 +12,7 @@ include_once "vendor/autoload.php";
 $accessToken = getenv('HUBSPOT_TOKEN') ?: '';
 
 $enquiry_date = date("l dS M \'y");
-$drg = isset($_GET['drg']) ? $_GET['drg'] : '';
+$drg = isset($_GET['drg']) ? (int)$_GET['drg'] : 0;
 
 $payment_no = isset($_GET['pn']) ? $_GET['pn'] : '';
 
@@ -283,20 +283,24 @@ if (!empty($_GET['drg'])) {
                 exit();
             }
             while ($row = mysqli_fetch_array($result)) {
+                $pos  = (int)$row['position'];
+                $desc = htmlspecialchars($row['description'], ENT_QUOTES, 'UTF-8');
+                $paid = htmlspecialchars($row['paid'], ENT_QUOTES, 'UTF-8');
+                $val  = htmlspecialchars($row['value'], ENT_QUOTES, 'UTF-8');
                 echo "<div class='mb-1 row justify-content-start'>";
-                echo "<label for='description' class='col-1 col-form-label'>" . $row['position'] . "</label>";
-                echo "<input type='hidden' id='progress' v-model='progress' value='" . $row['position'] . "'>";
+                echo "<label for='description' class='col-1 col-form-label'>" . $pos . "</label>";
+                echo "<input type='hidden' id='progress' v-model='progress' value='" . $pos . "'>";
                 echo "<div class='col-sm-5'>";
-                echo "<input type='text' class='form-control form-control-sm' id='description' v-model='description' value='" . $row['description'] . "' disabled>";
+                echo "<input type='text' class='form-control form-control-sm' id='description' v-model='description' value='" . $desc . "' disabled>";
                 echo "</div>";
                 echo "<div class='col-sm-2'>";
-                echo "<input type='text' class='form-control form-control-sm' id='paid' v-model='paid' value='" . $row['paid'] . "' disabled>";
+                echo "<input type='text' class='form-control form-control-sm' id='paid' v-model='paid' value='" . $paid . "' disabled>";
                 echo "</div>";
                 echo "<div class='col-sm-2'>";
-                echo "<input type='currency' class='form-control form-control-sm' id='value' v-model='value' value='" . $row['value'] . "' disabled>";
+                echo "<input type='currency' class='form-control form-control-sm' id='value' v-model='value' value='" . $val . "' disabled>";
                 echo "</div>";
                 echo "<div class='col-sm-2'>";
-                echo "<button class='btn btn-sm bg-brown-three brown-five' id='card-button' type='button' data-value=" . $row['value'] . " >Pay $" . $row['value'] . "</button>";
+                echo "<button class='btn btn-sm bg-brown-three brown-five' id='card-button' type='button' data-value='" . $val . "'>Pay $" . $val . "</button>";
                 echo "</div>";
                 echo "</div>";
             }

+ 0 - 1
internal/planbuild.php

@@ -11,7 +11,6 @@ if ($_POST['token'] !== SECRET_TOKEN) {
     exit;
 }
 */
-file_put_contents('upload_debug.log', print_r($_FILES, true) . print_r($_POST, true));
 
 // Check file
 if (!isset($_FILES['pdf']) || $_FILES['pdf']['error'] !== UPLOAD_ERR_OK) {

+ 6 - 6
internal/progress.php

@@ -12,7 +12,7 @@ include_once "vendor/autoload.php";
 $accessToken = getenv('HUBSPOT_TOKEN') ?: '';
 
 $enquiry_date = date("l dS M \'y");
-$drg = isset($_GET['drg']) ? $_GET['drg'] : '';
+$drg = isset($_GET['drg']) ? (int)$_GET['drg'] : 0;
 
 if (!empty($_GET['drg'])) {
     include "table.php";
@@ -131,16 +131,16 @@ if (!empty($_GET['drg'])) {
                     }
                     while ($row = mysqli_fetch_array($result)) {
                     	echo "<div class='mb-1 row justify-content-start'>";
-                        echo "<label for='description' class='col-1 col-form-label'>" . $row['position'] . "</label>";
-                        echo "<input type='hidden' id='progress' v-model='progress' value='" . $row['position'] . "'>";
+                        echo "<label for='description' class='col-1 col-form-label'>" . (int)$row['position'] . "</label>";
+                        echo "<input type='hidden' id='progress' v-model='progress' value='" . (int)$row['position'] . "'>";
                         echo "<div class='col-sm-7'>";
-                        echo "<input type='text' class='form-control' id='description' v-model='description' value='" . $row['description'] . "' disabled>";
+                        echo "<input type='text' class='form-control' id='description' v-model='description' value='" . htmlspecialchars($row['description'], ENT_QUOTES, 'UTF-8') . "' disabled>";
                         echo "</div>";
                     	echo "<div class='col-sm-2'>";
-                        echo "<input type='text' class='form-control' id='paid' v-model='paid' value='" . $row['paid'] . "' disabled>";
+                        echo "<input type='text' class='form-control' id='paid' v-model='paid' value='" . htmlspecialchars($row['paid'], ENT_QUOTES, 'UTF-8') . "' disabled>";
                         echo "</div>";
                         echo "<div class='col-sm-2'>";
-                        echo "<input type='currency' class='form-control' id='value' v-model='value' value='" . $row['value'] . "' disabled>";
+                        echo "<input type='currency' class='form-control' id='value' v-model='value' value='" . htmlspecialchars($row['value'], ENT_QUOTES, 'UTF-8') . "' disabled>";
                         echo "</div>";
                     	echo "</div>";
         			}