Пишем простой модуль для Nessus

Пишем простой модуль для Nessus

Life-Hack [Жизнь-Взлом]/Хакинг

#Обучение

Одним из ключевых аспектов тестирования на проникновения является автоматизация шаблонных действий. Кто-то для этого пишет отдельные программы, однако сейчас существует множество продуктов, которые позволяют расширять свои функциональные возможности с помощью дополнительных модулей. Пример бесплатного сканера уязвимостей с поддержкой модулей - OpenVAS, но в этой статье речь пойдет о Nessus, который хоть и платный, но субъективно находит больше и генерирует меньше false positive срабатываний (хотя OpenVAS начался, как форк Nessus, но это было давно). 

Большинство модулей для Nessus представляют собой обычные текстовые файлы с расширением .nasl. Часть модулей поставляются в виде бинарных файлов с расширением .nbin, но не будем об этом. Модули (или плагины) по умолчанию можно найти по следующим путям (https://community.tenable.com/s/article/Location-of-Plugin-Directory):

Windows: C:\ProgramData\Tenable\Nessus\nessus\plugins
Linux: /opt/nessus/lib/nessus/plugins 

Модулей довольно много, более 100 тысяч, часть из них написаны давно (судя по коду) и почти не обновляются, хотя реализуют базовые моменты сканирования (например, поиск распространенных имен директорий). Модули зачастую никак не параметризуются, что приводит к необходимости вручную править код, чтобы, например, расширить встроенный в модуль словарь. Зато в таком разнообразии всегда можно найти пример кода, чтобы реализовать какую-то специфичную функцию в своем модуле. 

В качестве примера мы напишем тривиальный модуль для поиска скрипта администрирования БД Adminer (https://github.com/vrana/adminer/). В Nessus есть похожий модуль для phpMyAdmin (https://phpmyadmin.net/). Модуль будет искать Adminer по всевозможным характерным путям, определять версию и в зависимости от нее выставлять степень критичности находки (до версии 4.6.3 возможно было читать файлы на сервере с помощью LOAD DATA LOCAL INFILE, подробнее можно прочитать тут). 

Отмечу, что документация по доступному API своеобразная и обрывочная, одни и те же действия в стадартных модулях временами реализуются разными способами без видимой причины, именование некоторых функций также оставляет вопросы, что наводит на мысль о пласте legacy-кода, который Tenable (разработчик Nessus) никак не вычистит (возможно, не хотят старые модули переписывать). 

Приступим. Модуль начинается с указания уникального внутреннего идентификатора для него, а также описания, даты релиза, степени критичности, CVE и т.п. Практически все является опциональным и служит лишь для удобного представления в веб-интерфейсе (а ведь модули можно запускать и без него через консоль). Рекомендую использовать подсветку синтаксиса для Ruby. Тут, естественно, используется не он, а NASL, но подсвечивает приемлемо.

# Adminer script discovery
include("compat.inc");
if(description)
{
    script_id(10797107);
    script_version("$Revision: 0.1 $");
    script_cvs_date("$Date: 2019/04/10 13:37:00 $");
    script_name(english: "Adminer Database Management Detection");
    script_set_attribute(attribute: "synopsis", value: "Adminer Database Management script was detected on the remote host.");
    script_set_attribute(attribute: "description", value: "Adminer Database Management script was detected on the remote host.");
    script_set_attribute(attribute: "solution", value: "Restrict access to the script, if desired.");
    script_set_attribute(attribute: "risk_factor", value: "Low");
    script_set_attribute(attribute:"plugin_publication_date", value: "2019/04/10");
    script_set_attribute(attribute:"plugin_type", value: "remote");
    script_end_attributes();
    script_summary(english: "Reports if Adminer (https://www.adminer.org/) was discovered on the remote host.");
    script_category(ACT_GATHER_INFO);
    script_copyright(english: "This script is Copyright (C) Kaimi (https://kaimi.io)");
    script_family(english: "CGI abuses");
    script_dependencie("webmirror.nasl");
    script_exclude_keys("Settings/disable_cgi_scanning");
    script_require_keys("Settings/enable_web_app_tests");
    script_require_ports("Services/www");
    script_timeout(1800);
    exit(0);
} 

Так как код в целом простой, буду описывать суть в абзацах после фрагментов кода. В вышеприведенном участке мы задали уникальный идентификатор, версию, дату, описание и прочие атрибуты модуля. Список атрибутов неполный, если есть необходимость добавить связанный CVE, CVSS и прочее - посмотрите примеры в стандартных модулях. В конце мы задаем категорию модуля - CGI abuses и несколько условий. Нам необходимо, чтобы до старта нашего модуля отработал модуль webmirror.nasl. 

Данный модуль занимается перебором стандартных путей и заполняет некоторые глобальные структуры, которые затем могут быть использованы другими модулями. Далее мы задаем условия, чтобы наш модуль не запускался если в политике сканирования явно отключено CGI scanning (https://www.tenable.com/blog/nessus-web-application-scanning-new-plugins-configuration), либо отключено тестирование веб-приложений. 

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

Вот так будет выглядеть информация о модуле в веб-интерфейсе Nessus.

Для поиска возможных путей нам необходим список версий, а также возможные именования. Все это можно получить из официального репозитория Adminer - https://github.com/vrana/adminer/. Я составил полный список возможных именований с учетом доступных языков - https://github.com/kaimi-io/web-fuzz-wordlists/blob/master/adminer.txt

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

prefix_list = make_list("adminer-", "editor-", "adminer");
# Versions up to current for 4/10/2019
version_list = make_list("","4.7.1","4.7.0","4.6.3","4.6.2","4.6.1","4.6.0","4.5.0","4.4.0","4.3.1","4.3.0","4.2.5","4.2.4","4.2.3","4.2.2","4.2.1","4.2.0","4.1.0","4.0.3","4.0.2","4.0.1","4.0.0","3.7.1","3.7.0","3.6.4","3.6.3","3.6.2","3.6.1","3.6.0","3.5.1","3.5.0","3.4.0","3.3.4","3.3.3","3.3.1","3.3.0","3.2.2","3.2.1","3.2.0","3.1.0","3.0.1","3.0.0");
# More languages are available according to https://github.com/vrana/adminer
suffix_list = make_list("-en.php", "-mysql-en.php", "-mysql.php", ".php", "/");
found_list = make_list();
found_list_ver = make_list();
found_ctr = 0;
high_severity = 0;
dirs = list_uniq(make_list(cgi_dirs(), ""));
foreach dir (dirs)
{
    path = dir + '/';
    foreach prefix (prefix_list)
    {
        foreach version (version_list)
        {
            foreach suffix (suffix_list)
            {
                # path/ + adminer- + 4.1.0 + -en.php
                url = path + prefix + version + suffix;
                res = http_send_recv3(
                    method : "GET",
                    port : port,
                    item : url
                );
                if (isnull(res))
                    continue;
    
                match = pregmatch(pattern: '<span class="version">([0-9\\.]+)</span>', string: res[2], icase: TRUE);
                if (!empty_or_null(match))
                {
                    # LOAD DATA LOCAL INFILE disabled since 4.6.3
                    if (match[1] =~ "^(?:[1-4]\.[0-6]\.[0-2]|[1-3]\.[0-9]\.[0-9])$")
                        high_severity = 1;
    
                    found_list[found_ctr] = url;
                    found_list_ver[found_ctr] = match[1];
    
                    found_ctr++;
                }
            }
        }
    }
}
if (found_ctr > 0)
{
    report = NULL;
    if (report_verbosity > 0)
    {
        report += '\nThe following instance of Adminer was detected on the remote host: \n';
        report += '\n';
        for (i = 0; i < found_ctr; i++)
        {
            url = found_list[i];
            version = found_list_ver[i];
            report += 'Adminer Version\t: ' + version + '\n';
            report += 'URL\t\t: ' + build_url(port: port, qs: url) + '\n';
            report += '\n';
        }
        if (high_severity)
            report += '\nDiscovered versions may be susceptible to LOAD DATA LOCAL INFILE attack\n';
    }
    if (high_severity)
        security_hole(port: port, extra: report);
    else
        security_note(port: port, extra: report);
}
else
{
    audit(AUDIT_WEB_APP_NOT_AFFECTED, app, build_url(port: port, qs:"/"));
}

Здоровенный фрагмент кода. В общем, исходя из репозитория, мы составили список версий, префиксов и суффиксов именования путей, по которым может быть расположен Adminer. 

Объявили несколько переменных (массивы для хранения пути, версии, общий счетчик числа обнаружений и флажок повышенной критичности). Далее мы начинаем процесс сканирования, используя при этом обнаруженные ранее пути. Формируем путь для проверки и делаем обычный GET-запрос. 

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

После проверки всех директорий генерируем текст для отчета, где указываем пути, обнаруженные версии и в зависимости от этого возвращаем, что ничего не нашлось (AUDIT_WEB_APP_NOT_AFFECTED), уязвимость низкого уровня (если версия >= 4.6.3), иначе высокого.

Вот так выглядят результаты работы модуля в веб-интерфейсе:

Как я упоминал, модуль также может быть запущен из командной строки следующим образом:

/opt/nessus/bin/nasl -t 192.168.1.1 ./adminer.nasl

Подробнее можно почитать тут.

Наконец, после того, как модуль написан и перемещен в директорию с другими модулями, необходимо обновить БД плагинов (https://community.tenable.com/s/article/Rebuild-the-Plugin-Database):

/opt/nessus/sbin/nessuscli fix --set nasl_no_signature_check=yes
service nessusd stop
/opt/nessus/sbin/nessusd -R
service nessusd start

Первая команда отключает проверку подписи у используемых плагинов. Все готово, можно пользоваться. Для желающих почитать более структурированное описание процесса разработки модулей - можно полистать книгу Nessus Network Auditing, издание старое, но представление о процессе и доступном API дает.

Модуль из статьи: adminer_detect.nasl.zip

Источник


Report Page