DevGang
Авторизоваться

Использование nmap для непрерывного мониторинга уязвимостей

Мы будем использовать 'nmap' и Checkson для мониторинга демонов SSH на предмет CVE.

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

  • Обеспечение безопасности вашей цепочки поставок программного обеспечения
  • Защита ваших систем от внешнего доступа с помощью межсетевых экранов и VPN.
  • Обеспечение постоянного обновления операционной системы с точки зрения обновлений безопасности.
  • Непрерывное сканирование на наличие уязвимостей в системах
  • Постоянное сканирование на наличие уязвимостей извне

В этом посте мы хотим сосредоточиться на последнем пункте в этом списке. Использование инструментов сканирования уязвимостей для внешнего мониторинга ваших систем.

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

Очень мощный инструмент для сканирования уязвимостей — это почтенный 'nmap'. В качестве примера мы будем использовать 'nmap' для мониторинга демона SSH на наших серверах на предмет уязвимостей.

Возьмите следующую команду:

nmap -p 22 -sV -oX /tmp/nmap-output.xml --script vulners example.com
  • -p 22: сканировать только порт 22 (SSH).
  • -sV: определить версию служб на основе их проверки.
  • -oX /tmp/nmap-output.xml: вывести результат сканирования в виде XML-файла.
  • -script vulners: используйте скрипт vulners. Будет использована обнаруженная версия и проверен API на наличие CVE.
  • example.com: сервер для проверки

Пример вывода может выглядеть так:

22/tcp  open  ssh      OpenSSH 8.9p1 Ubuntu 3ubuntu0.6 (Ubuntu Linux; protocol 2.0)
| vulners: 
|   cpe:/a:openbsd:openssh:8.9p1: 
|_    	CVE-2023-51767	3.5	https://vulners.com/cve/CVE-2023-51767

'nmap' обнаружил, что версия сервера OpenSSH — '8.9p1'. Для этой версии существует CVE.

Конечно, вы можете сделать это и для других работающих служб, например. для веб-серверов, работающих на портах 80 и 443.

Наша цель — не только выполнить это сканирование один раз, но и делать это постоянно. Для этого мы будем использовать Checkson. Мы напишем сценарий, который будет выполнять сканирование с использованием 'nmap' и сообщать Checkson об ошибке, если будут обнаружены какие-либо CVE. В качестве дополнительного бонуса мы создадим вложение к проверке с HTML-отчетом о результатах. Во-первых, сценарий. Мы будем использовать для этого Python и вызывать 'nmap' через модуль 'subprocess':

from subprocess import check_output, call
import xml.etree.ElementTree as ET
import os
import sys


def main():
    cmd = "nmap -p 22 -sV -oX /tmp/nmap-output.xml --script vulners example.com"
    nmap_output = check_output(cmd, shell=True)
    print("nmap output was: ", nmap_output)


if __name__ == '__main__':
    main()

Как видите, сканирование выполняется с помощью 'nmap'. Он сохраняет выходные данные в файл XML: /tmp/nmap-output.xml.

Выходной XML-файл выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE nmaprun>
<?xml-stylesheet href="file:///usr/bin/../share/nmap/nmap.xsl" type="text/xsl"?>
<nmaprun scanner="nmap" args="nmap -p 22 -sV -oX /tmp/nmap-output.xml -&#45;script vulners example.com" start="1712122535" startstr="Wed Apr  3 07:35:35 2024" version="7.80" xmloutputversion="1.04">
  <scaninfo type="connect" protocol="tcp" numservices="1" services="22"/>
  <verbose level="0"/>
  <debugging level="0"/>
  <host starttime="1712122535" endtime="1712122536">
    <status state="up" reason="syn-ack" reason_ttl="0"/>
    <address addr="100.100.100.100" addrtype="ipv4"/>
    <hostnames>
      <hostname name="example.com" type="user"/>
    </hostnames>
    <ports>
      <port protocol="tcp" portid="22">
        <state state="open" reason="syn-ack" reason_ttl="0"/>
        <service name="ssh" product="OpenSSH" version="8.9p1 Ubuntu 3ubuntu0.6" extrainfo="Ubuntu Linux; protocol 2.0" ostype="Linux" method="probed" conf="10">
          <cpe>cpe:/a:openbsd:openssh:8.9p1</cpe>
          <cpe>cpe:/o:linux:linux_kernel</cpe>
        </service>
        <script id="vulners" output="&#xa;  cpe:/a:openbsd:openssh:8.9p1: &#xa;    &#x9;CVE-2023-51767&#x9;3.5&#x9;https://vulners.com/cve/CVE-2023-51767">
          <table key="cpe:/a:openbsd:openssh:8.9p1">
            <table>
              <elem key="id">CVE-2023-51767</elem>
              <elem key="is_exploit">false</elem>
              <elem key="cvss">3.5</elem>
              <elem key="type">cve</elem>
            </table>
          </table>
        </script>
      </port>
    </ports>
    <times srtt="33172" rttvar="25279" to="134288"/>
  </host>
  <runstats>
    <finished time="1712122536" timestr="Wed Apr  3 07:35:36 2024" elapsed="0.95" summary="Nmap done at Wed Apr  3 07:35:36 2024; 1 IP address (1 host up) scanned in 0.95 seconds" exit="success"/>
    <hosts up="1" down="0" total="1"/>
  </runstats>
</nmaprun>

Давайте расширим скрипт для анализа CVE. Пока мы этим занимаемся, мы добавим возможность игнорировать CVE, которые мы проанализировали, но считаем безвредными, например потому что нет возможности их практически эксплуатировать. Мы будем использовать переменную env под названием $IGNORED_CVES.

from subprocess import check_output, call
import xml.etree.ElementTree as ET
import os
import sys


def main():
    cves = []
    ignored_cves = os.environ.get('IGNORED_CVES', '').split(',')

    cmd = "nmap -p 22 -sV -oX /tmp/nmap-output.xml --script vulners example.com"
    nmap_output = check_output(cmd, shell=True)
    print("nmap output was: ", nmap_output)

    xml = ET.parse('/tmp/nmap-output.xml')
    root = xml.getroot()
    xpath = './/host/ports/port'
    for port in root.findall(xpath):
        table = port.find('script').find('table')
        for vulnerability in table.findall('table'):
            vulnerability_id = vulnurability.find('.//elem[@key="id"]').text
            cve_score = vulnerability.find('.//elem[@key="cvss"]').text
            print(vulnerability_id, cve_score)
            if vulnerability_id not in ignored_cves:
                cves.append(vulnerability_id)

    print("Non ignored CVEs: ", cves)
    if len(cves) > 0:
        print("At last one relevant CVE found, exiting with status 1")
        sys.exit(1)

    print("No relevant CVEs found, exiting with status 0")
    sys.exit(0)


if __name__ == '__main__':
    main()

Это завершится с кодом завершения 1, если есть неигнорированные CVE. Код выхода, отличный от 0, сообщит Checkson, что проверка должна быть КРИТИЧЕСКОЙ и уведомления должны быть отправлены.

Мы можем выполнить сценарий и игнорировать определенные CVE следующим образом:

export IGNORED_CVES="CVE-2023-51385,CVE-2023-51384"
python3 check.py

Давайте добавим еще одну вещь: отчет о результатах в формате HTML. Для вывода XML с помощью nmap этого можно добиться с помощью XSLT для преобразования XML в HTML. Для этого есть инструмент командной строки: 'xsltproc'. Мы просто вызовем это из Python. Файл помещается в каталог $CHECKSON_DIR/attachments, поэтому Checkson сделает его доступным в качестве вложения. Это вложение будет доступно через веб-приложение Checkson. Полный список скрипта Python выглядит так:

from subprocess import check_output, call
import xml.etree.ElementTree as ET
import os
import sys


def main():
    cves = []
    ignored_cves = os.environ.get('IGNORED_CVES', '').split(',')

    cmd = "nmap -p 22 -sV -oX /tmp/nmap-output.xml --script vulners example.com"
    nmap_output = check_output(cmd, shell=True)
    print("nmap output was: ", nmap_output)

    create_html_report()

    xml = ET.parse('/tmp/nmap-output.xml')
    root = xml.getroot()
    xpath = './/host/ports/port'
    for port in root.findall(xpath):
        table = port.find('script').find('table')
        for vulnerability in table.findall('table'):
            vulnerability_id = vulnurability.find('.//elem[@key="id"]').text
            cve_score = vulnerability.find('.//elem[@key="cvss"]').text
            print(vulnerability_id, cve_score)
            if vulnerability_id not in ignored_cves:
                cves.append(vulnerability_id)

    print("Non ignored CVEs: ", cves)
    if len(cves) > 0:
        print("At last one relevant CVE found, exiting with status 1")
        sys.exit(1)

    print("No relevant CVEs found, exiting with status 0")
    sys.exit(0)


def create_html_report():
    checkson_dir = os.environ.get('CHECKSON_DIR', '/tmp')
    if not os.path.exists(checkson_dir):
        os.makedirs(checkson_dir)
    call(f'xsltproc /tmp/nmap-output.xml -o {checkson_dir}/attachments/nmap-output.html', shell=True)


if __name__ == '__main__':
    main()

Чтобы иметь возможность развернуть эту проверку в Checkson, остается только обернуть ее в контейнер Docker. Следующий файл Dockerfile устанавливает необходимые части программного обеспечения 'nmap' и 'xsltproc':

FROM alpine:3
RUN apk add --update nmap nmap-scripts libxslt bash python3
ADD main.py /check.py
CMD [ "python", "/check.py" ]

Вы можете собрать этот образ Docker локально и протестировать его:

Все готово для развертывания чека в Checkson. После развертывания проверки вы получите сообщение по электронной почте или в Slack, когда будут обнаружены новые CVE для демона SSH на вашем сервере серверов.

Это был пример использования 'nmap' для мониторинга уязвимостей. Конечно, мы коснулись лишь поверхности. Есть целая категория скриптов для 'nmap' на всевозможные уязвимости.

Источник:

#Python
Комментарии
Чтобы оставить комментарий, необходимо авторизоваться

Присоединяйся в тусовку

В этом месте могла бы быть ваша реклама

Разместить рекламу