Эта заметка – вольный перевод статьи Stefan Esser MySQL and SQL Column Truncation Vulnerabilities. SQL-инъекции (SQL-injection) на сегодняшний день остаются наиболее обсуждаемыми проблемами безопасности web приложений. В тоже время, другие уязвимости SQL запросов, например, связанные со слишком длинными входными данными, обычно игнорируются, хотя могут привести ко всем видам проблем безопасности. Первая уязвимость касается движка MySQL В MySQL существует параметр, который называется max_packet_size. По-умолчанию ему присвоено значение 1МБ. Он контролирует максимальный размер пакетов, которые передаются между SQL клиентом и сервером. Если запросы или результат их выполнения не укладывается в размер пакета – возникает ошибка. Это означает, что слишком длинные SQL запросы никогда не отправляются серверу и, таким образом, никогда не выполняются. Это может привести к проблемам безопасности, если хакер может передать большие блоки данных, которые потом используются в SQL запросах. Например, представьте запросы авторизации, которые объединяют информацию из HTTP заголовков, id сессий и логов. В результате получается большой запрос, который не укладывается в размер пакета. Еще один пример – очистка таблицы сессий, при которой сначала создается PHP массив из всех сессий, которые соответствуют определенным параметрам, после этого выполняется очистка, а в конце создается один большой запрос на удаление со всеми id выбранных сессий. Очевидно, что такой запрос может стать слишком длинным. Таким образом, web разработчики должны всегда проверять длину запросов. И тут не играет роли, каким образом выполняется подготовка запроса.
Вторая уязвимость касается длины столбцов. Если не проверять длину данных, полученных от пользователя, может возникнуть уязвимость, связанная с отбрасыванием части данных при вставке в таблицу (в оригинале – SQL Column Truncation Vulnerabilities). По-умолчанию MySQL обрезает строки, длина которых превышает максимальную длину столбца и при этом отправляет только предупреждение (warning). Обычно web приложение эти предупреждения не видит и, соответственно, не обрабатывает их. В MySQL можно активировать режим sql_mode STRICT_ALL_TABLES чтобы превратить эти предупреждения в ошибки (errors). Но большинство web приложений работают на серверах, запущенных в обычном режиме. Таким образом, необходима проверка длины данных, полученных от пользователя. Например, представьте такую ситуацию. 1) web приложение представляет собой форум; 2) имя администратора известно, например, «admin»; 3) MySQL работает в обычном режиме; 4) в приложении отсутствует ограничение на длину имени пользователя; 5) длина поля в базе данных равна 16-ти символам. Хакер может попытаться зарегистрироваться под именем «admin » (с пробелом в конце), но это ему не удастся, если выполняется проверка на существование такого имени. Дело в том, что MySQL не сравнивает данные в двоичном режиме. По-умолчанию используется более гибкая система проверок. При которой пробелы в конце строк отбрасываются. Это означает, что строки «admin» «admin » равны. Т. е. запрос