Certificados curinga com nomes de host curtos?

6

Estou tentando gerar um certificado com o seguinte subjectAltName :

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

Eu gero o CSR via OpenSSL e obtenho o certificado dos Serviços de Certificados do Microsoft Active Directory. O certificado funciona bem para os seguintes nomes alternativos:

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

Mas, *.hostname simplesmente não funciona. Testando com Curl, recebo a seguinte saída:

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

Se, por outro lado, adicionar 'm.example' como subjectAltName , funcionará. Assim, o caractere curinga com nome de host reduzido apenas se recusa a funcionar.

    
por Jakov Sosic 13.03.2015 / 12:26

2 respostas

9

Experiência pessoal

Um tempo atrás eu tive um problema semelhante.

Eu configurei um DNS local para servidores Windows e Linux com o .staging como TLD. Para economizar na criação e assinatura de certificados para cada host virtual e evitar ter que configurar novos endereços IP (servidores da Web não-SNI), criei um chave e cert para *.staging mas todos os clientes que eu tentei (incluindo curl) apenas relatou que o nome da entidade do certificado *.staging não corresponde ao host de destino nome sempre que tentei carregar hosts virtuais em nosso servidor Staging usando TLS.

RFCs relevantes

Eu passei muito tempo tentando descobrir por que o certificado curinga que eu havia gerado para *.staging não funcionaria. Eu tinha lido todos os RFCs relevantes, mas nenhum deles especificamente declarou que tal certificado curinga era inválido ou ilegal.

Respostas do Exchange da pilha de segurança

Eu finalmente me iluminei depois de ler esta excelente resposta do Security Stack Exchange .

What matters is what SSL clients will accept as a "valid certificate", i.e. a certificate including a name which "matches" the intended server name (the one included in the URL). This is nominally specified in RFC 2818, section 3.1, and it allows many kinds of wildcard names, including things like "www.*.*c*", matching (theoretically) any server name containing three components, the first being "www" and the third containing at least one "c".

...

So browser vendors made their own schemes and restrictions. Much later, a new RFC (6125, from March 2011) was published, with section 6.4.3 dedicated to the processing of wildcard names in certificates. What RFC 6125 describes is more in tune with the reality, and is a "proposed standard", so there is at least some will, at some level, to make it happen. However, nothing in RFC 6125 mandates rejection of *.com; yet browsers do reject it.

A resposta aceita para Um certificado SSL curinga pode ser emitido para um segundo nível domínio? também mereceu um voto para cima.

Editar

Eu percebi que, além de contar a frustração pessoal, minha resposta realmente não adiciona muito além de links para os RFCs e os relevantes respostas no Security Stack Exchange; Eu pensei em colocar mais esforço e pesquise o código-fonte atual relevante usado pelo Chromium e pelo Firefox.

Observe que os comentários no código-fonte do Chromium mencionam explicitamente domínios desconhecidos de nível superior (como *.intranet ) não são permitidos.

Além disso, não há referência a uma opção configurável pelo usuário que possa substituir esse comportamento.

código fonte do Mozilla

De repositório Mercurial mozilla-central

Like NSS, require at least two labels to follow the wildcard label.

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.
}

Código-fonte do Chromium

De Chromium Git Repository

Do not allow wildcards for public/ICANN registry controlled domains - that is, prevent *.com or *.co.uk as valid presented names

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.

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;
}

Os comentários em registry_controlled_domain.h também são relevantes:

The RegistryControlledDomainService examines the hostname of a GURL passed to it and determines the longest portion that is controlled by a registrar. Although technically the top-level domain (TLD) for a hostname is the last dot-portion of the name (such as .com or .org), many domains (such as co.uk) function as though they were TLDs, allocating any number of more specific, essentially unrelated names beneath them. For example, .uk is a TLD, but nobody is allowed to register a domain directly under .uk; the "effective" TLDs are ac.uk, co.uk, and so on. We wouldn't want to allow any site in *.co.uk to set a cookie for the entire co.uk domain, so it's important to be able to identify which higher-level domains function as effective TLDs and which can be registered.

Ambos os projetos Chromium e Mozilla baseiam sua definição de um efetivo TLD na Lista de Sufixo Público publicada pela Mozilla.

    
por 13.03.2015 / 13:21
6

Os clientes HTTPS devem se recusar a corresponder aos curingas do TLD, como *.com ou *.net (ou mesmo * ) por motivos de segurança: nenhum certificado individual deve reivindicar autoridade sobre um TLD inteiro.

Agora, como o cliente deve descobrir se o exemplo é um TLD (correspondência *.example proibido) ou um formato curto (correspondência permitida)? Particularmente, considerando que novos DPNs surgem a cada dois dias e que qualquer lista de TLDs estáticos estaria desatualizada em breve.

Assim, os clientes simplesmente se recusam a corresponder a qualquer curinga *.XYZ e esperam ver pelo menos dois pontos em um caractere curinga.

Observe que eles ainda devem manter listas negras com curingas como *.co.uk *.co.jp etc.

    
por 13.03.2015 / 12:39