nhance/app/Helpers/sanitizeInputArrayAdvanced_helper.php
2026-01-09 18:38:12 +05:30

85 lines
2.4 KiB
PHP

<?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;
}