From f83b5d9fa40af6ee6ecc7fdece3d43dd99b81a78 Mon Sep 17 00:00:00 2001 From: lacatoire Date: Mon, 31 Aug 2026 14:04:30 +0200 Subject: [PATCH] taint: revise the extension documentation --- reference/taint/book.xml | 65 ++-- reference/taint/configure.xml | 47 ++- reference/taint/detail.xml | 375 ++++++++++------------- reference/taint/functions/is-tainted.xml | 56 +++- reference/taint/functions/taint.xml | 88 +++++- reference/taint/functions/untaint.xml | 82 ++++- reference/taint/ini.xml | 79 +++-- reference/taint/reference.xml | 2 +- reference/taint/setup.xml | 31 +- 9 files changed, 507 insertions(+), 318 deletions(-) diff --git a/reference/taint/book.xml b/reference/taint/book.xml index dfd229511c..15c0b76631 100644 --- a/reference/taint/book.xml +++ b/reference/taint/book.xml @@ -1,61 +1,63 @@ - + - - Модуль определения «грязных» строк Taint + Taint Taint &reftitle.intro; - - Taint — модуль определения XSS-кодов — вредоносных, или «грязных» строк (англ. tainted strings). - Модуль также помогает выявлять попытки внедрения SQL-инъекций, - shell-инъекций и т. д. - - - Модуль выдаст предупреждение при передаче в отдельные функции подозрительной строки, - которую получили из суперглобальных переменных $_GET, - $_POST или $_COOKIE. - + + Taint — модуль для обнаружения XSS-кода, то есть заражённых строк. + Модулем также выявляют SQL-инъекции, инъекции команд, инъекции путей + к файлам и похожие уязвимости. + + + Когда модуль taint включили, строки, которые пришли из пользовательского + ввода — $_GET, $_POST + и $_COOKIE, — помечаются как заражённые при запуске + запроса, и метка отслеживается через строковые операции. Когда заражённая + строка попадает в опасный приёмник — вывод, SQL-запрос, команду оболочки, + путь к файлу и так далее, — taint поднимает предупреждение, которое + указывает на это место. Полные списки приводит раздел + «Распространение и проверяемые приёмники». + + + Taint — инструмент разработки и аудита, а не средство защиты во время + выполнения: он только сообщает о возможных проблемах и никогда не блокирует + и не изменяет данные. Модуль намеренно осторожен и иногда сообщает лишнее, + поэтому чистый прогон означает лишь «taint ничего не увидел», но никогда — + «доказано безопасно». В производственной среде модуль не включают. + - Пример определения вредоносных строк функцией <function>taint</function> + Пример работы модуля Taint ]]> &example.outputs.similar; @@ -66,6 +68,7 @@ Warning: mysql_query() [function.mysql-query]: SQL statement contains data that &reference.taint.reference; + +
&reftitle.install; - + &pecl.info; - &url.pecl.package;taint + &url.pecl.package;taint. + + + + Модуль устанавливают через PECL: + + + + + + + + + Исходный код размещается на + GitHub. Чтобы собрать + модуль из исходного кода: + + + + + Затем модуль включают, добавив в файл &php.ini; строку + extension=taint.so (или + extension=php_taint.dll в ОС Windows) и установив + директиве taint.enable + значение 1. + + + + Taint — инструмент разработки и аудита. Его не включают в производственной + среде: инструментирование замедляет каждый запрос и отключает JIT + в OPcache, а предупреждения переносят данные запроса в журналы. + +
+ - Дополнительные подробности + Распространение и проверяемые приёмники
- Функции и операторы, которые могут распространять сомнительный символ - испорченной строки + Как распространяется метка заражённости + + Метка заражённости — один бит, который хранят на самой строке, а не + на переменной. Присваивание, передача и любое другое совместное + использование заражённой строки сохраняют метку. Конкатенация строк + и интерполяция тоже её распространяют: + - - - - - - - Функция/Оператор - Мин. версия - - + Операторы, которые распространяют метку заражённости + - = (присваивание) - 0.1.0 - - - . (конкатенация) - 0.1.0 - - - "{$var}" (подстановка переменных) - 0.1.0 - - - .= (присваивание с конкатенацией) - 0.1.0 - - - strval - 0.3.0 - - - explode/split - 0.3.0 + = (присваивание, включая list() и деструктуризацию массива) - implode/join - 0.3.0 + . (конкатенация) - sprintf - 0.3.0 + .= (присваивание с конкатенацией) - vsprintf - 0.3.0 - - - trim - 0.4.0 + "{$var}" (интерполяция строк, включая быстрый путь ROPE) + + +
+
+ + Кроме того, taint знает фиксированный набор строковых функций: когда + какой-нибудь из значимых строковых аргументов заражён, возвращаемая строка + тоже помечается как заражённая. Охватываются и обычный вызов, и — начиная + с PHP 8.4 — вызов по быстрому безкадровому пути. + + + + Функции, которые распространяют метку заражённости + + - rtrim - 0.4.0 + trim, rtrim, ltrim - ltrim - 0.4.0 + substr, strstr - strstr - 0.5.0 + str_replace, str_ireplace - str_pad - 0.5.0 + str_pad, strtolower, strtoupper, strval - str_replace - 0.5.0 + explode (каждый элемент получившегося массива) - substr - 0.5.0 + implode/join (заражённый разделитель тоже заражает результат) - strtolower - 0.5.0 + sprintf, vsprintf (метку несёт только спецификатор %s; вызов sprintf("%d", $t) возвращает чистую строку) - strtoupper - 0.5.0 + dirname, basename, pathinfo
+ + Каждая функция, которую taint не понимает явно, возвращает новую строку + без метки — включая вспомогательные функции экранирования вроде + htmlspecialchars, htmlentities + или mysqli_real_escape_string. Так сделали намеренно: + taint скорее сообщит лишнее, чем возьмётся решать, «безопасно» ли значение + для конкретного контекста вывода. Чтобы снять метку со значений, которые + проверили самостоятельно, вызывают функцию untaint. +
-
- Функции и операторы, которые проверяют испорченные строки +
+ Где taint поднимает предупреждения + + Когда заражённая строка попадает в один из приёмников ниже, taint поднимает + предупреждение — по умолчанию уровня E_USER_WARNING; + уровень настраивают директивой + taint.error_level. + Проверяются только строковые аргументы верхнего уровня; вывод массива, + который лишь содержит заражённые значения, предупреждения не вызывает. + - + Приёмники вывода - - - - Функция/Оператор - Мин. версия - + ПриёмникЧто проверяют - Основные выражения - - - eval - 0.1.0 - - - include/include_once - 0.1.0 - - - require/require_once - 0.1.0 - - - - - Функции вывода - - - echo - 0.1.0 - - - print - 0.1.0 - - - printf - 0.1.0 - - - file_put_contents - 0.1.0 - - - - Функции файловой системы - - - fopen - 0.2.0 - - - opendir - 0.2.0 - - - basename - 0.2.0 - - - dirname - 0.2.0 - - - file - 0.2.0 - - - pathinfo - 0.2.0 + echo, print + выражение, которое выводят - - Соответствующие функции базы данных + printf, vprintf + строку формата и подставляемые значения - mysql_query - 0.2.0 + print_r, var_dump, var_export + значение, которое выводят, если это строка - mysqli_query/MySQLi::query - 0.2.0 + exit/die с сообщением + сообщение - sqlite_query/SqliteDataBase::query - 0.3.0 - - - sqlite_single_query/SqliteDataBase::singleQuery - 0.3.0 - - - oci_parse - 0.3.0 + file_put_contents, fwrite, fputs в php://output + данные, которые записывают + + +
+
+ + + Приёмники файловой системы + + + ПриёмникЧто проверяют + + - PDO::query - 0.3.0 + fopen, opendir, unlink + путь - PDO::prepare - 0.3.0 + file, readfile, file_get_contents, highlight_file/show_source + путь - SQLite3::query - 2.0.1 + copy, rename, move_uploaded_file + и исходный путь, и путь назначения - SQLite3::prepare - 2.0.1 + mkdir, rmdir, touch + путь - - Соответствующие функции командной строки + include, include_once, require, require_once + путь к файлу + + +
+
+ + + SQL-приёмники + + + ПриёмникЧто проверяют + + - system - 0.1.0 + mysqli_query, mysqli_prepare, mysqli_real_query, mysqli_multi_query + строку запроса - exec - 0.1.0 + mysql_query, sqlite_query, sqlite_single_query, oci_parse, pg_query, pg_send_query + строку запроса - proc_open - 0.1.0 + mysqli::query, mysqli::prepare, mysqli::real_query, mysqli::multi_query + строку запроса - passthru - 0.1.0 + PDO::query, PDO::prepare, PDO::exec + строку запроса - shell_exec - 0.3.0 + SQLite3::query, SQLite3::prepare, SQLite3::exec, SQLiteDatabase::query, SQLiteDatabase::singleQuery + строку запроса - -
-
- -
- Функции, которые не будут обрабатывать испорченную строку - + Приёмники выполнения команд - - - - Функция/Оператор - Мин. версия - + ПриёмникЧто проверяют - addslashes - 0.1.0 - - - addcslashes - 0.1.0 + exec, system, passthru, shell_exec (включая оператор «обратный апостроф») + строку команды - htmlspecialchars - 0.1.0 + proc_open, popen + строку команды - htmlentities - 0.1.0 + eval + код, который выполняют - escapeshellcmd - 0.1.0 + динамические вызовы вроде $func(), $obj->$method(), call_user_func, вызываемые массивы + название функции, метода или класса, которое разрешают - mysql_escape_string - 0.1.0 - - - mysql_real_escape_string - 0.1.0 + preg_match, preg_match_all, preg_replace, preg_split, preg_grep, preg_replace_callback + шаблон, а для функции preg_replace_callback ещё и название функции обратного вызова + + +
+
+ + + Приёмники заголовков и cookie + + + ПриёмникЧто проверяют + + - mysqli_escape_string/MySQLi::escape_string - 0.1.0 + header + строку заголовка - mysqli_real_escape_string/MySQLi::real_escape_string - 0.1.0 + setcookie, setrawcookie + название и значение cookie + + +
+
+ + + Прочие приёмники + + + ПриёмникЧто проверяют + + - sqlite_escape_string/SqliteDataBase::escapeString - 0.3.0 + unserialize + сериализованную строку - PDO::quote - 0.3.0 + mail + получателя, тему, дополнительные параметры и дополнительные заголовки; тело письма — это содержимое, и его не проверяют
- + + Предупреждения следуют формату + function_name() [sink]: message, где + sink определяет проверяемую операцию — например, + echo, include или название функции, — + а сообщение описывает, что признали возможно заражённым. +
+ + + is_tainted - Проверяет, испорчена ли строка + Проверяет, заражена ли строка @@ -14,10 +14,11 @@ boolis_tainted stringstring - - Проверяет, является ли строка испорченной - - + + Функция проверяет, несёт ли переданное значение метку заражённости. + Заражёнными бывают только строки; для любого другого типа функция + возвращает &false;. + @@ -26,9 +27,9 @@ string - - - + + Значение, которое требуется проверить. + @@ -36,13 +37,46 @@ &reftitle.returnvalues; + + Функция возвращает &true;, если значение — заражённая строка, + иначе — &false;. Функция всегда возвращает &false;, когда директиву + taint.enable выключили. + + + + + &reftitle.examples; + + Пример использования функции <function>is_tainted</function> + + +]]> + + &example.outputs.similar; + + + + + + + + &reftitle.seealso; - Возвращает &true;, если строка испорчена или &false; в противном случае. + + taint + untaint + - + + taint - Испортить строку + Помечает строки как заражённые @@ -13,11 +13,21 @@ booltaint stringstring - stringstrings + stringstrings - - Делает строку испорченной строку. Используется в целях отладки. - + + Функция вручную помечает переданные строки как заражённые, как если бы они + пришли из пользовательского ввода. Переменные передают по ссылке, но саму + метку хранят на строке, а не на переменной: заражёнными сразу становятся + все переменные, которые делят одну и ту же строку. + + + В основном функция пригождается для тестирования и для имитации + пользовательского ввода в CLI-скриптах, где суперглобальные переменные + $_GET, + $_POST и + $_COOKIE не заполняются. + @@ -26,16 +36,17 @@ string - - - + + Переменная со строкой, которую требуется пометить. + strings - - + + Дополнительные переменные, которые требуется пометить. + @@ -43,14 +54,63 @@ &reftitle.returnvalues; + + Функция всегда возвращает &true;. Когда директиву + taint.enable выключили, функция + ничего не делает и всё равно возвращает &true;. + + + + + &reftitle.examples; + + Пример использования функции <function>taint</function> + + +]]> + + &example.outputs.similar; + + + + + + + + &reftitle.notes; + + + Помечаются только непустые строки; переменные с другими типами + и пустые строки молча пропускаются. + + + + + Интернированные, постоянные и неизменяемые строки — строковые литералы, + разделяемые строки OPcache — метку нести не могут и молча пропускаются. + + + + + + &reftitle.seealso; - Возвращает &true;, если преобразование строки выполнено. - Всегда возвращает &true;, если модуль taint не включён. + + untaint + is_tainted + - + + untaint - Исправить строку + Снимает со строк метку заражённости @@ -13,11 +13,17 @@ booluntaint stringstring - stringstrings + stringstrings - - Исправляет испорченную строку - + + Функция снимает метку заражённости с переданных строк. + + + Метку хранят на самой строке, а не на переменной, поэтому функция снимает + её сразу для всех переменных, которые делят одну и ту же строку. Функцию + применяют, чтобы занести в белый список значения, которые проверили + самостоятельно, например после строгой проверки по списку разрешённых. + @@ -26,17 +32,17 @@ string - - - + + Переменная со строкой, которую требуется очистить. + strings - - - + + Дополнительные переменные, которые требуется очистить. + @@ -44,13 +50,61 @@ &reftitle.returnvalues; - + + Функция всегда возвращает &true;. Когда директиву + taint.enable выключили, функция + ничего не делает и всё равно возвращает &true;. + + - + + &reftitle.examples; + + Пример использования функции <function>untaint</function> + + +]]> + + &example.outputs.similar; + + + + + + &reftitle.notes; + + + Метку могут нести только строковые значения; передача значения + другого типа ничего не делает. + + + + + + &reftitle.seealso; + + + taint + is_tainted + + + + +
@@ -26,7 +26,7 @@ taint.error_level - E_WARNING + 512 (E_USER_WARNING) INI_ALL @@ -40,32 +40,61 @@ - - taint.enable - int - - - - Включён ли модуль. - - - - - - taint.error_level - int - - - - Тип ошибки, который будет возвращать модуль при обнаружении - подозрительной строки. - - - - + + taint.enable + bool + + + + Главный переключатель. Когда директиву включили, taint перехватывает + исполнитель и помечает строки из $_GET, + $_POST и $_COOKIE как заражённые + при запуске запроса. + + + Директиву задают только в файле &php.ini;: её включение требует + перезапуска процесса, поэтому переключать её на каждый запрос + или на каждый каталог нельзя. + + + + Директиву не включают в производственной среде: инструментирование + замедляет каждый запрос и несовместимо с JIT в OPcache. + + + + + + + taint.error_level + int + + + + Уровень ошибки, который taint применяет, когда сообщает о возможно + заражённой строке. Значение по умолчанию — + E_USER_WARNING (512). + + + Поскольку директива относится к режиму INI_ALL, + её изменяют во время выполнения. Например, чтобы заглушить + предупреждения taint для текущего скрипта: + + + + +]]> + + + +
+ + diff --git a/reference/taint/setup.xml b/reference/taint/setup.xml index 5852b6f6aa..f203b58026 100644 --- a/reference/taint/setup.xml +++ b/reference/taint/setup.xml @@ -1,25 +1,36 @@ - + &reftitle.setup; -
- &reftitle.install; - - &pecl.moved; - - - &pecl.info; - &url.pecl.package;taint. - +
+ &reftitle.required; + + Для работы Taint 3.x требуется PHP 8.0 или новее. Для PHP 7.x берут + выпуски taint 2.1.x, а для PHP 5.x — выпуски taint 1.x. +
+ + &reference.taint.configure; + + &reference.taint.ini; +
+ &reftitle.resources; + + Модуль Taint не определяет типов ресурсов. Саму метку заражённости хранят + во внутренней структуре zend_string, а не в ресурсе, + который виден пользователю. + +
+ +