Fix WAF whitelist ordering and URI matching
This commit is contained in:
@@ -257,6 +257,7 @@ class Waf extends Page implements HasForms, HasTable
|
||||
{
|
||||
$ruleId = (string) ($entry['rule_id'] ?? '');
|
||||
$uri = (string) ($entry['uri'] ?? '');
|
||||
$uriPath = $this->stripQueryString($uri);
|
||||
$host = (string) ($entry['host'] ?? '');
|
||||
$ip = (string) ($entry['remote_ip'] ?? '');
|
||||
|
||||
@@ -281,10 +282,10 @@ class Waf extends Page implements HasForms, HasTable
|
||||
if ($matchType === 'ip' && $matchValue !== '' && $this->ipMatches($ip, $matchValue)) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'uri_exact' && $matchValue !== '' && $uri === $matchValue) {
|
||||
if ($matchType === 'uri_exact' && $matchValue !== '' && ($uri === $matchValue || $uriPath === $matchValue)) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'uri_prefix' && $matchValue !== '' && str_starts_with($uri, $matchValue)) {
|
||||
if ($matchType === 'uri_prefix' && $matchValue !== '' && (str_starts_with($uri, $matchValue) || str_starts_with($uriPath, $matchValue))) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'host' && $matchValue !== '' && $host === $matchValue) {
|
||||
@@ -306,6 +307,7 @@ class Waf extends Page implements HasForms, HasTable
|
||||
|
||||
$ruleId = (string) ($entry['rule_id'] ?? '');
|
||||
$uri = (string) ($entry['uri'] ?? '');
|
||||
$uriPath = $this->stripQueryString($uri);
|
||||
$host = (string) ($entry['host'] ?? '');
|
||||
$ip = (string) ($entry['remote_ip'] ?? '');
|
||||
|
||||
@@ -322,10 +324,10 @@ class Waf extends Page implements HasForms, HasTable
|
||||
if ($matchType === 'ip' && $matchValue !== '' && $this->ipMatches($ip, $matchValue)) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'uri_exact' && $matchValue !== '' && $uri === $matchValue) {
|
||||
if ($matchType === 'uri_exact' && $matchValue !== '' && ($uri === $matchValue || $uriPath === $matchValue)) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'uri_prefix' && $matchValue !== '' && str_starts_with($uri, $matchValue)) {
|
||||
if ($matchType === 'uri_prefix' && $matchValue !== '' && (str_starts_with($uri, $matchValue) || str_starts_with($uriPath, $matchValue))) {
|
||||
return true;
|
||||
}
|
||||
if ($matchType === 'host' && $matchValue !== '' && $host === $matchValue) {
|
||||
@@ -365,8 +367,9 @@ class Waf extends Page implements HasForms, HasTable
|
||||
public function whitelistEntry(array $record): void
|
||||
{
|
||||
$rules = $this->getWhitelistRules();
|
||||
$matchType = 'uri_exact';
|
||||
$matchValue = (string) ($record['uri'] ?? '');
|
||||
$matchType = 'uri_prefix';
|
||||
$rawUri = (string) ($record['uri'] ?? '');
|
||||
$matchValue = $this->stripQueryString($rawUri);
|
||||
if ($matchValue === '') {
|
||||
$matchType = 'ip';
|
||||
$matchValue = (string) ($record['remote_ip'] ?? '');
|
||||
@@ -417,6 +420,16 @@ class Waf extends Page implements HasForms, HasTable
|
||||
->send();
|
||||
}
|
||||
|
||||
protected function stripQueryString(string $uri): string
|
||||
{
|
||||
$pos = strpos($uri, '?');
|
||||
if ($pos === false) {
|
||||
return $uri;
|
||||
}
|
||||
|
||||
return substr($uri, 0, $pos);
|
||||
}
|
||||
|
||||
public function removeWhitelistEntry(array $record): void
|
||||
{
|
||||
$rules = $this->getWhitelistRules();
|
||||
|
||||
@@ -799,7 +799,11 @@ function wafAuditLogList(array $params): array
|
||||
$entry['severity'] = $matches[1];
|
||||
}
|
||||
if (preg_match('/\\[uri "([^"]+)"\\]/', $line, $matches)) {
|
||||
$entry['uri'] = $matches[1];
|
||||
$loggedUri = $matches[1];
|
||||
$currentUri = (string) ($entry['uri'] ?? '');
|
||||
if ($currentUri === '' || (!str_contains($currentUri, '?') && $loggedUri !== '')) {
|
||||
$entry['uri'] = $loggedUri;
|
||||
}
|
||||
}
|
||||
if (preg_match('/\\[hostname "([^"]+)"\\]/', $line, $matches)) {
|
||||
$entry['host'] = $matches[1];
|
||||
@@ -3094,6 +3098,50 @@ function findWafBaseConfig(): ?string
|
||||
return null;
|
||||
}
|
||||
|
||||
function findWafCoreConfig(): ?string
|
||||
{
|
||||
$paths = [
|
||||
'/etc/modsecurity/modsecurity.conf',
|
||||
'/etc/modsecurity/modsecurity.conf-recommended',
|
||||
'/etc/nginx/modsecurity.conf',
|
||||
];
|
||||
|
||||
foreach ($paths as $path) {
|
||||
if (file_exists($path) && isWafBaseConfigUsable($path)) {
|
||||
return $path;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function buildWafCrsIncludeLines(): array
|
||||
{
|
||||
$lines = [];
|
||||
|
||||
if (file_exists('/etc/modsecurity/crs/crs-setup.conf')) {
|
||||
$lines[] = 'Include /etc/modsecurity/crs/crs-setup.conf';
|
||||
} elseif (file_exists('/usr/share/modsecurity-crs/crs-setup.conf')) {
|
||||
$lines[] = 'Include /usr/share/modsecurity-crs/crs-setup.conf';
|
||||
}
|
||||
|
||||
if (file_exists('/etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf')) {
|
||||
$lines[] = 'Include /etc/modsecurity/crs/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf';
|
||||
}
|
||||
|
||||
if (is_dir('/etc/modsecurity/crs/rules')) {
|
||||
$lines[] = 'Include /etc/modsecurity/crs/rules/*.conf';
|
||||
} elseif (is_dir('/usr/share/modsecurity-crs/rules')) {
|
||||
$lines[] = 'Include /usr/share/modsecurity-crs/rules/*.conf';
|
||||
}
|
||||
|
||||
if (file_exists('/etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf')) {
|
||||
$lines[] = 'Include /etc/modsecurity/crs/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf';
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
|
||||
function isModSecurityModuleAvailable(): bool
|
||||
{
|
||||
$output = [];
|
||||
@@ -3186,15 +3234,15 @@ function wafApplySettings(array $params): array
|
||||
}
|
||||
|
||||
ensureWafUnicodeMapFile();
|
||||
$baseConfig = findWafBaseConfig();
|
||||
if (!$baseConfig) {
|
||||
$coreConfig = findWafCoreConfig();
|
||||
if (!$coreConfig) {
|
||||
file_put_contents(JABALI_WAF_INCLUDE, "# Managed by Jabali\nmodsecurity off;\n");
|
||||
return ['success' => false, 'error' => 'ModSecurity base configuration not found'];
|
||||
}
|
||||
|
||||
$rules = [
|
||||
'# Managed by Jabali',
|
||||
'Include "' . $baseConfig . '"',
|
||||
'Include "' . $coreConfig . '"',
|
||||
'SecRuleEngine On',
|
||||
'SecAuditEngine ' . ($auditLog ? 'On' : 'Off'),
|
||||
'SecAuditLog /var/log/nginx/modsec_audit.log',
|
||||
@@ -3207,6 +3255,11 @@ function wafApplySettings(array $params): array
|
||||
$rules = array_merge($rules, $whitelistLines);
|
||||
}
|
||||
|
||||
$crsIncludes = buildWafCrsIncludeLines();
|
||||
if (!empty($crsIncludes)) {
|
||||
$rules = array_merge($rules, $crsIncludes);
|
||||
}
|
||||
|
||||
file_put_contents(JABALI_WAF_RULES, implode("\n", $rules) . "\n");
|
||||
|
||||
$include = [
|
||||
|
||||
Reference in New Issue
Block a user