Главная страница
Навигация по странице:

  • Настройка защиты от SQL-инъекции

  • о home

  • Оглавление 4 Введение 8 Основы безопасности 12

  • Простые методы взлома 64

  • Работа 130 с системными командами 130

  • SQL-инъекция (PHP + MySQL) 149

  • SQL-инъекция .NET + MS SQL Server 181

  • CSRF, или XSRF-уязвимость 192 DoS-атака на web-сайт 201

  • Авторизация 226 XSS 239 Заключение 251 Предметный указатель 253

  • ГЛАВА 6

  • Особенности MS SQL Server

  • Опасные процедуры MS SQL Server

  • WEb практикум. Web'cepbep


    Скачать 4.76 Mb.
    НазваниеWeb'cepbep
    АнкорWEb практикум
    Дата22.01.2023
    Размер4.76 Mb.
    Формат файлаdocx
    Имя файлаWEB.docx
    ТипДокументы
    #898678
    страница13 из 18
    1   ...   10   11   12   13   14   15   16   17   18

    Welcome

    ";

    } else {

    echo "

    Try again

    ";

    }

    В этом коде снова есть SQL-инъекция, но именно сейчас не об этом.

    В данном случае подразумевается, что в переменной $_post [' username' ] находится имя проверяемого пользователя, а в переменной $_post[ 'password' ] — пароль. Ес­ли SQL-запрос возвращает хотя бы одну строку, то авторизацию считаем пройден­ной удачно, ведь раз такой пользователь есть в таблице, значит, все в порядке.

    А если в качестве имени и пароля указать процент? В этом случае запрос вернет все записи, и сценарий посчитает нашу авторизацию корректной, хотя на самом деле она такой не является.

    Чтобы авторизоваться под чужим именем, достаточно указать его имя пользователя (на web-сайтах и форумах имена зарегистрированных пользователей чаще всего не являются секретом), а в качестве пароля — процент. В результате запрос найдет нужную запись и разрешит нам вход. Хакеру достаточно только узнать имя адми­нистратора (чаще всего это admin или administrator), войти под его именем, и мож­но делать на web-сайте все, что душе угодно и от чужого имени.

    Если символ процента запрещен, а подчеркивания — нет, то наша задача усложня­ется, но не сильно. Мы должны только подобрать длину пароля и указать соответ­ствующее количество подчеркиваний. Подбор не отнимет очень много времени, нужно только указать сначала один символ подчеркивания, затем два, три и т. д., пока вход не завершится удачей. Количество проверок будет равно количеству символов в пароле. Чаще всего это количество не более 10 символов.

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

    Листинг 5.2. Проверка корректности имени пользователя

    $line = $query->fetch(PDO::FETCH_ASSOC); if ($query->rowCount() > 0 &&

    $line[username] == $_POST['username'] &&

    $line[password] == $_POST['password']) { echo "

    Welcome

    ";

    } else {

    echo "

    Try again

    ";

    }

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

    Но даже в этом случае лучше все же не использовать like в запросах, а заменить его на знак равенства, как показано в листинге 5.3.

    Листинг 5.3. Используем знак равенства

    $sql = "SELECT * FROM user WHERE username = $_POST['username'] . "' AND password = $_POST['password'] . "'";

    $query = $connection->prepare($sql);

    $query->execute();

    $line = $query->fetch(PDO::FETCH_ASSOC);

    if ($line[username] == $_POST['username'] && $line[password] == $_POST['password']) { echo "

    Welcome

    ";

    } else {

    echo "

    Try again

    ";

    }

    1. Возможные проблемы

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

    Например, сценарий выполняет следующий SQL-запрос:

    SELECT *

    FROM tablel t1, table2 t2 WHERE posterName='$username'

    AND t1.keyfield = t2.keyfield

    Если в переменной $username будут просто одинарные кавычки и открытие ком­ментария, то результат окажется нежелательным. Необходимо в переменной пере­давать и связь, например:

    ' AND t1.keyfield = t2.keyfield and ... /*

    Если какая-то команда не выполняется, то это плюс администратору, который за­блокировал доступ, или просто у вас нет прав на выполнение данной команды.

    Чуть проще ситуация в тех случаях, когда используется связь таблиц через join:

    SELECT *

    FROM table1 t1 inner join table2 t2 on t1.keyfield = t2.keyfield WHERE posterName='$username'

    Здесь мы внедряемся в SQL-запрос уже после того, как наведена любая связь.

    Еще одна преграда, которую устанавливают администраторы и программисты перед хакерами: экранирование одинарных кавычек или их запрет. Раньше в PHP был па­раметр magic_quotes_gpc. Если этот параметр включен, то перед опасными симво­лами, такими как одинарная кавычка, устанавливается слеш. С одной стороны, это хорошо, потому что если хакер в качестве параметра передаст кавычку, то она не будет иметь специализированного значения. То же самое программисты могут сде­лать на сервере и другими инструментами, просто заменяя одинарную кавычку на \' простой заменой.

    Недостаток этого подхода в том, что он расслабляет администратора, который надеется, что хакер не сможет использовать SQL-инъекцию, но это не так. Дан­ную защиту очень легко обойти практически в любой СУБД. Для начала посмот­рим, как это можно сделать в MySQL. Допустим, вы хотите внедрить следующий SQL-запрос:

    INSERT INTO table VALUES (1, 'admin')

    Так как одинарная кавычка невозможна, этот запрос не может быть выполнен. Как же тогда передать текст, если нельзя использовать кавычку? Да очень просто — передать строку в виде кодов:

    INSERT INTO table VALUES (1, char(97, 100, 109, 106, 110))

    Теперь в SQL-запросе нет кавычки, и СУБД его выполнит даже при включенном параметре magic_quotes_gpc или ручном экранировании.

    Чтобы вам было удобнее, в табл. 4.1 приведены коды всех английских букв.


    Таблица 4.1. Таблица кодов английских букв

    a

    97

    b

    98

    c

    99

    d

    100

    e

    101

    f

    102

    g

    103

    h

    104

    i

    105

    j

    106

    k

    107

    i

    108

    m

    109

    n

    110

    o

    111

    p

    112

    q

    113

    r

    114

    s

    115

    t

    116

    u

    117

    y

    118

    w

    119

    x

    120

    w

    121

    z

    122













    Помимо букв вам могут понадобиться еще и некоторые другие символы. Например, символ слеша имеет код 47.

    1. От теории к практике

    Никакая теория не заменит практику. Нет, мы не будем заниматься взломом, пото­му что это нарушение закона. Мы просто проведем поиск уязвимых к SQL- инъекции web-сайтов, построенных на связке "PHP + MySQL", и посмотрим, какие возможности предоставляет злоумышленнику данная уязвимость.

    Для начала нам понадобится web-сайт с приличной посещаемостью. В Google я за­пустил поиск по словам Sport, USA, php (это случайные слова, которые пришли мне в голову) и начал просматривать результат, выбирая нужное. Первый web-сайт, ко­торый меня заинтересовал, ничего особого не содержал. Может, в нем и были ошибки, но поверхностный осмотр ничего особого не показал: все параметры, ко­торые я увидел, фильтровались на опасные символы.

    Вторым мне на глаза попался web-сайт www.usacycling.org, посвященный велоси­педному спорту. Две минуты мне понадобилось на то, чтобы найти первую уязви­мость. Все это время я подставлял в параметры одинарную кавычку и ждал сооб­щения об ошибке. И вот она появилась в сценарии news/user/story.php в параметре id. Как же любят администраторы называть ключевое поле в таблицах или перемен­ные для поиска по этому полю именем id.

    Уязвимый сценарий найден, и для подтверждения этого добавляю в параметр id условие "' and 1=1" и "and 1=1". Это значит, что нужно в адрес­ной строке ввести следующие URL: http://www.usacycling.org/news/user/

    story.php?id=1053'%20and%201=1 и http://www.usacycling.org/news/user/ story.php?id=1053'%20and%201=1.

    Первый SQL-запрос не выполнился, а второй отработал корректно. Значит, пара­метр id при подстановке в запрос не заключается в одинарные кавычки. Чуть позже я узнал, что включена магическая кавычка, и то, что параметр id не заключается в одинарные кавычки, — самая большая ошибка администратора. Если бы он выпол­нил это простое действие, то я не смог бы встроить код, потому что мне нужно бы­ло бы закрыть кавычку (выполнить запрос ' and 1=1), а так как одинарная кавычка запрещена, то SQL-инъекция не прошла бы.

    Итак, начинаю перебирать количество полей, встраивая объединение запросом select, и последовательно увеличиваю количество NULL-полей: www.usacydmg.org/news/user/story.php?id=1053%20umon%20select%20nun, www.usacydmg.org/news/user/story.php?id=1053%20umon%20seled%20nuU,nuU и т. д. Если количество полей не совпадет с имеющимся в таблице, то web-сервер должен вернуть ошибку, как показано на рис. 5.6.




    Рис. 5.6. При неверном количестве полей мы видим ошибку MySQL




    Перебор долго не продолжался, потому что SQL-запрос в сценарии получал из базы данных 4 поля, а значит, мне нужно было встроить объединение с четырьмя нуле­выми полями:

    UNION SELECT null,null,null,null

    Теперь рассмотрим web-страницу, которая отобразилась после SQL-инъекции. Ни­чего особенного в ней нет. Видимо, сценарий читает только одну запись из резуль­тата, полученного из базы данных. Чтобы убедиться в этом, я встроил следующий SQL-запрос:

    UNION SELECT 1111,2222,3333,4444

    SQL-запрос, выполняющий сценарий к базе данных, возвращает одну статью, которая и отображается. Мой дополнительный SQL-запрос добавляет к результату еще одну строку, которую сценарий просто игнорирует. Как же мне увидеть нужный результат? Нужно, чтобы первый SQL-запрос, прописанный в сценарии, ничего не вернул. Для этого достаточно через параметр id передать номер несуществующей статьи, на­пример 99991053. Это число очень большое, и я уверен, что статьи с таким номером не будет. Теперь первый SQL-запрос ничего не вернет, и сценарий выведет нужный мне результат (рис. 5.7). Прямоугольниками я выделил области, куда попали числа из моего SQL-запроса.




    Рис. 5.7. Теперь сценарий отображает результат внедренного SQL-запроса




    Давайте продолжим. Мне нужно узнать имена используемых таблиц. Попробуем наугад, ведь на web-сайте есть регистрация пользователей, а значит, может сущест­вовать таблица users. Добавим следующий SQL-запрос, который выбирает простые числовые поля из таблицы users:

    UNION SELECT 1111,2222,3333,4444 FROM users

    Тут меня ждала неудача и сообщение об ошибке:

    Table 'news.users' doesn't exist

    Это уже что-то. Мне сказали, что таблицы news.users не существует. Но я же за­прашивал просто users, откуда взялось news? Это имя базы данных, с которой рабо­тает web-сайт.

    Движемся дальше. Самое сложное в том, что включена фильтрация ввода кавычки и я не могу использовать ее в своих SQL-запросах. Ну ничего, как-нибудь обойдем­ся. Попробуем обратиться к системной базе данных MySQL и ее таблице user. Са­мое интересное, что эта база данных оказалась доступной, а значит, можно вычис­лить хеш пароля. Имя пользователя можно получить с помощью функции user(), а посредством функции version() — версию СУБД.

    Все, что мне нужно, я объединил в один большой SQL-запрос и получил следую­щий URL:

    http://www.usacydmg.org/news/user/story.php?id=99991053%20union%

    20select%20mysql.user.password,USER(),VERSION(),4444%20from%

    20mysql.user/*

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

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

    UNION

    SELECT mysql.user.password, USER(), VERSION(), 4444,

    FROM mysql.user

    WHERE mysql.user.password NOT IN ('УЖЕ ИЗВЕСТНЫЙ HASH')

    Или можно воспользоваться ограничением LIMIT:

    UNION

    SELECT mysql.user.password, USER(), VERSION(), 4444,

    FROM mysql.user

    WHERE mysql.user.password

    LIMIT 2,3

    Теперь SQL-запрос вернет строки со второй по третью. Таким образом, по одному можно прочитать из таблицы все необходимые системные данные.

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

    Я не занимаюсь вандализмом, поэтому сообщил администраторам и программи­стам о найденной ошибке. Пусть исправят.

    1. Настройка защиты от SQL-инъекции

    SQL-инъекция достаточно опасна, но при правильной настройке web-сервера хакер не сможет ею полноценно воспользоваться. Например, недавно я заглянул на web- сайт www.skanditek.ru (рис. 5.8), который содержит ошибку SQL-инъекции. В поле поиска достаточно ввести какой-нибудь текст и указать символ одинарной кавыч­ки, и в результате мы увидим сообщение об ошибке от MySQL (рис. 5.9).

    /а Skanditek :: SEARCH - Microsoft Internet Explorer

    File Edit View Favorites Tools

    ©Back 0 • 0 | & P Search >> Favorites Media [ j- ^ S T


    Address
    http: //ww w, skanditek, ru/search/index-en. php?q=%27





















    5KANDI |EK

    o products о standard designs о technologies

    o photogallery

    о news

    о feedback

    о home

    search

    5t.Petersburg office;

    Inostrannyi lane 6, St.Petersburg; Russia +7 812 327-1999,323-2301

    Moscow office;

    Krasnobogatyrskaya str., 2 +7 495 169-6567,168-0342

    infQtgJskanditek.ru

    random designs

    Wooden house ALEX

    feedback dealers in europe

    jroducts standard designs technologies ohotogallerv

    tel/fax: +7 812 327-1999, +7 812 323-2301, +7 495 169-65Б7, +7 495 168-0342

    Copyright © 2005 SkandiTak Ltd. All Rights Reserved, Design: Siluet Studio

    Rambler's

    Щ Internet
    PORSA

    Рис. 5.8. Web-сайт www.skanditek.ru

    У меня зачесались руки сделать что-то и показать разработчику ошибку на приме­ре, но ничего не вышло. Настройки хостинговой компании и права доступа в MySQL, под которыми работал web-сайт, не позволяли внедрить код. При попытке добавить команду удаления всех записей из таблицы меня культурно отправляли на web-сайт хостинговой компании, где красовалась надпись "Request rejected". По­пытки вставить данные, удалить таблицу, обновить данные также заканчивались неудачей. Тогда я решил попробовать получить доступ к файловой системе через функции load_file и into outfile, но снова меня ждала неудача.

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

    Заглянув на web-сайт разработчика и просмотрев все их работы в портфолио, я вы­яснил, что подобная ошибка находится в половине web-сайтов, которые разрабаты­вались этой компанией.

    Несмотря на то, что безопасность web-сервера, в основном, зависит от выполняе­мых на нем сценариев и программистов, которые их пишут, есть возможность по­

    строить защиту, которая не зависит от этих факторов. Отличное решение данной проблемы — бесплатный модуль для Apache под названием mod_security.




    Рис. 5.9. Ошибка SQL




    Принцип действия модуля схож с действиями сетевого экрана, который встроен в ОС, только в данном случае он специально разработан для обеспечения взаимодей­ствия по протоколу HTTP. Модуль на основе правил, которые задает администра­тор, анализирует запросы пользователей к web-серверу и выносит свое решение о возможности пропустить пакет.

    Правила определяют, что может быть в запросе, а что нет. Там обычно содержится URL, откуда необходимо взять документ или файл. Как можно сформулировать правило для модуля с точки зрения безопасности системы?

    Рассмотрим простейший пример: для web-сервера представляет опасность несанк­ционированное обращение к файлу /etc/passwd, а значит, его не должно быть в строке URL. Таким образом, создаем правило, и модуль проверяет на основе задан­ных фильтров адрес URL, и если он нарушает правила, то запрос отклоняется.

    Итак, модуль mod_security можно найти на web-сайте http://www.modsecurity.org. По­сле его установки в файле httpd.conf можно будет использовать дополнительные директивы фильтрации запросов.

    Рассмотрим наиболее интересные из них:

    • secFilterEngine On — включить режим фильтрации запросов;

    • secFilterCheckURLEncoding On — проверять кодировку URL (URL encoding is valid);

    • SecFilterForceByteRange 32 126 — использовать символы только из указанного диапазона. Существует достаточное количество служебных символов (напри­мер, перевод каретки, конец строки), коды которых менее 32. Большинство из них невидимы, но требуют обработки нажатия соответствующих клавиш. Но как же тогда хакер может ввести такой символ в URL? Только через их код. Напри­мер, чтобы применить символ "конец строки", необходимо указать в URL "%13". В данном случае коды символов менее 32 и более 126 являются недопус­тимыми для адреса, поэтому вполне логично такие пакеты не пропускать к web- серверу;

    • secAuditLog iogs/audit_iog — определяет файл журнала, в котором будет со­храняться информация об аудите;

    • SecFilterDefaultAction "deny,log,status:406" — задает действие по умолча­нию. В данном случае указан запрет (deny);

    • SecFilter xxx redirect:http://www.webkreator.com — обеспечивает переадреса­цию. Если правила соблюдены, то пользователя отправляют на web-сайт

    http://www.webkreator.com;

    • SecFilter yyy log,exec:/home/apache/report-attack.pl — запускает сценарий. Если фильтр срабатывает, то будет выполнен сценарий /home/apache/report- attack.pl;

    • SecFilter /etc/password — устанавливает запрет на использование в запросе пользователя обращения к файлу /etc/passwd. Таким же образом нужно добавить ограничение на файл /etc/shadow;

    • SecFilter /bin/ls — отказ пользователям в обращении к директивам. В данном случае запрещается команда ls, которая может позволить хакеру уви­деть содержимое каталога, если в сценарии есть ошибка. Необходимо предотвра­тить обращения к таким командам, как cat, rm, cp, ftp и др.;

    • SecFilter "\.\./" — классическая атака, когда в URL указываются символы точек. Их не должно там быть;

    • SecFilter "delete[[:space:]]+from" — запрет текста delete...from, который чаще всего указывается в SQL-запросах для удаления данных. Такая строка очень часто используется в атаках типа SQL-инъекции. Помимо этого, рекомен­дуется установить следующие три фильтра:

    • SecFilter "insert [ [: space: ] ] +into" — используется в SQL-запросах для до­бавления данных;

    • SecFilter "select.+from" — используется в SQL-запросах для чтения данных из таблицы базы данных;

    • SecFilter "<(.|\n)+>" и SecFilter "<[[:space:]]*script" — позволяют защи­титься от XSS-атак (Cross-Site Scripting, межсайтовое выполнение сценариев).

    Мы рассмотрели основные методы, использование которых может повысить безо­пасность вашего web-сервера. Таким образом можно защищать даже сети из web- серверов.

    1. Защита СУБД

    Ошибке, приводящей к возможности SQL-инъекции, подвержены сценарии на всех языках программирования и все СУБД. Дело в том, что к этому приводит особен­ность языка SQL, а хакер использует именно его возможности.

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

    Возможности, которые может получить хакер при использовании SQL-инъекции, зависят именно от используемой СУБД. Если я не ошибаюсь, то до сих пор наибо­лее популярной является MySQL, но ей на пятки точно наступает PostgreSQL.

    Однако в интернете можно встретить множество web-серверов, которые использу­ют более мощные (обладающие большим количеством возможностей) СУБД, на­пример, Oracle или MS SQL Server. Но именно дополнительные возможности могут дать хакеру опасные привилегии при неправильной настройке.

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

    У простых пользователей не должно быть возможности удалять записи, поэтому для них должен стоять запрет на выполнение оператора delete. Вставка данных необходима таким сценариям, как форум или гостевая книга, а если у вас сценарии, которые только отображают данные (выполняют оператор select), то нужно запре­тить и insert. Обновление данных тоже достаточно популярная функция, и редко бывает возможность запретить ее.

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

    В MS SQL Server есть одна очень опасная процедура — xp_cmdsheii, с помощью которой можно выполнять команды от имени учетной записи, под которой работа­ет MS SQL Server. Так как эта СУБД очень часто работает под системной учетной записью, то хакер может получить неограниченные права.

    Еще одна процедура, которая может быть опасной, — sp_makewebtask; создающая новую задачу, а также функции отправки сообщений электронной почты xp_startmail, xp_sendmail. Почему так опасны почтовые функции? Дело в том, что хакеры могут использовать ваш web-сервер для рассылки спама, который может оказаться достаточно опасным. Чем? Ваш web-сервер может попасть в спам-листы, и ваши пользователи не смогут получать нужную корреспонденцию, да и не ис­ключены проблемы с правоохранительными органами. Спам во многих странах стал уголовно преследуемым. Да, вы не виноваты в том, что хакер использовал ваш web-сервер, и вас оправдают, но проблемы с законом ничего хорошего не принесут. Разве что можно заработать временную скандальную известность. Если вам нужен скандал, то можете оставить дыру и повесить объявление: "Взломайте меня", или объявите конкурс на лучший взлом.

    Но с какой базой данных вы бы ни работали, универсальный и самый лучший ме­тод защиты от SQL инъекции — это параметризированные запросы.

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

    Но проблема в том, что хранимые процедуры не так удобны в поддержке и сопро­вождении, поэтому они постепенно отошли на второй план.

    Параметры — отличный способ защиты, и раз уже мы начали использовать PHP для иллюстрации примеров, давайте продолжим это делать. В SQL на месте, где будут находиться данные, полученные от пользователей, нужно написать двоето­чие и имя, которое вы хотите дать параметру. Если мы проверяем имя и пароль, то можно назвать параметры :username и :password:

    $sql = "SELECT * FROM user WHERE username = :username AND password = :password";

    У нас одна большая строка, которая заключена в двойные кавычки, и уже нет ника­ких объединений с помощью плюсов или точек. Какой бы язык программирования вы ни использовали, основной признак SQL-инъекции — это внедрение параметров в запрос SQL через плюс или любой другой метод сложения строк. Если же у вас одна цельная строка, то это хороший знак, что запрос будет безопасным, если толь­ко вы потом ничего в него не вставляете и никак не изменяете эту строку. Я никак не меняю строку, так что она безопасна.

    Теперь подготавливаем запрос, как мы это делали и раньше с помощью prepay, чтобы получить объект $query. У этого объекта есть метод bindValue, принимаю­щий два параметра — имя параметра, которому нужно предоставить значение, и само значение:

    $query = $connection->prepare($sql);

    $query->bindValue(":username", $_POST['username']); $query->bindValue(":password", $_POST['password']);

    $query->execute();

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

    То же самое можно было бы сделать в две строки без использования bindValue, просто передать все имена параметров и значения прямо методу execute: $query->execute([":username" => $_POST['username'],

    ":password" => $_POST['password']]);

    Здесь в массиве у нас в качестве ключей имена параметров, а в качестве значения элементов массива уже идут значения параметров:

    [имя параметра 1 => значение 1, имя параметра 2 => значение 2]

    Параметры очень удобны, когда мы точно знаем, сколько их и где они расположе­ны в запросе, потому что мы просто ставим имя в нужном месте и используем. А что, если есть какое-то параметр, который может проверяться на соответствие не­скольким значениям? В SQL это часто выражается оператором in (). Что, если в in может находиться 2, а то и 10 значений? Можно как-то динамически собирать стро­ку SQL, но в нее помещать не сами значения, а именно параметры:

    WEB'CEPBEP 1

    глазами 1

    Оглавление 4

    Введение 8

    Основы безопасности 12

    1.3.1.Определение типа операционной системы 19

    1.3.2.Определение имен работающих служб 20

    1.3.3.Используемые фреймворки 24

    1.3.4.Использование эксплоитов 28

    1.3.5.Автоматизация 29

    1.4.1.Анализатор web-уязвимостей 33

    1.4.2.Взлом с помощью поисковой системы 36

    1.7.1.Distributed Denial of Service (DDoS) 46

    1.7.2.Защита от распределенной атаки 47

    1.8.1.Защита web-сервера 49

    1.8.2.Модули безопасности Apache 50

    1.9.1.Права сценариев web-сервера 52

    1.9.2.Права системных сценариев 53

    1.9.3.Права доступа к СУБД 54

    1.11.1.Самостоятельно написанные программы 58

    1.11.2.Готовые решения 59

    1.11.3.Программы, написанные под заказ 60

    1.11.4.Золотая середина 60

    Простые методы взлома 64

    2.1.1.Вариант накрутки № 1 64

    2.1.2.Вариант накрутки № 2 65

    2.1.3.Вариант накрутки № 3 66

    2.1.4.Защита от накрутки 67

    2.3.1.Внутренний мир каптчи 71

    2.3.2.Примеры некорректных каптчей 73

    2.3.3.Пример хорошей каптчи 74

    Взлом PHP-сценариев 80

    3.1.1.Пример реальной ошибки 80

    3.1.2.Проблема include 85

    3.1.3.Инъекция кода 89

    3.2.1.Лишние сценарии на рабочем сервере 91

    3.2.2.Дополнительные программы 91

    3.2.3.Резервные копии или старые файлы 92

    3.3.1.Метод GET 96

    3.3.2.Метод POST 98

    3.3.3.Уязвимость 101

    3.3.4.Другие методы 103

    3.3.5.Инициализация переменных 104

    3.4.1.Конфигурационные файлы 110

    3.4.2.Промежуточные модули 113

    3.4.3.Скрытые функции 116

    3.9.1.Воровство кликов 125

    3.9.2.Cross Frame Scripting 125

    3.9.3.Защита от фреймов 126

    Работа 130

    с системными командами 130

    • • • 131

    4.3.1.Проверка корректности файлов изображений 142

    4.3.2.Проверка корректности текстовых файлов 144

    4.3.3.Сохранение файлов в базе данных 145

    4.3.4.Обращение к файловой системе 145

    4.3.5.Угроза безопасности 148

    SQL-инъекция (PHP + MySQL) 149

    5.2.1.Сбор информации 156

    5.2.2.Использование уязвимости 170

    5.2.3.Доступ к файловой системе 172

    5.2.4.Поиск уязвимости 172

    5.2.5.Процент опасности 173

    5.2.6.Возможные проблемы 176

    5.2.7.От теории к практике 178

    SQL-инъекция .NET + MS SQL Server 181

    6.1.1.Опасные процедуры MS SQL Server 181

    6.1.2.Распределение прав доступа 184

    6.1.3.Опасные SQL-запросы 186

    6.1.4.Рекомендации по безопасности MS SQL Server 187

    CSRF, или XSRF-уязвимость 192

    DoS-атака на web-сайт 201

    8.2.1.Оптимизация SQL-запросов 202

    8.2.2.Оптимизация базы данных 208

    8.2.3.Выборка необходимых данных 211

    8.2.4.Резюме 212

    8.3.1.Кеширование вывода 213

    8.3.2.Кеширование web-страниц 214

    8.3.3.Программные решения 216

    8.3.4.Медленный код 217

    8.3.5.Асинхронный код 218

    Авторизация 226

    XSS 239

    Заключение 251

    Предметный указатель 253

    В результате может быть собрана строка в виде:

    select * from table where column in (:param1, :param2, ...)

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

    Теоретически можно использовать данные от пользователя напрямую в SQL- запросах, но для этого их нужно очищать от одинарных кавычек. Не рекомендую вам это делать. Единственный случай, когда я позволяю себе использовать напря­мую в запросе какие-то данные от пользователя — это если я ожидаю число. В та­ких случаях достаточно просто написать фильтр, который будет убирать из пользо­вательских данных все, что не является числом: function checknum($var)

    {

    $var=preg_replace("/[Л0-9]/i", "", $var); return $var;

    }

    Функция получает в качестве параметра переменную и с помощью регулярного вы­ражения вырезает из этой переменной все, что не является числом, т. е. любые дру­гие символы и буквы. Теперь перед использованием параметра, на который может повлиять пользователь (получаемый через форму, запросом get или из cookie), вы­полняем следующее:

    $id = checknum($id);

    Таким образом можно гарантировать, что параметр содержит только цифры и ни­чего другого и является абсолютно безопасным для SQL-запроса.

    Я использую этот подход очень редко и очень аккуратно. В реальности, если по­смотреть на мой код, то в 99,99999999% случаев будут именно параметры, и, мо­жет, в одном случае на миллион будет отфильтрованное числовое значение.

    1. Защита от инъекции в C#

    Хотя в этой книге я чаще показываю примеры на языке PHP, потому что он очень простой, некоторые из них я буду переводить и на C#. Все предыдущие уязвимости и проблемы, которые я рассматривал до этого, на C# реализовывались абсолютно так же: просто на другом языке пишем тот же код, который я привел на PHP. Тут же есть своя небольшая специфика, поэтому я посвятил уязвимости SQL-инъекции в C# отдельную главу (см. главу 6).

    ГЛАВА 6

    SQL-инъекция .NET + MS SQL Server

    Да, SQL-инъекция возможна и в сценариях, написанных на языках программирова­ния C# и Java. Есть много разговоров о том, что эти два языка программирования безопасны, но это не относится к SQL-инъекции. Оба языка предоставляют хорошую защиту памяти и предоставляют неплохие средства для защиты от SQL Injection, но не исключают проблемы.

    С точки зрения поиска уязвимостей процесс проверки сайтов на C# не отличается от PHP, так что поиск второй раз рассматривать смысла нет. С точки зрения ис­пользования отличия есть, потому что PHP-сайты обычно работают на ОС Linux, а C# сайты чаще работают на Windows, хотя сейчас набирает популярность плат­форма .NET Core, которая позволяет писать C# код.

    Если вы найдете ошибку в C# коде и получите доступ выполнять через базу данных команды в ОС, то нужно сначала понять, на какой именно операционной системе работает сайт.

    1. Особенности MS SQL Server

    Мои исследования показывают, что если web-сайт построен на C#, то, скорее всего, он использует базу данных MS SQL Server.

    При переходе от одной web-страницы к другой в ссылке чаще всего передаются числовые значения — например, идентификаторы строк из определенной таблицы, которые нужно отобразить. В ASP достаточно удобно реализована типизация. Про­граммист просто указывает, что определенная переменная должна быть числовой, и никаких проблем: все попытки хакера указать что-то вместо числа будут пресе­каться.

    В .NET доступ к параметрам, которые передают пользователи на сайт, можно по­лучить через специальный объект Request["id"]. В зависимости от того, какую версию фреймворка вы используете и какой паттерн, доступ к этому объекту мож­

    но получить через глобальную переменную HttpContext или через объект Page, если вы используете новый подход со страницами.

    В любом случае, у нас будет объект Request и мы сможем читать из него данные от пользователя.

    int id;

    if (int.TryParse(Request["id"], out id)) {

    // здесь используем число id

    }

    else {

    // здесь мы можем сгенерировать ошибку

    }

    В этом коде с помощью метода int.TryParse я попытаюсь превратить строку в число, и если это удастся сделать, то результат будет записан в переменную id. В этой переменной будет число и ничего кроме числа, так что если пользователь по­пытается передать что-то еще, лишние символы приведут к тому, что TryParse даст нам это понять.

    В поле для поиска необходимо вводить слова и любые читаемые символы, а значит, переменная для хранения искомого текста должна быть текстовой. Здесь уже нет возможности что-то убрать автоматически, и C# воспринимает получаемые данные в том виде, в котором указывает их пользователь. И вот тут начинает дей­ствовать волшебная одинарная кавычка.

    1. Опасные процедуры MS SQL Server

    Самое опасное с точки зрения безопасности — использование процедуры xp_cmdshell, которая позволяет выполнять системные команды. Запрос на выпол­нение команды может выглядеть следующим образом:

    '; exec master..xp_cmdshell 'команда' —

    Например, если вы хотите проверить связь с определенным компьютером командой ping, то можно выполнить:

    '; exec master..xp_cmdshell 'ping servername.com' —

    С помощью процедуры xp_cmdshell можно достаточно легко создать какой-нибудь файл, например:

    '; exec master..xp_cmdshell '"" >> hack.php' —

    Теперь, если у вас установлен интерпретатор PHP, хакер сможет использовать файл hack.php для более удобного выполнения команд. А можно произвести и дефейс. Если главная web-страница — это index.htm, то достаточно выполнить:

    '; exec master..xp_cmdshell '"
    1   ...   10   11   12   13   14   15   16   17   18


    написать администратору сайта