Пентест системы печати. Развиваем атаки

В предыдущих двух статьях (первая, вторая) мы начали разговор об уязвимостях системы печати. Поговорили о том, какие протоколы используют принтеры и как вообще устроен вывод документов на печать. Также, мы познакомились с инструментом Pentest Explotation Toolkit и рассмотрели некоторые атаки. Сегодня мы продолжим развивать тему атак на принтеры и за одно вспомним некоторые уязвимости Web.

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

Работаем с памятью

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

Для принтеров Brother в PJL есть специфическая команда производителя, которая позволяет записывать данные в NVRAM принтера или извлекать их из указанного адреса. Этой функциональностью можно воспользоваться для доступа к произвольным адресам NVRAM с помощью PJL, как показано ниже, где X — целое число, которое может быть увеличено для дампа всей NVRAM.

@PJL RNVRAM ADDRESS = X # чтение байта из ячейки памяти X

@PJL WNVRAM ADDRESS = X DATA = Y # запись байта Y в ячейку X

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

Если говорить об МФУ, то злоумышленник может изменить настройки Scan‑to‑FTP, чтобы отсканированные документы доставлялись на контролируемый злоумышленником FTP‑сервер, или изменить номера факсов в адресной книге, в результате чего факс будет отправлен на номер факса злоумышленника. Да, да факсы, эти устройства из 1990-х до сих пор используются некоторыми организациями.

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

$ ./pret.py –q printer pjl

4343bdcc8d10a2d5c5c953e83476047a.png

Если Brother позволяют работать с память с помощью PJL, то Xerox похожий функционал предлагает реализовать с помощью PostScript.

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

/counter 0 def 50000 {

  /counter counter 1 add def

  currentdict /RRCustomProcs /ProcSet findresource begin

  begin counter 1 false vxmemfetch end end == counter

} repeat

Реализовать этот скрипт можно к примеру, через Cross Site Printing, о котором мы поговорим далее.

Cross Site Scripting Printing

Атаки межсайтовой печати (XSP) позволяют веб‑злоумышленнику получить доступ к устройству принтера, который использует скрытый Iframe для отправки HTTP POST‑запросов на порт 9100/tcp принтера во внутренней сети жертвы.

HTTP‑заголовок печатается в виде обычного текста или отбрасывается в зависимости от настроек принтера. Однако данные POST‑запроса могут содержать произвольные задания печати, например команды PostScript или PJL, которые необходимо интерпретировать.

Например, мы можем передать скрипт, приведенный в предыдущем разделе, с помощью POST‑запроса и он будет выполнен.

Улучшенная межсайтовая печать

Предложенную концепцию межсайтовой печати можно улучшить. Вместо Iframe можно использовать JavaScript‑объекты XMLHttpRequest (XHR), для выполнения HTTP POST‑запросов к внутренним принтерам.

Основным ограничением рассмотренного до сих пор подхода к межсайтовой печати является то, что данные могут быть только отправлены на устройство, но не получены из‑за same‑origin policy.

Понятие SOP больше относится к безопасности Web, чем к системам печати. В рамках политики SOP веб‑браузер позволяет скриптам, находящимся на одной веб‑странице получить данные на второй веб‑странице, но только если обе веб‑страницы имеют одинаковый источник. Источник состоит из комбинации URI схемы, имени домена и номера порта.

Таким образом, SOP помогает изолировать потенциально вредоносные документы, сокращая возможные векторы атак. Например, она не позволяет вредоносному веб‑сайту в Интернете запускать JS в браузере для чтения данных из сторонней службы веб‑почты (в которой пользователь подписан) или внутренней сети компании (которая защищена от прямого доступа злоумышленника, поскольку не имеет публичного IP‑адреса) и передавать эти данные злоумышленнику.

Чтобы обойти ограничения политики SOP, можно использовать cross‑origin resource sharing (CORS) при условии, что веб‑сервер явно разрешает его использование, отправляя специальное поле заголовка HTTP.

Однако в сценарии межсайтовой печати мы имеем полный контроль над тем, что запрашиваемый веб‑сервер принтера, доступным через порт 9100/tcp, отправляет обратно в браузер. Здесь самое время вспомнить первую статью, когда мы искали нужные порты для работы с принтером.

Используя команды вывода PostScript, мы можем просто эмулировать HTTP‑сервер, работающий на порту 9100/tcp, и определить собственный HTTP‑заголовок для ответа — включая произвольные поля CORS Access‑Control‑Allow‑Origin, которые инструктируют веб‑браузер разрешить JavaScript доступ к этому ресурсу и, таким образом, пробивают брешь в SOP. Схематичный обзор атаки приведен ниже:

ba8b9f65eab3e550850e51bc41ead714.png

В таком расширенном варианте XSP — в сочетании с подменой CORS — веб‑злоумышленник получает полный доступ к HTTP‑ответу, что позволяет ему извлекать произвольную информацию, например захваченные задания печати с устройства принтера. Ниже показан примерный фрагмент JavaScript сценария:

job = "\x1B%-12345X\r\n"

    + "%!\r\n"

    + "(HTTP/1.0 200 OK\\n) print\r\n"

    + "(Server: PostScript HTTPD\\n) print\r\n"

    + "(Access-Control-Allow-Origin: *\\n) print\r\n"

    + "(Connection: close\\n) print\r\n"

    + "(Content-Length: ) print\r\n"

    + "product dup length dup string cvs print\r\n"

    + "(\\n\\n) print\r\n"

    + "print\r\n"

    + "(\\n) print flush\r\n"

    + "\x1B%-12345X\r\n";

 

var x = new XMLHttpRequest();

x.open("POST", "http://printer:9100");

x.send(job);

x.onreadystatechange = function() {

  if (x.readyState == 4)

    alert(x.responseText);

};

Но и здесь есть бочка дегтя в ложке меда.

Ограничения CSP

Начнем с того, что PCL как язык описания страниц неприменим для подмены CORS, поскольку он позволяет передавать только одно единственное число. И знакомый нам PJL также не может быть использован, потому что, он добавляет @PJL ECHO ко всем эхо‑строкам, что делает невозможным имитацию действительного HTTP‑заголовка.

Однако это не означает, что расширенные атаки XSP ограничиваются заданиями PostScript: PostScript может использоваться для ответа с поддельным HTTP‑заголовком, а команда завершения потока данных (\x1b), (именуемая также языком Universal Exit Language, UEL) может быть вызвана для переключения языка принтера. Таким образом, веб‑злоумышленник может получить результаты и для команд PJL.

Но существуют две проблемы в реализации, о которых стоит упомянуть: во‑первых, в PostScript необходимо определить правильную длину содержимого (Content‑Length) для данных, на которые нужно ответить. Если злоумышленник не может предсказать общий размер ответа, а кодирование по частям также не является вариантом, ему необходимо установить очень большое значение и использовать буфер.

Во‑вторых, важно добавить поле заголовка Connection: close, иначе соединения HTTP/1.1 будут поддерживаться до тех пор, пока либо веб‑клиент,  либо устройство принтера не сработает по таймауту, что означает, что принтер будет недоступен в течение некоторого времени.

Если принтер поддерживает печать обычного текста, заголовок HTTP‑запроса XHR распечатывается в виде твердой копии — включая поле заголовка Origin, содержащее URL‑адрес, вызвавший вредоносный JavaScript, что не позволяет злоумышленнику остаться незамеченным. Это неизбежно, поскольку мы не получаем контроль над принтером — и при некоторых обстоятельствах можем отключить функцию печати — до тех пор, пока тело HTTP не будет обработано, а заголовок HTTP уже будет интерпретирован устройством принтера как обычный текст.

Если приоритетом является снижение шума, злоумышленник может попытаться сначала отключить функцию печати с помощью собственных PJL‑команд, например, приведенных ниже:

@PJL SET SERVICEMODE=HPBOISEID

@PJL DEFAULT JOBMEDIA=OFF

Реализовать их с помощью PRET можно следующим образом:

$ ./pret.py -q printer pjl

1d3cf2edc34cab3a1d018ada97e2fd03.png

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

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

И наконец, стандарт IPP требует, чтобы тип содержимого для HTTP POST‑запросов был установлен на application/ipp, что невозможно сделать с объектами XHR — однако, здесь все зависит от реализации.

Заключение

Система печати является неотъемлемой частью инфраструктуры любой организации и наличие уязвимостей в ПО и настройках принтеров может привести к захвату всей сети точно также, как и захват пользовательской рабочей станции или сервера. Поэтому не стоит пренебрегать безопасностью данных систем. А при пентесте важно рассматривать печать как отдельный вектор и проверять его не менее тщательно, чем AD, Exchange и другие корпоративные системы.

В заключение рекомендую обратить внимание на открытые уроки, которые пройдут в марте в Otus:

  • «Роль CISO в построении системы информационной безопасности». Подробнее

  • «Безопасность в PostgreSQL: защита данных, управление доступом и аудит». Подробнее

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

© Habrahabr.ru