html-sanitize: Модуль NGINX для санитации HTML 5 с разрешенными элементами, атрибутами и CSS
Установка на Debian/Ubuntu
Эти документы относятся к APT пакету nginx-module-html-sanitize, предоставляемому репозиторием GetPageSpeed Extras.
- Настройте APT репозиторий, как описано в настройке APT репозитория.
- Установите модуль:
sudo apt-get update
sudo apt-get install nginx-module-html-sanitize
Показать дистрибутивы и архитектуры
| Дистрибутив | Версия | Компонент | Архитектуры |
|--------------|------------------|-------------|-----------------|
| debian | bookworm | main | amd64 |
| debian | bookworm-mainline| main | amd64 |
| debian | trixie | main | amd64 |
| debian | trixie-mainline | main | amd64 |
| ubuntu | focal | main | amd64 |
| ubuntu | focal-mainline | main | amd64 |
| ubuntu | jammy | main | amd64 |
| ubuntu | jammy-mainline | main | amd64 |
| ubuntu | noble | main | amd64 |
| ubuntu | noble-mainline | main | amd64 |
Название
ngx_http_html_sanitize_module - Основан на gumbo-parser от Google как парсер HTML5 и katana-parser от hackers-painters как парсер встроенного CSS для санитации HTML с разрешенными элементами, атрибутах и стилях CSS.
Статус
Готов к производству :-)
Пример
Пример конфигурации nginx в соответствии с https://dev.w3.org/html5/html-author/#the-elements:
server {
listen 8888;
location = /sanitize {
# Явно установить кодировку utf-8
add_header Content-Type "text/html; charset=UTF-8";
client_body_buffer_size 10M;
client_max_body_size 10M;
html_sanitize on;
# Проверьте https://dev.w3.org/html5/html-author/#the-elements
# Корневой элемент
html_sanitize_element html;
# Метаданные документа
html_sanitize_element head title base link meta style;
# Скрипты
html_sanitize_element script noscript;
# Секции
html_sanitize_element body section nav article aside h1 h2 h3 h4 h5 h6 header footer address;
# Группировка содержимого
html_sanitize_element p hr br pre dialog blockquote ol ul li dl dt dd;
# Семантика уровня текста
html_sanitize_element a q cite em strong small mark dfn abbr time progress meter code var samp kbd sub sup span i b bdo ruby rt rp;
# Изменения
html_sanitize_element ins del;
# Встраиваемое содержимое
htlm_sanitize_element figure img iframe embed object param video audio source canvas map area;
# Табличные данные
html_sanitize_element table caption colgroup col tbody thead tfoot tr td th;
# Формы
html_sanitize_element form fieldset label input button select datalist optgroup option textarea output;
# Интерактивные элементы
html_sanitize_element details command bb menu;
# Разные элементы
html_sanitize_element legend div;
html_sanitize_attribute *.style;
html_sanitize_attribute a.href a.hreflang a.name a.rel;
html_sanitize_attribute col.span col.width colgroup.span colgroup.width;
html_sanitize_attribute data.value del.cite del.datetime;
html_sanitize_attribute img.align img.alt img.border img.height img.src img.width;
html_sanitize_attribute ins.cite ins.datetime li.value ol.reversed ol.start ol.type ul.type;
html_sanitize_attribute table.align table.bgcolor table.border table.cellpadding table.cellspacing table.frame table.rules table.sortable table.summary table.width;
html_sanitize_attribute td.abbr td.align td.axis td.colspan td.headers td.rowspan td.valign td.width;
html_sanitize_attribute th.abbr th.align th.axis th.colspan th.rowspan th.scope th.sorted th.valign th.width;
html_sanitize_style_property color font-size;
html_sanitize_url_protocol http https tel;
html_sanitize_url_domain *.google.com google.com;
html_sanitize_iframe_url_protocol http https;
html_sanitize_iframe_url_domain facebook.com *.facebook.com;
}
}
Рекомендуется использовать следующую команду для санитации HTML5:
$ curl -X POST -d "<h1>Hello World </h1>" http://127.0.0.1:8888/sanitize?element=2&attribute=1&style_property=1&style_property_value=1&url_protocol=1&url_domain=0&iframe_url_protocol=1&iframe_url_domain=0
<h1>Hello World </h1>
Эта строка запроса element=2&attribute=1&style_property=1&style_property_value=1&url_protocol=1&url_domain=0&iframe_url_protocol=1&iframe_url_domain=0 следуеующая:
- element=2: вывод разрешенного элемента по html_sanitize_element
- attribute=1: вывод любых атрибутов по html_sanitize_attribute
- style_property=1: вывод любых стилей по html_sanitize_style_property
- style_property_value=1: проверка значения стиля для url функции и expression функции, чтобы избежать инъекций XSS по style_property_value
- url_protocol=1: проверка разрешенного url_protocol для абсолютного URL по html_sanitize_url_protocol
- url_domain=0: не проверять домен URL для абсолютного URL
- iframe_url_protocol=1: то же самое, что и url_protocol, но только для
iframe.srcпо html_sanitize_iframe_url_protocol - iframe_url_domain=0: то же самое, что и url_domain, но только для
iframe.srcпо html_sanitize_iframe_url_domain
С помощью ngx_http_html_sanitize_module мы имеем возможность указать, следует ли выводить элементы HTML5, атрибуты и свойства встроенного CSS с помощью directive и querystring следующим образом:
разрешенные элементы
- отключить элемент:
если мы не хотим выводить какой-либо элемент, мы можем сделать это следующим образом:
curl -X POST -d "<h1>h1</h1>" http://127.0.0.1:8888/sanitize?element=0
- включить элемент:
если мы хотим вывести какой-либо элемент, мы можем сделать это следующим образом:
$ curl -X POST -d "<h1>h1</h1><h7>h7</h7>" http://127.0.0.1:8888/sanitize?element=1
<h1>h1</h1><h7>h7</h7>
- включить разрешенный элемент:
если мы хотим вывести разрешенный элемент, мы можем сделать это следующим образом:
$ curl -X POST -d "<h1>h1</h1><h7>h7</h7>" http://127.0.0.1:8888/sanitize?element=1
<h1>h1</h1>
разрешенный атрибут
- отключить атрибут:
если мы не хотим выводить какой-либо атрибут, мы можем сделать это следующим образом:
curl -X POST -d "<h1 ha=\"ha\">h1</h1>" "http://127.0.0.1:8888/sanitize?element=1&attribute=0"
<h1>h1</h1>
- включить атрибут:
если мы хотим вывести какой-либо атрибут, мы можем сделать это следующим образом:
$ curl -X POST -d "<h1 ha=\"ha\">h1</h1>" "http://127.0.0.1:8888/sanitize?element=1&attribute=1"
<h1 ha="ha">h1</h1>
- включить разрешенный атрибут:
если мы хотим вывести разрешенный элемент, мы можем сделать это следующим образом:
$ curl -X POST -d "<img src=\"/\" ha=\"ha\" />" "http://127.0.0.1:8888/sanitize?element=1&attribute=2"
<img src="/" />
разрешенное свойство стиля
- отключить свойство стиля:
если мы не хотим выводить какое-либо свойство стиля, мы можем сделать это следующим образом:
## Это не выведет никакое свойство стиля
curl -X POST -d "<h1 style=\"color:red;\">h1</h1>" "http://127.0.0.1:8888/sanitize?element=1&attribute=1&style_property=0"
<h1>h1</h1>
- включить свойство стиля:
если мы хотим вывести любое свойство стиля, мы можем сделать это следующим образом:
$ curl -X POST -d "<h1 style=\"color:red;text-align:center;\">h1</h1>" "http://127.0.0.1:8888/sanitize?element=1&attribute=1&style_property=1"
<h1 style="color:red;text-align:center">h1</h1>
- включить разрешенное свойство стиля:
если мы хотим вывести разрешенное свойство стиля, мы можем сделать это следующим образом:
$ curl -X POST -d "<h1 style=\"color:red;text-align:center;\" >h1</h1>" "http://127.0.0.1:8888/sanitize?element=1&attribute=1&style_property=2"
<h1 style="color:red;">h1</h1>
Описание
В настоящее время реализация ngx_http_html_sanitize_module основана на gumbo-parser и katana-parser. Мы создаем комбинацию на его основе и запускаем ее на nginx как центральный веб-сервис, поддерживаемый профессиональными специалистами по безопасности с целью устранения языковых различий. Если мы хотим добиться более высокой производительности (здесь бенчмарк), рекомендуется написать библиотеку на языке уровня обертки над чистой C-библиотекой, чтобы преодолеть накладные расходы на сетевую передачу.
Бенчмарк
Тестирование с помощью wrk -s benchmarks/shot.lua -d 60s "http://127.0.0.1:8888" на Intel(R) Xeon(R) CPU E5-2630 v3 @ 2.40GHz и 64GB памяти
| Название | Размер | Средняя задержка | QPS |
|---|---|---|---|
| hacker_news.html | 30KB | 9.06ms | 2921.82 |
| baidu.html | 76KB | 13.41ms | 1815.75 |
| arabic_newspapers.html | 78KB | 16.58ms | 1112.70 |
| bbc.html | 115KB | 17.96ms | 993.12 |
| xinhua.html | 323KB | 33.37ms | 275.39 |
| google.html | 336KB | 26.78ms | 351.54 |
| yahoo.html | 430KB | 29.16ms | 323.04 |
| wikipedia.html | 511KB | 57.62ms | 160.10 |
| html5_spec.html | 7.7MB | 1.63s | 2.00 |
Директива
html_sanitize
синтаксис: html_sanitize on | off
по умолчанию: html_sanitize on
контекст: location
Указывает, включен ли обработчик санитации HTML на контексте локейшн
html_sanitize_hash_max_size
синтаксис: html_sanitize_hash_max_size size
по умолчанию: html_sanitize_hash_max_size 2048
контекст: location
Устанавливает максимальный размер таблиц хешей элементов, атрибутов, стилей, протоколов URL, доменов URL, протоколов URL iframe, доменов URL iframe.
html_sanitize_hash_bucket_size
синтаксис: html_sanitize_hash_bucket_size size
по умолчанию: html_sanitize_hash_bucket_size 32|64|128
контекст: location
Устанавливает размер корзины для элементов, атрибутов, свойств стилей, протоколов URL, доменов URL, протоколов URL iframe, доменов URL iframe. Значение по умолчанию зависит от размера линии кэша процессора.
html_sanitize_element
синтаксис: html_sanitize_element element ...
по умолчанию: -
контекст: location
Установите разрешенные HTML5 элементы, когда включен режим разрешенных элементов, задав строку запроса element:
html_sanitize_element html head body;
html_sanitize_attribute
синтаксис: html_sanitize_attribute attribute ...
по умолчанию: -
контекст: location
Установите разрешенные HTML5 атрибуты, когда включен режим разрешенных элементов, задав строку запроса attribute:
html_sanitize_attribute a.href h1.class;
PS: формат атрибута должен совпадать с element.attribute и поддерживать *.attribute (приставка с "" ) и element.* (суффикс с "" )
html_sanitize_style_property
синтаксис: html_sanitize_style_property property ...
по умолчанию: -
контекст: location
Установите разрешенное свойство CSS, когда включен режим разрешенных элементов, задав строку запроса style_property:
html_sanitize_style_property color background-color;
html_sanitize_url_protocol
синтаксис: html_sanitize_url_protocol [protocol] ...
по умолчанию: -
контекст: location
Установите разрешенные протоколы URL в [linkable attribute], когда URL является абсолютным, а не относительным, и включите проверку протокола URL, задав строку запроса url_protocol:
html_sanitize_url_protocol http https tel;
html_sanitize_url_domain
синтаксис: html_sanitize_url_domain domain ...
по умолчанию: -
контекст: location
Установите разрешенные домены URL в [linkable attribute], когда URL является абсолютным, а не относительным, и включите проверку протокола URL и домена URL, задав строки запроса url_protocol и url_domain:
html_sanitize_url_domain *.google.com google.com;
html_sanitize_iframe_url_protocol
синтаксис: html_sanitize_iframe_url_protocol [protocol] ...
по умолчанию: -
контекст: location
То же самое, что и html_sanitize_url_protocol, но только для атрибута iframe.src
html_sanitize_iframe_url_protocol http https tel;
html_sanitize_iframe_url_domain
синтаксис: html_sanitize_iframe_url_domain [protocol] ...
по умолчанию: -
контекст: location
То же самое, что и html_sanitize_url_domain, но только для атрибута iframe.src
html_sanitize_iframe_url_domain *.facebook.com facebook.com;
linkable_attribute
Разрешенные атрибуты:
- a.href
- blockquote.cite
- q.cite
- del.cite
- img.src
- ins.cite
- iframe.src
- CSS URL функция
Querystring
Строка запроса из URL запроса используется для управления внутренними действиями ngx_http_html_sanitize_module.
document
значение: 0 или 1
по умолчанию: 0
контекст: querystring
Указывает, следует ли добавлять <!DOCTYPE> к телу ответа
html
значение: 0 или 1
по умолчанию: 0
контекст: querystring
Указывает, следует ли добавлять <html></html> к телу ответа
script
значение: 0 или 1
по умолчанию: 0
контекст: querystring
Указывает, разрешено ли использование <script></script>
style
значение: 0 или 1
по умолчанию: 0
контекст: querystring
Указывает, разрешено ли использование <style></style>
namespace
значение: 0, 1 или 2
по умолчанию: 0
контекст: querystring
Указывает режим gumbo-parser со следующими значениями:
- GUMBO_NAMESPACE_HTML: 0
- GUMBO_NAMESPACE_SVG: 1
- GUMBO_NAMESPACE_MATHML: 2
context
значение: [0, 150)
по умолчанию: 38(GUMBO_TAG_DIV)
контекст: querystring
Указывает контекст gumbo-parser со значениями из этого файла tag_enum.h
element
значение: 0, 1, 2
по умолчанию: 0
контекст: querystring
Указывает режим вывода элемента со следующими значениями:
- 0: не выводить элемент
- 1: выводить все элементы
- 2: выводить разрешенные элементы
attribute
значение: 0, 1, 2
по умолчанию: 0
контекст: querystring
Указывает режим вывода атрибута со следующими значениями:
- 0: не выводить атрибуты
- 1: выводить все атрибуты
- 2: выводить разрешенные атрибуты
style_property
значение: 0, 1, 2
по умолчанию: 0
контекст: querystring
Указывает режим вывода CSS свойства со следующими значениями:
- 0: не выводить CSS свойства
- 1: выводить все CSS свойства
- 2: выводить разрешенные CSS свойства
style_property_value
значение: 0, 1
по умолчанию: 0
контекст: querystring
Указывает режим вывода значения свойства CSS со следующими значениями:
- 0: не проверять значение CSS свойства
- 1: проверять значение CSS свойства для функции URL и функции expression от IE, чтобы избежать инъекций XSS
url_protocol
значение: 0, 1
по умолчанию: 0
контекст: querystring
Указывает, следует ли проверять протокол URL в linkable_attribute. Значение следующее:
- 0: не проверять протокол URL
- 1: выводить разрешенный протокол URL
url_domain
значение: 0, 1
по умолчанию: 0
контекст: querystring
Указывает, следует ли проверять домен URL в linkable_attribute, когда включена проверка url_protocol. Значение следующее:
- 0: не проверять домен URL
- 1: выводить разрешенный домен URL
iframe_url_protocol
значение: 0, 1
по умолчанию: 0
контекст: querystring
То же самое, что и url_protocol, но только для iframe.src
iframe_url_domain
значение: 0, 1
по умолчанию: 0
контекст: querystring
То же самое, что и url_domain, но только для iframe.src