Статьи

Обеспечение безопасности в сети, один модульный тест за раз

Первоначально написано как часть Sysadvent 2013 .

Написание автоматических тестов для вашего кода — это одна из тех вещей, которые, попав в него, больше никогда не захотят видеть код без тестов. Зачем писать страницы и страницы документации о том, как что-то должно работать, когда вы можете написать тесты, чтобы показать, как именно что-то работает? Глядя на количество и качество инструментов и платформ тестирования (таких как cucumber, rspec, Test Kitchen , Server Spec , Beaker , Casper и Jasmine и др.), Которые появились в прошлом году или около того, я, очевидно, не единственный человек, у которого есть вещь для тестирования утилит.

Еще одна вещь, которая меня интересует, — это безопасность веб-приложений, так что эта статья посвящена использованию инструментов и методов модульного тестирования, чтобы избежать распространенных проблем безопасности веб-приложений. Я использую Ruby в примерах, но вы можете быстро преобразовать их в другие языки, если хотите.

В беде любой выход хорош

Давайте начнем с чего-то простого. Случайное раскрытие приложений на портах TCP может привести к потере данных или создать вектор для атаки. Возможно, ваш основной веб-сайт очень защищен, но вы оставили порт для своей базы данных открытым для Интернета. Это конфигурация сервера, эквивалентная забыванию запереть заднюю дверь.

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

require "tempfile"
require "nmap/program"
require "nmap/xml"

describe "the scanme.nmap.org website" do
  file = Tempfile.new("nmap.xml")
  before(:all) do
    Nmap::Program.scan do |nmap|
      nmap.xml = file.path
      nmap.targets = "scanme.nmap.org"
    end
  end

  @open_ports = []
  Nmap::XML.new("scan.xml") do |xml|
    xml.each_host do |host|
      host.each_port do |port|
        @open_ports << port.number if port.state == :open
      end
    end
  end
end

Используя приведенный выше код, мы можем писать тесты, такие как:

it "should have two ports open" do
 @open_ports.should have(2).items
end

it "should have port 80 open" do
 @open_ports.should include(80)
end

it "should have port 22 closed" do
 @open_ports.should_not include(22)
end

Мы можем запускать их вручную, но также потенциально как часть непрерывной интеграции или постоянно как часть пакета мониторинга.

Запустить Guantlt

Нам пришлось проделать немало работы, чтобы обернуть Nmap, прежде чем мы смогли написать тесты выше. Разве не было бы хорошо, если бы кто-то уже обернул много полезных инструментов для безопасности? Gauntlt — это просто система тестирования безопасности, основанная на cucumber, которая в настоящее время поддерживает curl, nmap, sslyze, sqlmap, garmr и множество других инструментов в master. Давайте сделаем нечто более продвинутое, чем наш тест сканирования портов выше, проверив URL-адрес на наличие уязвимости SQL-инъекции.

@slow
Feature: Run sqlmap against a target
  Scenario: Identify SQL injection vulnerabilities
    Given "sqlmap" is installed
    And the following profile:
      | name       | value                                      |
      | target_url | http://localhost/sql-injection?number_id=1 |
    When I launch a "sqlmap" attack with:
      """
      python <sqlmap_path> -u <target_url> —dbms sqlite —batch -v 0 —tables
      """
    Then the output should contain:
      """
      sqlmap identified the following injection points
      """
    And the output should contain:
      """
      [2 tables]
      +-----------------+
      | numbers         |
      | sqlite_sequence |
      +-----------------+
      """

Команда Gauntlt публикует множество примеров, подобных этому, вместе с исходным кодом, поэтому начать работу легко. Gauntlt очень мощный, но, как вы увидите из приведенного выше примера, вам нужно немного знать о базовых инструментах, которые он использует. В приведенном выше случае вам нужно знать различные аргументы sqlmap, а также как интерпретировать вывод.

Введите Prodder

Prodder — это инструмент, который я собрал, чтобы автоматизировать несколько конкретных типов тестирования безопасности. Во многих отношениях это очень похоже на Gauntlt; он использует среду тестирования на огурцы и использует некоторые из тех же инструментов (например, nmap и sslyze) под капотом. Однако, вместо универсальной инфраструктуры безопасности, такой как Gauntlt, Prodder более высокого уровня и очень самоуверенный. Вот пример:

Feature: SSL
  In order to ensure secure connections
  I want to check the SSL configuration of my servers
  Background:
    Given "sslyze.py" is installed
    Scenario: Check SSLv2 is disabled
      When we test using the "sslv2" protocol
      Then the exit status should be 0
      And the output should contain "SSLv2 disabled"

    Scenario: Check certificate is trusted
      When we check the certificate
      Then the output should contain "Certificate is Trusted"
      And the output should match /OK — (Common|Subject

Альтернатива) Название соответствия /

      And the output should not contain "Signature Algorithm: md5"
      And the output should not contain "Signature Algorithm: md2"
      And the output should contain "Key Size: 2048"

    Scenario: Check certificate renegotiations
      When we test certificate renegotiation
      Then the output should contain "Client-initiated

Переговоры: отклонены »

      And the output should contain "Secure Renegotiation: Supported"

    Scenario: Check SSLv3 is not using weak ciphers
      When we test using the "sslv3" protocol
      Then the output should not contain "Anon"
      And the output should not contain "96bits"
      And the output should not contain "40bits"
      And the output should not contain " 0bits"

Это немного более высокий уровень, чем пример Gauntlt — он не раскрывает работу sslyze, которая выполняет реальное тестирование. Все, что вам нужно, это понимание сертификатов SSL. Даже если вы не являетесь экспертом по SSL, вы можете принять вышеупомянутое мнение Prodder о том, как хорошо выглядит. В настоящее время Prodder содержит шаги и примеры для сканирования портов, сертификатов SSL и заголовков HTTP, ориентированных на безопасность. Если у вас уже есть набор тестов на основе огурцов (в том числе на основе Gauntlt), вы также можете использовать определения шагов в нем.

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

Я убежден, что мне делать дальше?

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