mirror of
https://github.com/itflow-org/itflow
synced 2026-07-26 10:17:15 +00:00
Neutralize CSV formula injection in generated exports using the new created escapeCsvFormula Function
This commit is contained in:
@@ -326,7 +326,7 @@ if (isset($_POST['export_users_csv'])) {
|
||||
}
|
||||
|
||||
$lineData = array($row['user_name'], $row['user_email'], $row['role_name'], $user_status_display, $row['user_created_at']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -1229,7 +1229,7 @@ if (isset($_POST['export_assets_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while ($row = mysqli_fetch_assoc($sql)) {
|
||||
$lineData = array($row['asset_name'], $row['asset_description'], $row['asset_type'], $row['asset_make'], $row['asset_model'], $row['asset_serial'], $row['asset_os'], $row['asset_purchase_date'], $row['asset_warranty_expire'], $row['asset_install_date'], $row['contact_name'], $row['location_name'], $row['asset_physical_location'], $row['asset_notes']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
@@ -1871,7 +1871,7 @@ if (isset($_POST['export_client_asset_interfaces_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = mysqli_fetch_assoc($sql)) {
|
||||
$lineData = array($row['interface_name'], $row['interface_description'], $row['interface_type'], $row['interface_mac'], $row['interface_ip'], $row['interface_nat_ip'], $row['interface_ipv6'], $row['network_name']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -376,7 +376,7 @@ if (isset($_POST['export_certificates_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['certificate_name'], $row['certificate_description'], $row['certificate_domain'], $row['certificate_issued_by'], $row['certificate_expire']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -514,7 +514,7 @@ if (isset($_POST['export_clients_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['client_name'], $row['client_type'], $row['client_referral'], $row['client_website'], $row['location_name'], formatPhoneNumber($row['location_phone']), $row['location_address'], $row['location_city'], $row['location_state'], $row['location_zip'], $row['location_country'], $row['contact_name'], $row['contact_title'], formatPhoneNumber($row['contact_phone']), $row['contact_extension'], formatPhoneNumber($row['contact_mobile']), $row['contact_email'], $row['client_rate'], $row['client_currency_code'], $row['client_net_terms'], $row['client_tax_id_number'], $row['client_abbreviation']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -1299,7 +1299,7 @@ if (isset($_POST['export_contacts_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['contact_name'], $row['contact_title'], $row['contact_department'], $row['contact_email'], formatPhoneNumber($row['contact_phone']), $row['contact_extension'], formatPhoneNumber($row['contact_mobile']), $row['location_name']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -450,7 +450,7 @@ if (isset($_POST['export_credentials_csv'])) {
|
||||
$credential_username = decryptCredentialEntry($row['credential_username']);
|
||||
$credential_password = decryptCredentialEntry($row['credential_password']);
|
||||
$lineData = array($row['credential_name'], $row['credential_description'], $credential_username, $credential_password, $row['credential_otp_secret'], $row['credential_uri']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -493,7 +493,7 @@ if (isset($_POST['export_domains_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['domain_name'], $row['domain_description'], $row['domain_registrar'], $row['domain_webhost'], $row['domain_expire']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -373,7 +373,7 @@ if (isset($_POST['export_expenses_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = mysqli_fetch_assoc($sql)) {
|
||||
$lineData = array($row['expense_date'], $row['expense_amount'], $row['vendor_name'], $row['expense_description'], $row['category_name'], $row['account_name']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -698,7 +698,7 @@ if (isset($_POST['export_invoices_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['invoice_prefix'] . $row['invoice_number'], $row['invoice_scope'], $row['invoice_amount'], $row['invoice_date'], $row['invoice_due'], $row['invoice_status'], $row['client_name']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -426,7 +426,7 @@ if(isset($_POST['export_locations_csv'])){
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()){
|
||||
$lineData = array($row['location_name'], $row['location_description'], $row['location_address'], $row['location_city'], $row['location_state'], $row['location_zip'], $row['location_phone'], $row['location_hours']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -210,7 +210,7 @@ if (isset($_POST['export_networks_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while ($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['network_name'], $row['network_description'], $row['network_vlan'], $row['network'], $row['network_gateway'], $row['network_dhcp_range'], $row['network_primary_dns'], $row['network_secondary_dns']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -736,7 +736,7 @@ if (isset($_POST['export_payments_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()){
|
||||
$lineData = array($row['payment_date'], $row['invoice_date'], $row['invoice_prefix'] . $row['invoice_number'], $row['invoice_amount'], $row['payment_amount'], $row['payment_method'], $row['payment_reference']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -274,7 +274,7 @@ if (isset($_POST['export_products_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = mysqli_fetch_assoc($sql)) {
|
||||
$lineData = array($row['product_name'], $row['product_description'], $row['product_price'], $row['product_currency_code'], $row['category_name'], $row['tax_name']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -724,7 +724,7 @@ if(isset($_POST['export_quotes_csv'])){
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()){
|
||||
$lineData = array($row['quote_prefix'] . $row['quote_number'], $row['quote_scope'], $row['quote_amount'], $row['quote_date'], $row['quote_status']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -639,7 +639,7 @@ if (isset($_POST['export_client_recurring_invoice_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['recurring_invoice_prefix'] . $row['recurring_invoice_number'], $row['recurring_invoice_scope'], $row['recurring_invoice_amount'], ucwords($row['recurring_invoice_frequency'] . "ly"), $row['recurring_invoice_created_at']);
|
||||
fputcsv($f, $lineData, $delimiter);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -290,7 +290,7 @@ if (isset($_POST['export_software_csv'])) {
|
||||
}
|
||||
|
||||
$lineData = array($row['software_name'], $row['software_version'], $row['software_description'], $row['software_type'], $row['software_license_type'], $row['software_seats'], $row['software_key'], $assigned_to_assets, $assigned_to_contacts, $row['software_purchase'], $row['software_expire'], $row['software_notes']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -2586,7 +2586,7 @@ if (isset($_POST['export_tickets_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while ($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($config_ticket_prefix . $row['ticket_number'], $row['ticket_priority'], $row['ticket_status_name'], $row['ticket_subject'], $row['ticket_created_at'], $row['ticket_resolved_at'], $row['ticket_closed_at']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -193,7 +193,7 @@ if (isset($_POST['export_transactions_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while ($row = mysqli_fetch_assoc($sql)) {
|
||||
$lineData = array($row['transaction_date'], $row['transaction_type'], $row['transaction_description'], $row['transaction_other_account'], $row['transaction_reference'], $row['transaction_category'], $row['transaction_payment_method'], $row['transaction_amount'], $row['transaction_balance']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -139,7 +139,7 @@ if (isset($_POST['export_trips_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = mysqli_fetch_assoc($sql)){
|
||||
$lineData = array($row['trip_date'], $row['trip_purpose'], $row['trip_source'], $row['trip_destination'], $row['trip_miles']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -388,7 +388,7 @@ if (isset($_POST['export_vendors_csv'])) {
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
$lineData = array($row['vendor_name'], $row['vendor_description'], $row['vendor_contact_name'], $row['vendor_phone'], $row['vendor_website'], $row['vendor_account_number'], $row['vendor_notes']);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
fputcsv($f, array_map('escapeCsvFormula', $lineData), $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -51,8 +51,7 @@ function cleanInput($input) {
|
||||
return $input;
|
||||
}
|
||||
|
||||
function toAlphanumeric($string)
|
||||
{
|
||||
function toAlphanumeric($string) {
|
||||
// Gets rid of non-alphanumerics
|
||||
return preg_replace('/[^A-Za-z0-9_-]/', '', $string);
|
||||
}
|
||||
@@ -144,3 +143,29 @@ function checkFileUpload($file, $allowed_extensions) {
|
||||
// reading the whole file into memory (up to 500 MB) for no downstream use.
|
||||
return randomString(32) . '.' . $extension;
|
||||
}
|
||||
|
||||
// Neutralize spreadsheet formula injection (CWE-1236) in a value bound for a
|
||||
// generated CSV export. This is NOT CSV-structure escaping — fputcsv already
|
||||
// quotes fields, doubles enclosures, and handles embedded newlines. Its only
|
||||
// job is to stop a spreadsheet app (Excel / LibreOffice Calc / Google Sheets)
|
||||
// from *evaluating* a syntactically valid cell as a formula on open. Prefixing
|
||||
// a single quote makes the app treat the cell as literal text.
|
||||
function escapeCsvFormula($value) {
|
||||
if (!is_string($value) || $value === '') {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Leave genuine numbers untouched so real data (e.g. negative amounts like
|
||||
// -42.50) isn't corrupted. An actual formula string is never is_numeric(),
|
||||
// so nothing dangerous slips through this early return.
|
||||
if (is_numeric($value)) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
// Leading characters that trigger formula / legacy-DDE evaluation on open.
|
||||
if (in_array($value[0], ['=', '+', '-', '@', "\t", "\r"], true)) {
|
||||
return "'" . $value;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user