Простейшие методы XSS защиты

В мире веб разработки очень важно рассматривать свой код с точки зрения безопасности от взлома и инъекций.

Особенно если это работа с web запросами и(или) куками
Особенно если есть работа и запись в базу данных
Особенно если проект работает с деньгами

Работу (особенно эту “рутину”) облегчают фреймворки. В любом современной фреймворке есть методы очищающие или защищающие параметры запроса от инъекций или вредоносного кода. Их преимущества в универсальности. Их недостатки в производительности.

Кстати, один из видов вредоносного вектора атаки — это эксплуатировать время очистки параметров от скриптов (для упрощения будем называть это XSS). Т.е., злоумышленник посылает множество запросов в ту область которая будет долго обрабатывать запросы и тормозить сервер. Ведь под капотом стандартных методов защиты от XSS различные сложные регулярные выражения с заменами.

Альтернативой являются простейшие методы защиты от XSS, там, где это применимо

  1. Приведение к простейшему типу.
    Если мы знаем, что получаемый GET параметр должен быть целочисленным — мы просто можем привести его к целочисленному перед дальнейшем обработкой или же отклонять запросы, если этот параметр не целочисленный.
    Так же можно поступать, если, например, мы знаем, что получаемый параметр может принимать только определенные значения.
$cleanParam = (int)$_GET["dirtyParam"];
  1. Простые регулярные выражения, заточенные под получаемый параметр
    Обрабатываемый параметр может, например, состоять только из цифр и букв английского алфавита. Незачем “прогонять” его по всем кругам регулярно стандартной защиты от XSS. Можно написать простую регулярку.
if( preg_match("/^[a-zA-Z\d]+$/", $_COOKIE["dirtyParam"]) )

MySQL — проблема запросов с limit и offset к очень большим таблицам и ее решение

Представим, что у нас есть таблица пользователей (users) или заказов (orders) на десятки миллионов записей и больше. И у нас стоит задача их перебора в любом контексте.

Я представляю себе это в виде цикла, в котором порционно забираем разумное количество записей, что-то вроде:

select * from users order by id limit 1000 offset 0;

Такой запрос выполняется очень быстро, моментально.

Рано или поздно мы приходим к offset, например 40 млн:

select * from users order by id limit 1000 offset 40000000;

И тут запрос может выполняться несколько минут.

Происходит это из-за того, что mysql не может гарантировать, что все элементы будут на своих порядковых местах, ведь может так статься, что элемент 40 000 099 был ранее удален и алгоритмам приходится сканировать все 40 млн элементов для получения выборки.

Решением этой проблемы может стать видоизменение запроса из limit-offset на where-limit:

 select * from users where id > 40000000 order by id limit 1000;

Выполняется моментально!

И даже, если не все элементы гарантированно присутствуют в таблице, айдишник для where легко «вытащить» из предыдущего запроса в цепочке.