web-dev-qa-db-fra.com

Firefox 54 a cessé de faire confiance aux certificats auto-signés

Avec la récente mise à jour de Firefox 54, mon certificat SSL localhost auto-signé a cessé d'être approuvé.

J'utilise un script Firefox AutoConfigure pour installer ce certificat. Cette technique fonctionne avec succès depuis plusieurs années. Firefox utilise son propre magasin de certificats, cert8.db, qui contient le certificat, vérifié à l'aide des préférences de Firefox, Options avancées, Certificats, Afficher les certificats, Autorités.

Ceci est reproductible à la fois sur MacOS et Windows. J'ai joint un exemple de certificat pour référence. Ceci est identique à celui que nous installerions.

Qu'est-ce qui a changé dans Firefox 54? J'ai examiné le changelog et je ne trouve rien de spécifique à la façon dont il approuve les certificats.

Edit: Lien vers le bogue Firefox ayant probablement introduit cette modification: firefox#1294580

-----BEGIN CERTIFICATE-----
MIID/DCCAuSgAwIBAgIEDZj+fTANBgkqhkiG9w0BAQsFADCBmjELMAkGA1UEBhMC
VVMxCzAJBgNVBAgTAk5ZMRIwEAYDVQQHEwlDYW5hc3RvdGExGzAZBgNVBAoTElFa
IEluZHVzdHJpZXMsIExMQzEbMBkGA1UECxMSUVogSW5kdXN0cmllcywgTExDMRww
GgYJKoZIhvcNAQkBFg1zdXBwb3J0QHF6LmlvMRIwEAYDVQQDEwlsb2NhbGhvc3Qw
HhcNMTcwMjEyMDMzMjEwWhcNMzcwMjEyMDMzMjEwWjCBmjELMAkGA1UEBhMCVVMx
CzAJBgNVBAgTAk5ZMRIwEAYDVQQHEwlDYW5hc3RvdGExGzAZBgNVBAoTElFaIElu
ZHVzdHJpZXMsIExMQzEbMBkGA1UECxMSUVogSW5kdXN0cmllcywgTExDMRwwGgYJ
KoZIhvcNAQkBFg1zdXBwb3J0QHF6LmlvMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCemwdWhvytOwhsRyEo/9ck3nKP
oBvMdkaiXKbMWlYZfYyb/EsJzw/LiEqGGhflWjneQLcgq0nuTtRaA9cm/vgPtVRX
OHewJeYBI2C4avJyjdFfQYHJKxuLi3nwmZ5JwcDm04H6SADwdyQuYB4AFr32uY5D
3id0gyDV+EX9sSOPThtdBpEbaBcFmAdAGdQUCzSJyi4Yu6UkIs7OPBHp9lOvm8VQ
r6ZVnqdFEXmxgpgMS0sQwDwZnBB3hFcVmE/sYy+2gV/h+yvRUjgqwC/SoLh9f4D0
eG19E3OEmsSyFM9K2Wl4ltOE/Aq1KFm7dPw34nDKxYcVDpm6JczWycbCi4zjAgMB
AAGjSDBGMCUGA1UdEQQeMByCCWxvY2FsaG9zdIIPbG9jYWxob3N0LnF6LmlvMB0G
A1UdDgQWBBT3Qs6/qQSmunLIGKQxz3GBO+RgIzANBgkqhkiG9w0BAQsFAAOCAQEA
lVI3sWr6wTtVtc7gsV9Kk99xNOUm5W2kp/Ot5CHvUIw68Ar1WIiouWT9BbjkvFc+
QpbtqKhluTdHI1/JP44r7A8qMApyYQLhw3AS/WTzRoOBOECJk3hYgGBIxAaoqvKY
HKCOULTqkoX8pgNhYobebn/BpeoSvXW+oxT21y7ElE01eMtrLsqXKaN5FODxVzJq
7jatxCaRZCy2Ki3R0cB5ZMIVvWSDeT1TLgh5UKWdldNsTdTNhbQSdm8ayU0uj4fH
tKqwh9lKvrBJiawghmADjZjeNEQzIJfjznF/soqVZnRNZO/phDH327lDE2UcD1IN
k4BqNRJmz5lrQeYz8GcfYA==
-----END CERTIFICATE-----
15
tresf

Pour imiter les exigences de la chaîne de certification imposées par Firefox 54, les éléments suivants sont requis:

  1. Une paire de clés marquée comme étant une autorité de certification racine, capable de générer un certificat SSL.
  2. Deuxième paire de clés marquée pour SSL qui obtient un certificat chaîné de Root-CA

Pour illustrer cette opération avec Java keytool, notamment les étapes permettant de créer des magasins de clés privés:

# Create a Root-CA private keystore capable of issuing SSL certificates
keytool -genkeypair -noprompt -alias my-ca -keyalg RSA -keysize 2048 -dname CN=localhost -validity 3650 -keystore .\my-ca.jks -storepass pass77 -keypass pass77 -ext ku:critical=cRLSign,keyCertSign -ext bc:critical=ca:true,pathlen:1

# Export the Root-CA certificate, to be used in the final SSL chain
keytool -exportcert -alias my-ca -keystore .\my-ca.jks -storepass pass77 -keypass pass77 -file .\my-ca.crt -rfc -ext ku:critical=cRLSign,keyCertSign -ext bc:critical=ca:true,pathlen:1

# Create a container SSL private keystore (external localhost.foo.bar dns entry optional:IE11 domain intranet policy)
keytool -genkeypair -noprompt -alias my-ssl -keyalg RSA -keysize 2048 -dname CN=localhost -validity 3650 -keystore .\my-ssl.jks -storepass pass77 -keypass pass77 -ext ku:critical=digitalSignature,keyEncipherment -ext eku=serverAuth,clientAuth -ext san=dns:localhost,dns:localhost.foo.bar -ext bc:critical=ca:false

# Create a certificate signing request (CSR) from our SSL private keystore
keytool -certreq -keyalg RSA -alias my-ssl -file .\my-ssl.csr -keystore .\my-ssl.jks -keypass pass77 -storepass pass77

# Issue an SSL certificate from the Root-CA private keystore in response to the request (external localhost.foo.bar dns entry optional)
keytool -keypass pass77 -storepass pass77 -validity 3650 -keystore .\my-ca.jks -gencert -alias my-ca -infile .\my-ssl.csr -ext ku:critical=digitalSignature,keyEncipherment -ext eku=serverAuth,clientAuth -ext san=dns:localhost,dns:localhost.foo.bar -ext bc:critical=ca:false -rfc -outfile .\my-ssl.crt

# Import Root-CA certificate into SSL private keystore
keytool  -noprompt -import -trustcacerts -alias my-ca -file my-ca.crt -keystore my-ssl.jks -keypass pass77 -storepass pass77

# Import an SSL (chained) certificate into keystore
keytool -import -trustcacerts -alias my-ssl -file my-ssl.crt -keystore my-ssl.jks -keypass pass77 -storepass pass77 -noprompt

Une fois cette opération effectuée, seul le certificat Root-CA doit être approuvé par Firefox et peut être importé à l'aide de l'interface graphique ou du script AutoConfig.

Le serveur SSL doit être redémarré à l'aide du nouveau magasin de clés privé SSL, qui contiendra la chaîne de confiance pour fonctionner via SSL.

Puisque my-ssl.jks contient toute la chaîne de confiance, my-ca.jks, my-ca.crt, my-ssl.crt et my-ssl.csr peuvent tous être supprimés en toute sécurité (en supposant que my-ca.crt a été importé correctement)

8
tresf

Inspiré par la réponse de @tresf et largement basé sur blogpost Comment créer votre propre autorité de certification SSL pour le développement HTTPS local par Brad Touesnard, j'ai créé un ensemble de commandes utilisant openssl.

# Generate the root key
openssl genrsa -des3 -out myCA.key 2048

# Generate a root-certificate based on the root-key
openssl req -x509 -new -nodes -key myCA.key -sha256 -days 1825 -out myCA.pem

# Generate a new private key
openssl genrsa -out example.com.key 2048

# Generate a Certificate Signing Request (CSR) based on that private key
openssl req -new -key example.com.key -out example.com.csr

# Create a configuration-file
echo \
"authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = example.com
"> example.com.conf

# Create the certificate for the webserver to serve
openssl x509 -req -in example.com.csr -CA myCA.pem -CAkey myCA.key -CAcreateserial \
-out example.com.crt -days 1825 -sha256 -extfile example.com.conf

Comment utiliser ces fichiers

1. Laissez votre autorité de certification être approuvée par votre navigateur/votre trousseau

Ajoutez myCa.pem à votre navigateur/à votre trousseau pour faire confiance aux certificats signés par votre nouveau certificat racine.

2. Signer les demandes avec votre certificat

Ajoutez example.com.crt et example.com.key à la configuration de votre serveur Web pour signer les demandes adressées à votre domaine.

9
Zombaya

Comme @tresf et @Zombaya l'ont indiqué, Firefox requiert deux certificats:

  • Un certificat d'autorité
  • Un certificat de développement

Le certificat d'autorité est utilisé pour signer le certificat de développement. Le certificat de développement est lié à un port HTTP. Le serveur Web écoute ce port pour les demandes.

Environnement de développement Windows

D'autres réponses expliquent quoi faire dans les environnements Java et Unix. Voici ce que je fais dans mon environnement de développement Windows. Cela crée des certificats approuvés par Firefox, Chrome et Internet Explorer:

Remplacez DNS par une entrée dans le fichier C:\Windows\System32\drivers\etc\hosts.

127.0.0.1  dev.brainstorm.com

Créez les certificats d'autorité et de développement et stockez-les dans le magasin de certificats de l'ordinateur local à l'aide de PowerShell. Remplacez "Brainstorm" par le nom de votre société et votre entrée DNS. Exécutez PowerShell en tant qu'administrateur.

# Create authority certificate.
# TextExtension adds the Server Authentication enhanced key usage and the CA basic contraint.
$authorityCert = New-SelfSignedCertificate `
    -Subject "CN=Brainstorm CA,OU=IT,O=Brainstorm Certificate Authority,C=US" `
    -KeyAlgorithm RSA `
    -KeyLength 4096 `
    -KeyUsage CertSign, CRLSign, DigitalSignature, KeyEncipherment, DataEncipherment `
    -KeyExportPolicy Exportable `
    -NotBefore (Get-Date) `
    -NotAfter (Get-Date).AddYears(10) `
    -HashAlgorithm SHA256 `
    -CertStoreLocation "Cert:\LocalMachine\My" `
    -FriendlyName "Brainstorm CA" `
    -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1", "2.5.29.19={critical}{text}ca=1")


# Create development certificate.
# Sign it with authority certificate.
# TextExtension adds the Server Authentication enhanced key usage.
$devCert = New-SelfSignedCertificate `
    -Subject "CN=Brainstorm,OU=Application Development,O=Brainstorm,C=US" `
    -DnsName dev.brainstorm.com `
    -KeyAlgorithm RSA `
    -KeyLength 4096 `
    -KeyUsage DigitalSignature, KeyEncipherment, DataEncipherment `
    -KeyExportPolicy Exportable `
    -NotBefore (Get-Date) `
    -NotAfter (Get-Date).AddYears(10) `
    -HashAlgorithm SHA256 `
    -CertStoreLocation "Cert:\LocalMachine\My" `
    -FriendlyName "Brainstorm" `
    -TextExtension @("2.5.29.37={text}1.3.6.1.5.5.7.3.1") `
    -Signer $authorityCert

# Export authority certificate to file.
$directory = "C:\Users\Erik\Documents\Temp\Certificates\"
if(!(test-path $directory))
{
New-Item -ItemType Directory -Force -Path $directory
}
$authorityCertPath = 'Cert:\LocalMachine\My\' + ($authorityCert.ThumbPrint)
$authorityCertFilename = $directory + "Authority.cer"
Export-Certificate -Cert $authorityCertPath -FilePath $authorityCertFilename

# Import authority certificate from file to Trusted Root store.
Import-Certificate -FilePath $authorityCertFilename -CertStoreLocation "Cert:\LocalMachine\Root"

# Delete authority certificate file.
Remove-Item -Path $authorityCertFilename

Accordez au développeur l'autorisation d'héberger un site Web et un service sur des URL et des ports spécifiques (via IIS Express). Utilisez le port SSL standard pour le site Web, utilisez un autre port pour le service. Pourquoi? IIS Express ne peut pas héberger simultanément deux applications sur le même port, différenciées par nom d'hôte. Ils doivent utiliser des ports différents.

netsh http add urlacl url=https://dev.brainstorm.com:443/ user="Erik"
netsh http add urlacl url=https://dev.brainstorm.com:44300/ user="Erik"

Si vous devez supprimer l'autorisation de développeur sur le site Web hôte à l'URL:

netsh http delete urlacl url=https://dev.brainstorm.com:443/
netsh http delete urlacl url=https://dev.brainstorm.com:44300/

Répertoriez les certificats dans le magasin d’ordinateur local.

Get-ChildItem -path "Cert:\LocalMachine\My"

Copiez l'empreinte numérique du certificat de développement (pas le certificat d'autorité).

Répertoriez les certificats liés aux ports HTTP. (IIS Express configure les ports 44300 à 44399 avec son propre certificat SSL.)

netsh http show sslcert

Copiez l'ID de l'application (identique pour tous les ports IIS Express 44300 - 44399). Remplacez le site Web et les ports de service déjà liés par IIS Express par notre certificat de développement (le certhash est l'empreinte numérique présentée ci-dessus). Vous devrez peut-être d'abord exécuter netsh, puis entrer la commande http, puis entrer la commande add sslcert ....

netsh http add sslcert hostnameport=dev.brainstorm.com:443 certhash=FE035397A4C44AB591A1D9D4DC0B44074D0F95BA appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certstore=my
netsh http add sslcert hostnameport=dev.brainstorm.com:44300 certhash=FE035397A4C44AB591A1D9D4DC0B44074D0F95BA appid={214124cd-d05b-4309-9af9-9caa44b2b74a} certstore=my

Si vous devez dissocier les certificats des ports HTTP:

netsh http delete sslcert hostnameport=dev.brainstorm.com:443
netsh http delete sslcert hostnameport=dev.brainstorm.com:44300

Dans Visual Studio, configurez le fichier launchSettings.json du service (dans le dossier Propriétés):

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "https://dev.brainstorm.com:44300/",
      "sslPort": 44300
    }
  },
  "profiles": {
    "Default": {
      "commandName": "IISExpress",
      "use64Bit": true
    }
  }
}

Dans Visual Studio, configurez le fichier launchSettings.json du site Web (dans le dossier Propriétés):

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "https://dev.brainstorm.com/",
      "sslPort": 443
    }
  },
  "profiles": {
    "Default": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "use64Bit": true
    }
  }
}

Configurez IIS Express (dans le dossier .vs/config caché):

<sites>
  <site name="Website" id="1" serverAutoStart="true">
    <application path="/">
      <virtualDirectory path="/" physicalPath="%IIS_SITES_HOME%\WebSite" />
    </application>
    <bindings>
      <binding protocol="https" bindingInformation="*:443:dev.brainstorm.com" />
    </bindings>
  </site>
  <site name="Service" id="2">
    <application path="/">
      <virtualDirectory path="/" physicalPath="%IIS_SITES_HOME%\IIS Service" />
    </application>
    <bindings>
      <binding protocol="https" bindingInformation="*:44300:dev.brainstorm.com" />
    </bindings>
  </site>
  <siteDefaults>
    <logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
    <traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" maxLogFileSizeKB="1024" />
  </siteDefaults>
  <applicationDefaults applicationPool="Clr4IntegratedAppPool" />
  <virtualDirectoryDefaults allowSubDirConfig="true" />
</sites>

Dans Firefox, accédez à about: config et définissez le paramètre security.enterprise_roots.enabled sur true.

4
Erik Madsen

Ce que vous voudrez probablement faire, c'est générer un autre certificat auto-signé avec le même sujet, le même émetteur et la même clé publique que celui que vous essayez de faire confiance. Cependant, au lieu des extensions d'entité finale, vous voudrez spécifier qu'il s'agit d'un certificat d'autorité de certification avec "basicConstraints: cA" et qu'il peut émettre des certificats avec "keyUsage: cRLSign, keyCertSign". Il peut également être judicieux d’ajouter une extension nameConstraints afin de ne pas l’appliquer à un certain ensemble de domaines. Si vous ajoutez ce certificat à la base de données de confiance de Firefox, tout devrait fonctionner comme avant.

0
David Keeler