Назад | Перейти на главную страницу

Подстановочные сертификаты с короткими именами хостов?

Я пытаюсь создать сертификат со следующим subjectAltName:

hostname
*.hostname
hostname.mydomain.local
*.hostname.mydomain.local

Я генерирую CSR через OpenSSL, а затем получаю сертификат из служб сертификации Microsoft Active Directory. Сертификат работает нормально для следующих альтернативных имен:

hostname
hostname.mydomain.local
*.hostname.mydomain.local

Но, *.hostname просто не работает. Тестируя Curl, я получаю следующий результат:

% curl https://m.example/
curl: (51) SSL: certificate subject name '*.example' does not match target host name 'm.example'

Если, с другой стороны, я добавлю m.example как subjectAltName, тогда это работает. Итак, подстановочный знак с сокращенным именем хоста просто отказывается работать.

Личный опыт

Некоторое время назад у меня была аналогичная проблема.

Я настроил локальный DNS для серверов Windows и Linux с .staging в качестве TLD. Чтобы сэкономить на создании и подписании сертификатов для каждого виртуального хоста и избежать необходимости настраивать новые IP-адреса (веб-серверы, отличные от SNI), я создал ключ и сертификат для *.staging но все клиенты, которых я пробовал (включая curl), сообщали только имя субъекта сертификата *.staging не соответствует имени целевого хоста, когда я пытался загрузить виртуальные хосты на наш промежуточный сервер с помощью TLS.

Соответствующие RFC

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

Ответы на Security Stack Exchange

Я в конце концов просветился после прочтения этот отличный ответ Security Stack Exchange.

Важно то, что SSL-клиенты будет принимать как «действительный сертификат», т.е. сертификат, включающий имя, которое «совпадает» с предполагаемым именем сервера (тем, которое включено в URL-адрес). Это номинально указано в RFC 2818, раздел 3.1, и он позволяет использовать множество видов подстановочных имен, в том числе такие, как "www.*.*c*", совпадающее (теоретически) с любым именем сервера, содержащим три компонента, первый из которых"www"а третий содержит хотя бы один"c".

...

Поэтому производители браузеров вводили свои схемы и ограничения. Намного позже новый RFC (6125, с марта 2011 г.), с раздел 6.4.3 посвящен обработке подстановочных имен в сертификатах. То, что описывает RFC 6125, больше соответствует действительности, и является «предлагаемый стандарт», так что на каком-то уровне есть хоть какая-то воля, чтобы это произошло. Однако ничто в RFC 6125 не требует отказа от *.com; еще браузеры делать отклонить это.

В принятый ответ к Можно ли выдать подстановочный SSL-сертификат для домена второго уровня? также заслуживает голосования.

редактировать

Я подумал, что помимо пересказа личного разочарования, мой ответ на самом деле ничего не добавляет, кроме ссылки на RFC и соответствующие ответы на Security Stack Exchange; Я подумал, что приложу больше усилий и найду актуальный исходный код, используемый Chromium и Firefox.

Обратите внимание, что комментарии в исходном коде Chromium явно упоминают, что неизвестные домены верхнего уровня (например, *.intranet) запрещены.

Также: нет ссылки на настраиваемый пользователем параметр, который может переопределить это поведение.

Исходный код Mozilla

Из Mercurial Repository в mozilla-central

Как и в случае с NSS, после метки с подстановочным знаком требуется как минимум две метки.

if (isWildcard) {
  // If the DNS ID ends with a dot, the last dot signifies an absolute ID.
  size_t labelCount = (labelLength == 0) ? dotCount : (dotCount + 1);

  // Like NSS, require at least two labels to follow the wildcard label.
  //
  // TODO(bug XXXXXXX): Allow the TrustDomain to control this on a
  // per-eTLD+1 basis, similar to Chromium. Even then, it might be better to
  // still enforce that there are at least two labels after the wildcard.
  if (labelCount < 3) {
    return false;
  }
  // XXX: RFC6125 says that we shouldn't accept wildcards within an IDN
  // A-Label. The consequence of this is that we effectively discriminate
  // against users of languages that cannot be encoded with ASCII.
  if (StartsWithIDNALabel(hostname)) {
    return false;
  }

  // TODO(bug XXXXXXX): Wildcards are not allowed for EV certificates.
  // Provide an option to indicate whether wildcards should be matched, for
  // the purpose of helping the application enforce this.
}

Исходный код Chromium

Из Репозиторий Chromium Git

Запрещать использование подстановочных знаков для общедоступных доменов / доменов, контролируемых реестром ICANN, то есть предотвращать использование * .com или * .co.uk в качестве допустимых представленных имен.

Кроме того, неявно предотвращаются также неизвестные домены верхнего уровня (например, домены «интрасети» или новые TLD / gTLD, еще не добавленные в набор данных домена, контролируемого реестром).

if (!reference_domain.empty()) {
  DCHECK(reference_domain.starts_with("."));

  // Do not allow wildcards for public/ICANN registry controlled domains -
  // that is, prevent *.com or *.co.uk as valid presented names, but do not
  // prevent *.appspot.com (a private registry controlled domain).
  // In addition, unknown top-level domains (such as 'intranet' domains or
  // new TLDs/gTLDs not yet added to the registry controlled domain dataset)
  // are also implicitly prevented.
  // Because |reference_domain| must contain at least one name component that
  // is not registry controlled, this ensures that all reference domains
  // contain at least three domain components when using wildcards.
  size_t registry_length =
      registry_controlled_domains::GetRegistryLength(
          reference_name,
          registry_controlled_domains::INCLUDE_UNKNOWN_REGISTRIES,
          registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);

  // Because |reference_name| was already canonicalized, the following
  // should never happen.
  CHECK_NE(std::string::npos, registry_length);

  // Account for the leading dot in |reference_domain|.
  bool is_registry_controlled =
      registry_length != 0 &&
      registry_length == (reference_domain.size() - 1);

  // Additionally, do not attempt wildcard matching for purely numeric
  // hostnames.
  allow_wildcards =
      !is_registry_controlled &&
      reference_name.find_first_not_of("0123456789.") != std::string::npos;
}

Комментарии в registry_controlled_domain.h также актуальны:

RegistryControlledDomainService проверяет имя хоста переданного ему GURL и определяет самую длинную часть, которая контролируется регистратором. Хотя технически домен верхнего уровня (TLD) для имени хоста является последней частью имени с точкой (например, .com или .org), многие домены (например, co.uk) функционируют, как если бы они были TLD, выделяя любые ряд более конкретных, по существу не связанных имен под ними. Например, .uk - это TLD, но никому не разрешено регистрировать домен непосредственно под .uk; «эффективными» TLD являются ac.uk, co.uk и т. д. Мы бы не хотели, чтобы какой-либо сайт в * .co.uk устанавливал cookie для всего домена co.uk, поэтому важно иметь возможность определять, какие домены более высокого уровня функционируют как эффективные TLD, а какие могут быть зарегистрированы.

И проекты Chromium, и Mozilla основывают свое определение эффективный TLD на Список общедоступных суффиксов как опубликовано Mozilla.

Клиенты HTTPS должны отказаться от сопоставления подстановочных знаков TLD, например *.com или *.net (или даже *) по соображениям безопасности: ни один сертификат не должен претендовать на полномочия в отношении всего TLD.

Теперь, как клиент должен узнать, является ли .example TLD (соответствие *.example запрещено) или краткая форма (соответствие разрешено)? Особенно с учетом того, что новые TLD появляются через день, и любой статический список TLD скоро устареет.

Таким образом, клиенты просто отказываются соответствовать любому подстановочному знаку *.XYZ и ожидайте увидеть как минимум две точки в подстановочном знаке.

Обратите внимание, что они по-прежнему должны поддерживать черные списки с подстановочными знаками, например *.co.uk *.co.jp и т.п.