Вместо того, чтобы использовать web.config
для своих правил переписывания, я использовалГеликон АПЭдля эмуляции функции Apache .htaccess
.
У меня есть большой универсальный .htaccess
файл, который применяется на всем сервере как часть функции ограничения доступа к передаваемым командам, таким как union, delete и т. д.
Однако я столкнулся с проблемой, когда строка кода создает ложное срабатывание и блокирует доступ к корректному URL-адресу.
URL-адрес, по которому произошел сбой:http://example.com/union-contracts
Используя приведенную ниже команду в web.config
, все отсутствующие URL-адреса переносятся в index.php
.
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" path="/index.php" responseMode="ExecuteURL" />
</httpErrors>
правило htaccess, которое возвращает 403
RewriteCond %{QUERY_STRING} (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode) [NC]
RewriteRule . - [F,L]
В конечном счете, я хотел бы продолжить блокировать union, например, мне просто нужно изменить строку для ложных срабатываний. Обратите внимание, что я не ищу, чтобы это -contracts
было жестко закодировано в моем .htaccess
правиле.
Мне удалось воспроизвести проблему в htaccess в XAMPP, вспомнив, как изначально генерируется URL.
На стороне посетителя веб-сайта при доступе к URL-адресу сервер генерирует ошибку 404. Я отфильтровываю URL-адрес, оставляя только последнюю часть, и проверяю базу данных по этой строке, чтобы увидеть, соответствует ли она сохраненному URL-адресу. Если это так, я не передаю эту ошибку 404 браузеру, она передается только в том случае, если URL-адрес не может быть найден.
Когда IIS выдает ошибку 404, URL-адрес становится следующим:
index.php?404;http://example.com:80/union-contracts
Но в этом формате он не передается в браузер.
решение1
Я выразил в комментариях свою обеспокоенность тем, что, должно быть, происходит «что-то еще», но в любом случае...
Трудно написать исключение для правила, которое не должно (читай: "не может") срабатывать изначально - это сплошные догадки. В конце концов, почему быисключениебыть удостоенным чести?
Это правило уже должно избегать данного запроса по нескольким «важным» причинам:
- Запрос не содержит строку запроса.
- Регулярное выражение в условии (CondPattern) не соответствует ни одной части URL (даже если она была в строке запроса).
Учитывая пункт 2 выше, регулярное выражение уже содержит достаточное исключение, чтобы не соответствовать данному запросу, так как же мы можем реализовать «другое» исключение?
Вы можете изменитьCondPatternчтобы избежать случаев, когда дефис ( -
) следует за словом «союз», используйтеотрицательный просмотр вперед. Например:
(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union(?!-)|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)
Итак, приведенное выше соответствует Xunion
, но не соответствует Xunion-
, где X
находится одна из последовательностей символов из первогочередованиегруппа (т.е. (;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00)
).
Или, когда дефис следует за любым из этих ключевых слов:
(;|<|>|'|"|\)|%0A|%0D|%22|%27|%3C|%3E|%00).*(/\*|union|select|insert|drop|delete|update|cast|create|char|convert|alter|declare|order|script|set|md5|benchmark|encode)(?!-)
(ОБНОВЛЯТЬ:Следующие два предложения, вероятно, не сработают, поскольку, по-видимому, директивы обрабатываются толькопослеIIS уже переписал URL. В этот момент URL-путь просто /index.php
, а не /union-contracts
.)
Или измените RewriteRule
так, чтобы он не совпадал, когда URL-путь начинается с /union-
(хотя это потенциально создает бэкдор для попытки XSS, которую правило пытается заблокировать). Например:
RewriteRule !^/?union- - [F]
(По крайней мере, в Apache L
при использовании флага этот флаг не требуется F
— он подразумевается.)
В качестве альтернативы вы можете создать еще одно правиловершина, перед вашими существующими правилами, что создает исключение при запросе URL, который начинается /union-
и не имеет строки запроса (хотя это может показаться противоречием, если верить другому правилу). Например:
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^/?union- - [L]
Однако это потенциально может «сломать» запрос, если далее в файле есть другие правила, которым необходимо каким-либо образом переписать URL, поскольку этого не произойдет.
Я предполагаю, что Helicon-APE/mod_rewrite работает вкаталог-подобныйконтекст (например, .htaccess
синтаксис стиля в отличие отсервериливиртуальныйхостконтекст)? Хотя это не должно влиять на директивы выше, как это и происходит.
ОБНОВЛЯТЬ:Когда IIS выдает ошибку 404, URL-адрес становится следующим:
index.php?404;http://example.com:80/union-contracts
Ах, да! Этот URLволяпопадают в исходное состояние. Так что, похоже, директивы mod_rewrite обрабатываютсяпослеIIS "переписать" в web.config! Это делает эти директивы "безопасности" несколько излишними или даже неправильными, поскольку онипредполагаемыйдля запуска по первоначальному запросу клиента. И....
Я отфильтровываю URL-адрес, оставляя только последнюю часть, и проверяю базу данных по этой строке, чтобы увидеть, соответствует ли она сохраненному URL-адресу.
Поскольку вы активно анализируете URL-адрес и отфильтровываете только нужную вам часть, то эти проверки «безопасности» кажутся излишними в любом случае, по крайней мере, для этих запросов «404». (На самом деле, в зависимости от реальных файлов (т. е. не запросов 404), которые потенциально могут быть запрошены напрямую, может ли вредоносная строка запроса такого рода реально представлять угрозу безопасности для любого URL-адреса?)
Два предложения выше по изменению регулярного выражения всостояниечтобы исключить случаи, когда дефис следует за ключевым словом «union», илилюбойключевое слово, все еще применимо здесь и, по-видимому, решает непосредственную проблему.
Вы также можете отменить все проверки, когда встречается URL-адрес такой формы index.php?404;
(т. е. после того, как он был перезаписан IIS). (Я предполагаю, что все ваши директивы mod_rewrite — это аналогичные проверки «безопасности»?)
Например, добавьте следующее ввершинасценария .htaccess
,досуществующие директивы:
RewriteCond %{QUERY_STRING} ^404;
RewriteRule ^/?index\.php - [L]
Это должно предотвратить дальнейшую обработку при обнаружении URL-адреса формы /index.php?404;......
. (Поскольку вы в любом случае анализируете URL-адрес в своем скрипте.)