FIX_VALIDATE_BUSI_INPUT_VALUES

This commit is contained in:
velz 2026-01-09 18:38:12 +05:30
parent c4ac5c386a
commit 20d63f09cd
3 changed files with 184 additions and 12 deletions

View File

@ -101,6 +101,6 @@ class Autoload extends AutoloadConfig
* @phpstan-var list<string>
*/
public $helpers = ['uuid','session','utility', 'form', 'url', 'oauth', 'fileupload',
'excel_import_export', 'file', 'drive','ExcelSanitizeHelper', 'api_helper','exception','sms_helper'
'excel_import_export', 'file', 'drive','ExcelSanitizeHelper', 'api_helper','exception','sms_helper','sanitizeInputArrayAdvanced'
];
}

View File

@ -736,14 +736,102 @@ class ClientController extends AdminController
public function saveDeposit()
{
$rules = [
'amount' => [
'rules' => 'required|numeric|greater_than_equal_to[0]',
'errors' => [
'required' => 'Amount is required',
'numeric' => 'Amount must be a valid number',
'greater_than_equal_to' => 'Amount cannot be negative',
]
],
'client_id' => [
'rules' => 'required|is_natural_no_zero',
'errors' => [
'required' => 'Client ID is required',
'is_natural_no_zero' => 'Client ID must be a positive integer',
]
],
'insurer_id' => [
'rules' => 'required|is_natural_no_zero',
'errors' => [
'required' => 'Insurer ID is required',
'is_natural_no_zero' => 'Insurer ID must be a positive integer',
]
],
'cd_ac_pk' => [
'rules' => 'required|is_natural_no_zero',
'errors' => [
'required' => 'Account PK is required',
'is_natural_no_zero' => 'Account PK must be a positive integer',
]
],
'cd_ac_no' => [
'rules' => 'required|is_natural_no_zero',
'errors' => [
'required' => 'Account number is required',
'is_natural_no_zero' => 'must be a positive integer',
]
],
'sub_type_id' => [
'rules' => 'required|is_natural_no_zero',
'errors' => [
'required' => 'Sub type ID is required',
'is_natural_no_zero' => 'Sub type ID must be a positive integer',
]
],
'description' => [
'rules' => 'required|string|min_length[3]|max_length[255]',
'errors' => [
'required' => 'Description is required',
'string' => 'Description must be text',
'min_length' => 'Description must be at least 3 characters',
'max_length' => 'Description must not exceed 255 characters',
]
],
'transaction_type' => [
'rules' => 'required|in_list[Credit,Debit]',
'errors' => [
'required' => 'Transaction type is required',
'in_list' => 'Transaction type must be either credit or debit',
]
],
];
if (! $this->validate($rules)) {
return $this->response
->setStatusCode(400)
->setJSON([
'status' => 'error',
'message' => 'Input validation failed',
'errors' => $this->validator->getErrors()
]);
}
//sanitize the post params
$post_data = $this->request->getPost();
$sanitized_post_data = sanitizeInputArrayAdvanced($post_data);
// Retrieve form data from POST request
$loggedInUserID = get_session_userid();
// print_rr($sanitized_post_data);die();
$client_id = $sanitized_post_data['client_id'];
$insurer_id = $sanitized_post_data['insurer_id'];
$record_date = $sanitized_post_data['record_date'];
$cd_ac_pk = $sanitized_post_data['cd_ac_pk'];
$cd_ac_no = $sanitized_post_data['cd_ac_no'];
$client_id = $this->request->getPost('client_id');
$insurer_id = $this->request->getPost('insurer_id');
$record_date = $this->request->getPost('record_date');
$cd_ac_pk = $this->request->getPost('cd_ac_pk');
$cd_ac_no = $this->request->getPost('cd_ac_no');
// $CD_Account_Number = $this->CDMasterModel
// ->where('client_id', $client_id)
@ -761,16 +849,16 @@ class ClientController extends AdminController
}
$data = [
'amount' => $this->request->getPost('amount'),
'sub_type_id' => $this->request->getPost('sub_type_id'),
'client_id' => $this->request->getPost('client_id'),
'amount' => $sanitized_post_data['amount'],
'sub_type_id' => $sanitized_post_data['sub_type_id'],
'client_id' => $sanitized_post_data['client_id'],
'client_policy_id' => null,
'cd_ac_no' => $cd_ac_no ?? null,
'cd_ac_pk' => $cd_ac_pk ?? null,
'endorsement_no' => null,
'insurer_id' => $this->request->getPost('insurer_id'),
'description' => $this->request->getPost('description'),
'transaction_type' => $this->request->getPost('transaction_type') ?: 'Credit',
'insurer_id' => $sanitized_post_data['insurer_id'],
'description' => $sanitized_post_data['description'],
'transaction_type' => $sanitized_post_data['transaction_type'] ?: 'Credit',
'updated_by' => 1,
'record_date' => $record_date
];

View File

@ -0,0 +1,84 @@
<?php
// use Normalizer;
/**
* High security sanitizer
* - Normalizes unicode
* - Removes control chars
* - Removes null bytes
* - Removes invisible unicode tricks
* - Strips dangerous HTML
* - Prevents polyglot payloads
*/
function sanitizeInputArrayAdvanced(array $data, array $htmlAllowedFields = []): array
{
foreach ($data as $k => $v) {
if (is_array($v)) {
$data[$k] = sanitizeInputArrayAdvanced($v, $htmlAllowedFields);
continue;
}
if (!is_string($v)) {
continue;
}
// 1. Unicode normalization (prevents homoglyph attacks)
if (class_exists('Normalizer')) {
$v = \Normalizer::normalize($v, \Normalizer::FORM_C);
}
// 2. Remove NULL bytes & control chars
$v = preg_replace('/[\x00-\x1F\x7F]/u', '', $v);
// 3. Remove invisible unicode chars (zero width, etc)
$v = preg_replace('/[\x{200B}-\x{200F}\x{202A}-\x{202E}\x{2060}-\x{206F}]/u', '', $v);
// 4. Decode HTML entities (so hidden payloads are exposed)
$v = html_entity_decode($v, ENT_QUOTES | ENT_HTML5, 'UTF-8');
// 5. Trim
$v = trim($v);
// 6. If this field is NOT allowed to contain HTML → strip aggressively
if (!in_array($k, $htmlAllowedFields, true)) {
// Remove all tags
$v = strip_tags($v);
// Kill any leftover JS protocol
$v = preg_replace('/(javascript:|data:|vbscript:)/i', '', $v);
} else {
// This is HTML-allowed field → run HTML sanitizer
$v = sanitizeTrustedHtml($v);
}
$data[$k] = $v;
}
return $data;
}
function sanitizeTrustedHtml(string $html): string
{
// Allowed tags for email templates
$allowedTags = '<p><br><b><strong><i><u><em><ul><ol><li><table><thead><tbody><tr><td><th><a><img><div><span><h1><h2><h3><h4><h5><h6>';
// Strip all other tags
$html = strip_tags($html, $allowedTags);
// Remove event handlers like onclick, onerror, etc
$html = preg_replace('/\son\w+="[^"]*"/i', '', $html);
$html = preg_replace("/\son\w+='[^']*'/i", '', $html);
// Remove javascript: and data:
$html = preg_replace('/(javascript:|vbscript:|data:)/i', '', $html);
// Remove iframe, object, embed even if sneaked in
$html = preg_replace('/<(iframe|object|embed|script|style)[^>]*>.*?<\/\1>/is', '', $html);
return $html;
}