[SendIt 2.5.0] Дополнительная защита от SQL-инъекций

Приветствую! Если коротко, то с версии 2.5.0 компонент принудительно прогоняет все поступающие с фронта данные через паттерн для очистки о возможных SQL-инъекций. Чуть подробнее под катом

В целом, я надеюсь что вы используете для формирования запросов к базе данных методы класса xPDOQuery. Предполагается, что там уже есть защита от SQL-инъекций, но безопасности не бывает много. В связи с этим я добавил класс Sanitazer с одним единственным методом process для обработки данных.

Паттерн по которому происходит фильтрация выглядит так
private const DANGEROUS_PATTERNS = [
        '/\b(SELECT|INSERT|UPDATE|DELETE|DROP|UNION|EXEC|EXECUTE|TRUNCATE|ALTER|CREATE|SHOW|DESCRIBE|GRANT|REVOKE|COMMIT|ROLLBACK|MERGE|CALL)\b/i',
        '/;.*--/',
        '/\/\*.*\*\//',
        '/--\s+/',
        '/#.*$/',
        '/WAITFOR\s+DELAY/i',
        '/XP_/i',
        '/sp_/i',
        '/@@/',
        '/@\w+/',
        '/CHAR\(\d+\)/',
        '/0x[0-9A-Fa-f]+/',
        '/BENCHMARK\(/i',
        '/SLEEP\(/i',
        '/LOAD_FILE\(/i',
        '/INTO\s+(OUTFILE|DUMPFILE)/i',
        '/CONCAT_WS\(/i',
        '/GROUP_CONCAT\(/i',
        '/INFORMATION_SCHEMA/i',
        '/sys\./i',
        '/pg_/i'
    ];
Придумал его Deepseek, так что все претензии к нему)))
Входе испытаний было выявлено, что данный паттерн портит адреса электронной почты, поэтому значения похожие на них были исключены из проверки следующим образом
if(preg_match(self::EMAIL_REGEXP, $input)){
    return $input;
}
И конечно же, чтобы вы, дорогие коллеги, могли творить любую дичь, было добавлено событие senditOnSetValue, в котором можно оставить исходное значение или сделать дополнительные проверки, или исключить отдельные поля из проверки.

Спасибо за внимание!
Артур Шевченко
13 сентября 2025, 17:54
modx.pro
380
+2
Поблагодарить автора Отправить деньги

Комментарии: 5

Александр Туниеков
17 сентября 2025, 21:41
0
Безопасность MODX для меня не слишком понятная тема. Когда то искал как безопасно писать запросы в базу. Нашел только приводить к инт все id получаемые с фронта. И плюс вырезать из получаемого с фронта теги MODX и fenom. Было бы интересно увидеть разбор безопасности MODX, при запросах в базу. И увидеть примеры атак, чтобы знать от чего защищаться.
    Артур Шевченко
    17 сентября 2025, 21:46
    0
    Я тоже далеко не специалист в безопасности, но точно знаю, что надо валидировать пользовательский ввод, поэтому и добавил этот функционал в SendIt.
      Александр Туниеков
      17 сентября 2025, 22:53
      0
      К сожалению, не понимая думаю можно наделать других дырок. Попробовал проверить на уязвимость из https://habr.com/ru/articles/130826/ .

      Вроде не уязвимо :-). Почти все через pdoFetch идет. Только иногда использую сложное условие вроде (id IN (2,3) and (parent = 4 or parent IS NULL)) в where. Тогда… хм. проверю :-).

      Код для проверки:
      <?php
      $pdo = $modx->getService('pdoFetch');
      $id = $_GET['id'];
      $pdo->setConfig([
          'class'=>'modResource',
          'where'=>[
              0=>"(id = $id and (parent = 4 or parent = 0))"
          ],
          'limit'=>0,
          'return'=>'data'
      ]);
      
      $ress = $pdo->run();
      foreach($ress as $res){
          echo "<p>{$res['id']}</p>";
      }
      echo '<pre>'.$pdo->getTime().'</pre>';
      На запрос gettables.ru/test.html?id=4+OR+1 выдало:
      1
      
      2
      
      3
      
      4
      
      5
      
      6
      
      7
      
      14
      
      16
      
      19
      
      20
      
      21
      
      22
      
      25
      
      30
      
      0.0000529: xPDO query object created
      0.0000019: Processed additional conditions
      0.0000720: Added where condition: 0=(id = 4 OR 1 and (parent = 4 or parent = 0))
      0.0000749: Sorted by modResource.id, ASC
      0.0002530: SQL prepared "SELECT * FROM `modx_site_content` AS `modResource` WHERE (id = 4 OR 1 and (parent = 4 or parent = 0)) ORDER BY modResource.id ASC "
      0.0014510: SQL executed
      0.0000789: Rows fetched
      0.0000720: Returning raw data
      0.0167792: Total time
      4 194 304: Memory usage
      Выдало все id страниц. То есть
      'where'=>[
              0=>"(id = $id and (parent = 4 or parent = 0))"
          ],
      Уязвимо для инъекций. Будем знать.
        Артур Шевченко
        18 сентября 2025, 00:09
        0
        Вставлять сырые данные с фронта в запрос небезопасно, именно на этот случай мной и была добавлена принудительная проверка. Сам в начале этим грешил. А еще в pdo есть методы для подготовки запроса, это делает их чуть более безопасными. Тут можно почитать
          Александр Туниеков
          18 сентября 2025, 01:09
          0
          Что РКН с инетом делает?? гитхаб не открывается, а впн помогло :-(
    Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
    5