Так сложилось, что вот уже который год мне приходится заниматься технической поддержкой хостинга, а также поддержкой сайтов, к которым я имею довольно косвенное отношение. А так как администраторы довольно часто сталкиваются с разного рода атаками на свои сайты, не имея при этом возможности нанять специалиста, мне пришло в голову придумать единое и универсальное решение для всех сайтов, которое бы помогло им защитить свой сайт без особых усилий. И хотя в нем есть еще немало минусов и нюансов, которые мне пока не удалось решить, тем не менее это единственное на данный момент решение, которое позволяет обезопасить сайт изнутри, не обращаясь к разного рода плагинам и модулям, которые нужно устанавливать извне и которое даже малоопытный разработчик сайтов способен установить и настроить у себя на сайте. Суть данного решения заключается в том, чтобы обработать данные переданные методами GET, POST и/или COOKIE, еще до момента обработки и записи их самих непосредственно в базу данных.

В этой статье я приведу примеры использования и недостатки того или иного метода.

Вот собственно сам код

$jsxss="onabort,oncanplay,oncanplaythrough,ondurationchange,onemptied,onended,onerror,onloadeddata,onloadedmetadata,onloadstart,onpause,onplay,onplaying,onprogress,onratechange,onseeked,onseeking,onstalled,onsuspend,ontimeupdate,onvolumechange,onwaiting,oncopy,oncut,onpaste,ondrag,ondragend,ondragenter,ondragleave,ondragover,ondragstart,ondrop,onblur,onfocus,onfocusin,onfocusout,onchange,oninput,oninvalid,onreset,onsearch,onselect,onsubmit,onabort,onbeforeunload,onerror,onhashchange,onload,onpageshow,onpagehide,onresize,onscroll,onunload,onkeydown,onkeypress,onkeyup,altKey,ctrlKey,shiftKey,metaKey,key,keyCode,which,charCode,location,onclick,ondblclick,oncontextmenu,onmouseover,onmouseenter,onmouseout,onmouseleave,onmouseup,onmousemove,onwheel,altKey,ctrlKey,shiftKey,metaKey,button,buttons,which,clientX,clientY,detail,relatedTarget,screenX,screenY,deltaX,deltaY,deltaZ,deltaMode,animationstart,animationend,animationiteration,animationName,elapsedTime,propertyName,elapsedTime,transitionend,onerror,onmessage,onopen,ononline,onoffline,onstorage,onshow,ontoggle,onpopstate,ontouchstart,ontouchmove,ontouchend,ontouchcancel,persisted,javascript";
$jsxss = explode(",",$jsxss);
foreach($_GET as $k=>$v)
{
	if(is_array($v))
	{
		foreach($v as $Kk=>$Vv)
		{
			$Vv = preg_replace ( "'<script[^>]*?>.*?</script>'si", "", $Vv );
			$Vv = str_replace($jsxss,"",$Vv);
			$Vv = str_replace (array("*","\\"), "", $Vv );
			$Vv = strip_tags($Vv);
			$Vv = htmlentities($Vv, ENT_QUOTES, "UTF-8");
			$Vv = htmlspecialchars($Vv, ENT_QUOTES);
			$_GET[$k][$Kk] = $Vv;
		}
	}
	ELSE
	{
		//Сначала удаляем любые скрипты для защиты от xss-атак
		$v = preg_replace ( "'<script[^>]*?>.*?</script>'si", "", $v );
		//Вырезаем все известные javascript события для защиты от xss-атак
		$v = str_replace($jsxss,"",$v);
		//Удаляем экранирование для защиты от SQL-инъекций
		$v = str_replace (array("*","\\"), "", $v );
		//Экранируем специальные символы в строках для использования в выражениях SQL
		$v = mysql_real_escape_string( $v );
		//Удаляем другие лишние теги.	
		$v = strip_tags($v);
		//Преобразуем все возможные символы в соответствующие HTML-сущности
		$v = htmlentities($v, ENT_QUOTES, "UTF-8");
		$v = htmlspecialchars($v, ENT_QUOTES);
		//Перезаписываем GET массив
		$_GET[$k] = $v;
	}
	
}

Вышеуказанный пример обрабатывает только GET запросы. Так что цикл необходимо повторить как минимум с POST и COOKIE. К сожалению мне так и не удалось выполнить данное решение рекурсивно в функции, и передать все нужные нам массивы $_GET, $_POST и $_COOKIE одновременно. А самое главное, что так и не удалось реализовать, так это рекурсивный обход многомерных массивов такого типа, что связано с особенностью передачи данных данных внутри функции, а также ограниченностью использования переменных переменных.

1) $v = preg_replace ( "'<script[^>]*?>.*?'si", "", $v );

Здесь мы удаляем явно не нужный javascript код. Функция может оказаться лишней, если Вы все таки позволяете передавать непосредственно сам код, не для его выполнения, а для ознакомления. Например на форумах.

2) $v = str_replace($jsxss,"",$v);

Функция аналогична первой, только в данном случае мы вырезаем события, которые можно использовать для xss-атак. Можно несколько модифицировать данное решение и вырезать не только само событие, но содержимое, которое к нему пытаются прикрепить. Но я пока не увидел в этом необходимости

3) $v = str_replace (array("*","\\"), "", $v );

А эти вредоностные символы, особенно обратная косая черта, могут стать причиной взлома Вашей SQL. Так как сам символ используется довольно редко, а его потенциальная опасность довольно велика, я решил уничтожить его на корню.

4) $v = mysql_real_escape_string( $v );

Использование этой функции может вызвать излишнее экранирование символов, ведь скорее всего он уже используется непосредственно при записи данных в базу, но с другой стороны, он как никто другой поможет защититься от sql-инъекций и защитит Ваши данные. При его использовании необходимо использовать функцию после подключения к базе данных. Также не будем забывать, что mysql_real_escape_string не используется в php 7, да и само использование подобных функций зависит от способа подключения. Например при подключении к базе через mysqli может понадобиться использовать функция mysqli_real_escape_string.

5) $v = strip_tags($v);

Strip_tags поможет удалить все ненужные теги. К сожалению, и нужные тоже. Вторым параметром можно указать теги, которые нужно оставить. Но беда в том, что нужных тегов так много, что перечислить их довольно проблематично, а что самое прискорбное, то бывают встречаются и такие теги, которые разработчики сайтов добавляют самостоятельно, для создания определенных функций на сайте. Конечно, было бы куда удобнее указать теги, которые нужно удалить, а не оставить. Но будем довольствоваться тем, что есть. К тому же для таких решений можно использовать регулярные выражения.

6) $v = htmlentities($v, ENT_QUOTES, «UTF-8»);

7) $v = htmlspecialchars($v, ENT_QUOTES);


Думаю, что эти две функции не нуждаются в представлении и одна аналогична другой, поэтому вполне достаточно использовать одну из них. Тем не менее и они далеко не всегда уместны.

На текущий момент это все, что мне удалось собрать. Если кому-то есть, чем дополнить данную статью, то буду только рад ;)

P.S. Для тех, кто хаит решение и предлагает использовать PDO, шаблонизаторы, разные серверные модули и тд. Я ни в коей мере не отрицаю, что данное решение имеет свои минусы, и где-то покорежит вывод и даже может повлиять на функционал, для чего и написал вначале поста о том, решение имеет свои недостатки.

Этот пост не для программистов, он для администраторов сайтов, которым не хватает знаний и опыта, чтобы изменить код изнутри. Для тех, кто не хочет, или не может, платить за доработку сайтов. Что часто бывает, когда разработчик делает сайты подешевле, на какой-нибудь недорогой, а часто и вовсе бесплатной CMS.

А чтобы такого не происходило необходимо разрабатывать свои сайты на надежных и проверенных CMS, с качественной техподдержкой. Наиболее подходящая и функциональная CMS для разработки подобных проектов это Битрикс. Заказывая у нас на https://wazzup. Хостинг и Лицензию Битрикс мы готовы выполнить настройку и установку магазина совершенно бесплатно.

Также прошу учесть, что у нас действует акция за покупку Лицензии Битрикс, до 6 месяцев хостинга бесплатно.

Наши клиенты выбирают Битрикс, так как это единственная крупнейшая система управления сайтами в РФ с огромной системой техподдержки и мощнейшим функционалом. Надежность Битрикс обусловлена не только временем, но и постоянной квалифицированной техподдержкой программистов, в отличии от бесплатных и недорогих CMS, разработкой и поддержкой которых занимаются постоянно меняющиеся энтузиасты, без большого опыта.

Комментарии (40)


  1. andreymal
    05.10.2019 03:58
    +1

    Вы же понимаете, что если бы Хабр выполнял такие же замены, вы бы просто не смогли написать этот пост здесь?


    Этот бездумный карго-культ с пиханием всего подряд в одну кучу лишь вредит.


    1. zaratustra_ivan_ivanovich Автор
      05.10.2019 10:14
      -2

      Когда сайт в руках злоумышленников, это вредит куда больше. Да и для того и расписана каждая функция, чтобы каждый делал это избирательно в зависимости от своих потребностей и особенностей своего сайта.


      1. andreymal
        05.10.2019 14:05

        Нет никакой необходимости использовать ни одну из этих функций. От sql-инъекций защищают подготовленные выражения в PDO, от XSS же любой нормальный шаблонизатор поддерживает автоматическое экранирование из коробки, а если нужно разрешить пользователям немного html-кода (как на Хабре), то можно взять какой-нибудь Jevix, который работает не по чёрным, а по белым спискам, и оттого более безопасен, чем этот пост. А этот пост — вреден.


        1. zaratustra_ivan_ivanovich Автор
          06.10.2019 14:38

          Все известные мне шаблонизаторы направлены скорее на форматирование текста, в связи с чем, перенасыщены лишними настройками и опциями, в которых еще нужно разобраться. А для внедрения PDO в сайт обычно знаний администраторов сайта недостаточно.
          Я хочу подчеркнуть, никто не спорит, что это не лучшее решение, но за лучшее решение администраторам сайта вынуждены либо платить.


          1. andreymal
            06.10.2019 14:43

            Никто не заставляет зубрить каждую существующую опцию. Основы же можно изучить за пару часов в перерывах на обед.


            1. zaratustra_ivan_ivanovich Автор
              06.10.2019 15:52

              Первое и самое главное, Вы совершенно не задаетесь вопросом, кто будет это делать.
              Второе, шаблонизаторы также далеко не идеальны. В том же htmlpurifier, существует масса недостатков.
              Третье, если не нужны лишние опции, то вполне можно обойтись без них. Также ничто не мешает разобраться и потратить пару часов, как это делать, при этом изучив причины и следствия, что будет куда полезнее, чем изучение настроек шаблонизатора, тем более учитывая, что лишние опции будут только нагружать систему в целом.


              1. andreymal
                06.10.2019 15:58

                Вы совершенно не задаетесь вопросом, кто будет это делать.

                Очевидно, тот же, кому не лень писать вредительский код из этого поста.


                htmlpurifier

                Это не шаблонизатор.


                при этом изучив причины и следствия

                Но вот почему-то вы не потрудились это сделать перед написанием этого вредительского поста, и следствия приходится рассказывать нам самим в комментариях.


                лишние опции будут только нагружать систему в целом.

                Не будут, какой-нибудь opcache есть на каждом приличном хостинге.


  1. vital72
    05.10.2019 04:04

    вот это костылище…
    давайте поощрять быдло-кодеров?


  1. tempick
    05.10.2019 06:47

    Универсальная защита от xss-атак и sql-инъекций
    Я, конечно, не senior… Но разве бывает такое?

    К сожалению мне так и не удалось выполнить данное решение рекурсивно в функции, и передать все нужные нам массивы $_GET, $_POST и $_COOKIE одновременно
    $_REQUEST

    Существует же множество готовых библиотек для подобной «очистки» текста от тегов и пр. Зачем ЭТО?


    1. zaratustra_ivan_ivanovich Автор
      05.10.2019 10:44

      Тогда $_REQUEST и заменится, а $_POST и $_GET останутся без изменений. Не говоря о том, что может же быть и $_POST['name'] и $_GET['name'] в одном флаконе. Я не нашел библиотеки, которая бы включала в себя нужный объем защиты, по крайней мере на уровне php. Более того, они показались мне излишне громоздкими, с учетом того, что все тоже можно было бы сделать вполне без них используя минимум кода и не разбираясь в лишних настройках. А использование серверных решений, навроде ModSecurity, в большей степени не доступно для администраторов сайта, не говоря уже о том, что большинство из них обладают лишь поверхностными знаниями, и также не лишена тех же недостатков.


    1. Finesse
      05.10.2019 12:45

      Универсальная защита от xss-атак и sql-инъекций
      Я, конечно, не senior… Но разве бывает такое?
      Бывает: выключить сервер


      1. WhiteBlackGoose
        05.10.2019 13:30
        +2

        О, а вот и senior


  1. alexander222
    05.10.2019 08:22

    Читал и с каждым пунктом все больше ждал увидеть табоичку sarcasm в конце. Но так и не дождался, видимо все-таки серьезно.


  1. MKMatriX
    05.10.2019 10:20

    Простенький WAF, почитайте как приручают более сложные, профессиональные, продаваемые за деньги. Начните тут xakep.ru/2016/12/19/web-application-firewalls-bypasses


  1. M1ndgr3p
    05.10.2019 10:46

    а как быть с <javascript>, например?


    1. zaratustra_ivan_ivanovich Автор
      05.10.2019 10:55

      Такого тега не существует


    1. M1ndgr3p
      05.10.2019 21:03

      прошу прощения, из приложухи кривой коммент получился. имел ввиду


      <scr<script>ipt>


      1. dopusteam
        06.10.2019 01:21

        Прогнать код дважды, делов то ;)


        1. andres_kovalev
          07.10.2019 00:38

          &lt;scr&lt;scr&lt;script&gt;ipt&gt;ipt&gt;


        1. WhiteBlackGoose
          07.10.2019 09:12

          while "<javascript>" in text
          {
              bydlocode.run();
          }


  1. vilgeforce
    05.10.2019 12:19

    А нормально код писать не судьба? CSP там всякие использовать… Отдельно хочется узнать у автора пробовал ли он хотя бы sqlmap против своей «защиты»?


  1. marataziat
    05.10.2019 13:13

    Это обычный blacklisting который можно легко обойти. Хостинг не обязан заниматся безопасностью самих сайтов! Но если вы работаете напрямую то можно было настроить WAF на nginx.


    Но опять же, все эти топорные waf сделаны для предотвращения массовых атак в которых никто небудет искать обходы waf. Даже популярные waf как cloudflare невсегда помогают тк каждый день находят байпассы их блеклистов итд :)


  1. michael_vostrikov
    05.10.2019 14:14

    Раз никто еще не рассказал автору, как делать правильно, то я расскажу.


    В общем, товарищ автор, вы сделали ерунду, так никто не делает. Представьте, что у вас есть поле "Имя", и пользователь туда ввел имя с кавычкой, например "Д'Артаньян". А какое-то другое поле он не заполнил, и вам надо снова показать форму с теми значениями, которые он ввел. Если вы просто выведете получившееся значение, в интерфейсе в этом поле будет что-то типа Д\&#039;Артаньян.


    Правильно делать так: вызываем только одну нужную функцию в месте вывода значения, нужная функция определяется по контексту — htmlspecialchars для вывода в HTML-разметку, mysql_real_escape_string для вывода в текст SQL-запроса, urlencode для формирования URL и т.д. Для URL в разметке типа <a href="?name=...&surname=..." надо 2 функции — urlencode для значений и htmlspecialchars для полного URL. А для SQL mysql_real_escape_string использовать вообще не надо, это устаревший способ, я про него написал чтобы пояснить принцип. Для безопасной передачи параметров в SQL-запрос используется PDO и именованные параметры.


    1. zaratustra_ivan_ivanovich Автор
      05.10.2019 14:19

      Хорошо. В следующий раз когда ко мне обратятся с данной проблемой я напишу Вам и не сомневаюсь Вы совершенно бескорыстно пройдетесь по всему коду клиента и внесете необходимые изменения в каждом файле. Ну и не только мне я думаю. Можете даже команду собрать, которая будет бесплатно анализировать скрипты пользователей и вносить необходимые правки.


      1. michael_vostrikov
        05.10.2019 14:41
        +1

        Вам платят за поддержку сайтов? Значит берете и меняете в каждом файле, исправления безопасности это поддержка сайта. На данный момент ваше решение портит данные, которые вводят пользователи. Они сохраняются в таком виде в БД, и у пользователей даже нет возможности это исправить, любое повторное редактирование увеличивает число лишних символов.


        1. zaratustra_ivan_ivanovich Автор
          06.10.2019 06:54

          Кто сказал, что мне платят за поддержку сайтов? Я написал, что занимаюсь техподдеркой хостинга, и в техподдержку хостинга не входит исправление сайта. А люди хотят, чтобы им бесплатно исправили, когда на сайте у злоумышленника есть доступ. У кого-то интернет-магазины, где-то людей взламывают и пополняют балансы. Кто-то продал 2 крючка и вешалку у себя на вордпресс магазине, а за вешалку оказалось никто и не платил, зато кому-то она досталась бесплатно. В мою работу это не входит, и сидеть анализировать сайт для меня не вариант. Такое чувство, что никто не читал для кого и зачем написана статья. Все увидели только недостатки, которые я и так не скрывал, когда писал статью.


          1. michael_vostrikov
            06.10.2019 08:22

            Я написал, что занимаюсь техподдержкой хостинга

            Вы написали "вот уже который год мне приходится заниматься технической поддержкой хостинга, а также поддержкой сайтов". Если не платят, тогда непонятны ваши претензии по поводу "бескорыстной работы", вы и так ее делаете.


            Все увидели только недостатки, которые я и так не скрывал

            Вы написали только, что есть немало минусов и нюансов, а в чем они заключаются, не сказали. Основные это изменение корректных данных и отсутствие гарантии, так как невозможно предусмотреть все ситуации. Вот такой код например пройдет <script>alert(1)</script > (пробел перед последним символом).


            Недостатки объективны, поэтому на них обращают внимание. Вы предлагаете использовать ваше решение разработчикам на своих сайтах, именно поэтому и претензии. В работу разработчика изменение сайта входит, поэтому для него правильный вариант экранировать в месте вывода.


            1. zaratustra_ivan_ivanovich Автор
              06.10.2019 10:20

              Я полностью согласен, что правильны вариант экранировать на месте. Но я также понимаю, что большинство людей пытаются делать сайты как можно дешевле, заказывая самые дешевые тарифы на хостингах, используя бесплатные движки, и не хотя, а то и не могут, они тратить деньги, на специалиста, который будет этим заниматься, да и у самих знаний не хватает.
              По техподдержке сайта у меня таких вопросов не возникает. Если я его поддерживаю, значит я знаю и код. Я не использую, сомнительные движки и модули в своих работах, и либо пишу его сам, либо использую проверенные и надежные CMS.
              Совсем бескорыстной работой я не занимаюсь, мне платят за техподдержку хостинга, но никак не сайтов на них размещенный. Но куда проще предложить именно такое решение, чем сказать клиенту, чтобы он разбирался сам. Тем более клиент будет винить и хостинг в этом. В итоге клиент уйдет, решив, что дырявый именно хостинг, да еще и хаять будет его тут и там. Минусы да возможны, в виде кривого вывода. Но опыт показывает, что в таких случаях клиенты готовы мириться с этим.


      1. alutskevich
        05.10.2019 15:12

        Если кому-то есть, чем дополнить данную статью, то буду только рад ;)

        Что-то Вы не сильно рады дополнению ;)


  1. TheGodfather
    05.10.2019 18:54

    Удивительно, что никто не упомянул HTMLPurifier, который вроде как де-факто стандарт для очистки лишних тэгов и защиты от XSS в том числе. Поддерживаемый, протестированный и используемый в сотнях проектов — явно надежнее, чем очередной авторский велосипед.


  1. firk
    05.10.2019 19:09

    Вы опоздали, кто-то уже придумал этот способ https://habr.com/ru/post/460655/#comment_20412465


  1. BigDflz
    05.10.2019 19:13

    у примеру для защиты от sql-инъекций достаточно использовать хранимые процедуры.
    (для mysql нужно очень постараться чтоб сделать процедуру, подверженную атаке, и то это будет только один вариант атаки)
    для возражения — прошу предоставить проверенный вариант хранимки, а не поднимать шум
    ( и тем более не минусовать)


    1. michael_vostrikov
      06.10.2019 08:24

      $id = $_GET['id'];
      $db->query('CALL get_order(' . $id . ')');
      // http://.../order?id=(SELECT 123456 FROM user WHERE username = 'admin' AND auth_key like 'O%')
      // CALL get_order((SELECT 123456 FROM user WHERE username = 'admin' AND auth_key like 'O%'))

      Перебираем символы ключа авторизации по одному, получаем 404 на неправильный символ, данные заказа 123456 на правильный.


  1. Akuma
    05.10.2019 20:45
    +1

    Мне кажется тут проблема не в том, что автор «не бумбум». А в том, что там какие-то легаси-проекты, в которых все современные PDO и шаблонизаторы тупо не лезут, а платить за их внедрение не хотят.

    Хотят вариант быстро, бесплатно и чтобы работало. Вот автор так и сделал.
    Да, можно было использовать что-то более готовое конечно, но уж что есть.

    P.S. В реальных поддерживаемых проектах так конечно делать не стоит.


  1. FanatPHP
    05.10.2019 22:15

    Я не увидел здесь универсальной защиты. А только набор разрозненных и зачастую противоречащих друг другу рекомендаций.


    Я бы принял этот пост за чистую монету, если бы он был последовательным, т.е. — "вот моя задача, поддержка сайтов с адовым легаси, вот решение, страшное как моя жизнь, но рабочее, проверено на несколькх сайтах в течение полугода". Но приведенный код нежизнеспособен. Видно что он собран на коленке для публикации, и никогда не тестировался на живом сайте. Жаль. Не то чтобы я поддерживаю такой поход в принципе, но пост мог бы пройти хотя бы пройти по категории "тяжела и неказиста жинь простого сисадмиста". А получилась просто коллекция карго культ кода и пособие "как делать не надо".


  1. symbix
    05.10.2019 22:47

    Судя по рекламе, размещенной в профайле автора, в данном случае все органично.


  1. michael_vostrikov
    06.10.2019 11:11

    К сожалению мне так и не удалось выполнить данное решение рекурсивно в функции, и передать все нужные нам массивы $_GET, $_POST и $_COOKIE одновременно. А самое главное, что так и не удалось реализовать, так это рекурсивный обход многомерных массивов такого типа

    Вот так можно сделать. Раз уж используете, то пусть хотя бы меньше копи-пасты будет.


    function escape(&$data)
    {
        foreach ($data as $key => &$value) {
            if (is_array($value)) {
                escape($value);
            } else {
                $value = ...;
                ...
            }
        }
    }
    
    $data = [&$_GET, &$_POST, &$_COOKIE, &$_REQUEST];
    escape($data);
    unset($data);


  1. andres_kovalev
    07.10.2019 00:45

    А чем не угодили параметризованные запросы?


  1. dady_KK
    07.10.2019 02:28

    Ребят, вот честно, зря накинулись на автора. То, что он плохо разбирается и все такое, это конечно плохо, НО это повод указать на ошибки (как это многие сделали) и рассказать попроще что не так в коде (а ещё лучше что не так в самом подходе). Заодно и новичкам, коих тут пруд пруди, будет намного полезнее, иначе они подумают что нужно код переписать немного с учетом всех ошибок и готово.


    Простой пример, как бы мог сделать я (оговорюсь, я не программист, хотя на коленке наваять велосипед смогу, я больше по части продукта). Вот поступила задача по-быстрому отвадить ботов из условного Бангладеша с их автоматическими попытками взлома, компания маленькая и программист — это бывший сеошник, которому приходиться править верстку время от времени и про бекенд он знает только что там все работает на пхп, а это «очень сложный язык» (сарказм в отношении знаний, а не пхп как языка). Этот сеошник в гугле находит или просто часто читает Хабр эту статью, прочитал комменты, вспомнил, как примерно борется клаудфлер (блокировки на промежуток времени) и решил так и сделать и реализовал схему блокировок по айпи (не ругайтесь — это вполне может работать и даже довольно успешно, если подходить со значением дела и понимаем что нужно и как работает) и выстреливает себе в ногу, потому что поисковые боты блокируются и трафик в ноль, потому что где-то на сайте случайно есть на продажу условная книга «Как защититься от javascript в GET” (ну или добрые конкуренты ставят ссылки с подобными включениями в ГЕТ, которые индексируются ботами). Ну или блокируют сами себя, а доступ к серверу только через один айпи и бекапов не делают (а что от них ожидать, если сервером занимается сеошник или какой-нибудь контент-менеджер без образования) и они не знают других способов получать доступ к серверу/базе и т.п.


    Но в защитную автора и его способа скажу, как отсекатель мусорного трафика в масштабах хостинга может и будет работать, особенно если при этом не блокировать. А делать дополнительные проверки, типа невидимой (или видимой) рекаптчи. И не надо говорить, что «я одной левой обхожу все каптчи», да Вы можете, а остальные 99% тупых ботов, даже без поддержки js и печенек (по опыту скажу — она не вымерли) — вот отлично будут ловиться, в вместе с ними и непуганые мамкины хацкеры и на час-два отправляется учить уроки, а при повторенном попадании под каптчу — можно и блокировать и на поболее. А отсеивать нормальных ботов очень просто, кто этим занимался — не даст мне соврать (ну кроме ошибок в rdns и прочих редких «радостей»). Но то что я описываю — это не скрипт из одной функции на три десятка строк. И вот это нужно было бы рассказать автору и всем, кто захочет пойти по его «дорожке».


    Ну и ещё пара слов, WAF — это очень серьезная штука и кроме основной задачи, т.е. блокировки всего «лишнего», ещё очень важные моменты — ложно-положительные срабатывания и как уже писали байпас правил блокировки. И замена вот этого всего большого комплекса на одну функцию в тридцать строчек — это явно плохой вариант, но вот той компании, где программирует сеошник, а «админит сервер» (то есть заливает файлы по фтп) контент-менеджер, при чем первый — это директор, а второй — это собственник и ни желания и возможности платить за решения этой проблемы нет, возможно это лучший вариант, автоматические запросы не пройдут, а вот защититься от целенаправленной атаки (ну или хитрой какой-нибудь) они все равно не смогут, да и скорее всего не заинтересуют никого (т.е. защита Неуловимого Джо, которая не работает от автоматических запросов). Поэтому несмотря на абсурдность ситуации всегда нужно понимать, что для каждой задачи нужно свои решения и стрелять пушкой по воробьям — не всегда лучшая идея, и есть ситуации, когда и этот код будет хорошим решением. Но автора надо «розгами по рукам» за кликбейтный заголовок


  1. istepan
    07.10.2019 10:30

    Обожаю такие посты.

    Как делаю я:
    0. Для изучения проблемы в первую очередь гуглю известные и наиболее правильные\эффективные решения.

    1. При построении SQL запросов использую подготовленные выражения (prepared statement).

    При использовании подготовленных выражений (prepared statement) параметры внешнего происхождения отправляются на сервер отдельно от самого запроса либо автоматически экранируются клиентской библиотекой.
    Грамотная защита от SQL-Injection

    2. Данные в БД хранятся в неизменном виде. При выводе на клиентскую часть используется библиотека HTMLPurifier.

    3. В некоторых случаях в правилах валидации прописывается минимальный запрет на некоторые символы. Где очевидно пользователи не станут их использовать. Чаще всего для спам и прочих ботов, чтоб не захламляли базу и не отправлялись мусорные уведомления.