web-dev-qa-db-fra.com

Comment faire une demande https avec un mauvais certificat?

Dites que je veux obtenir https://golang.org par programme. Actuellement, golang.org (ssl) a un mauvais certificat qui est attribué à *.appspot.com Donc quand j’exécute ceci:

package main

import (
    "log"
    "net/http"
)

func main() {
    _, err := http.Get("https://golang.org/")
    if err != nil {
        log.Fatal(err)
    }
}

Je reçois (comme je m'y attendais)

Get https://golang.org/: certificate is valid for *.appspot.com, *.*.appspot.com, appspot.com, not golang.org

Maintenant, je veux faire confiance à ce certificat moi-même (imaginez un certificat auto-émis où je puisse valider une empreinte digitale, etc.): comment puis-je faire une demande et valider/faire confiance au certificat?

J'ai probablement besoin d'utiliser openssl pour télécharger le certificat, le charger dans mon fichier et remplir tls.Config struct!?

93
topskip

Note de sécurité: Désactiver les contrôles de sécurité est dangereux et doit être évité

Vous pouvez désactiver les contrôles de sécurité globalement pour toutes les demandes du client par défaut:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
    _, err := http.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}

Vous pouvez désactiver le contrôle de sécurité pour un client:

package main

import (
    "fmt"
    "net/http"
    "crypto/tls"
)

func main() {
    tr := &http.Transport{
        TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
    }
    client := &http.Client{Transport: tr}
    _, err := client.Get("https://golang.org/")
    if err != nil {
        fmt.Println(err)
    }
}
204
cyberdelia

Voici un moyen de le faire sans perdre les paramètres par défaut de la DefaultTransport et sans avoir besoin de la fausse demande conformément au commentaire de l'utilisateur.

defaultTransport := http.DefaultTransport.(*http.Transport)

// Create new Transport that ignores self-signed SSL
httpClientWithSelfSignedTLS := &http.Transport{
  Proxy:                 defaultTransport.Proxy,
  DialContext:           defaultTransport.DialContext,
  MaxIdleConns:          defaultTransport.MaxIdleConns,
  IdleConnTimeout:       defaultTransport.IdleConnTimeout,
  ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout,
  TLSHandshakeTimeout:   defaultTransport.TLSHandshakeTimeout,
  TLSClientConfig:       &tls.Config{InsecureSkipVerify: true},
}
13
Jonathan Lin

Toutes ces réponses sont fausses! N'utilisez pas InsecureSkipVerify pour traiter un CN qui ne correspond pas au nom d'hôte. Les développeurs de Go ont imprudemment insisté sur le fait de ne pas désactiver les vérifications de nom d’hôte (qui ont des utilisations légitimes - tunnels, nats, certificats de cluster partagés, etc.), tout en conservant un aspect similaire mais en réalité complètement ignore la vérification du certificat. Vous devez savoir que le certificat est valide et signé par un certificat en lequel vous avez confiance. Mais dans les scénarios courants, vous savez que le CN ne correspond pas au nom d’hôte avec lequel vous vous êtes connecté. Pour ceux-ci, définissez ServerName sur tls.Config. Si tls.Config.ServerName == remoteServerCN, la vérification du certificat réussira. Voici ce que vous voulez. InsecureSkipVerify signifie qu'il n'y a PAS d'authentification; et c'est mûr pour un homme du milieu; vider l'objectif d'utiliser TLS.

Il y a une utilisation légitime pour InsecureSkipVerify: utilisez-le pour vous connecter à un hôte et récupérer son certificat, puis déconnectez-vous immédiatement. Si vous configurez votre code pour utiliser InsecureSkipVerify, c'est généralement parce que vous n'avez pas défini ServerName correctement (cela doit provenir d'une variable d'env ou quelque chose d'autre. N'ayez pas mal au ventre à propos de cette exigence ... faites le correctement).

En particulier, si vous utilisez des certificats de client et comptez sur eux pour l'authentification, vous disposez en réalité d'un faux login qui ne se connecte plus. Refusez le code qui contient InsecureSkipVerify ou vous apprendrez ce qui ne va pas avec cela à la dure!

8
Rob

Si vous souhaitez utiliser les paramètres par défaut du package http, de sorte que vous n'avez pas besoin de créer un nouvel objet Transport et Client, vous pouvez modifier pour ignorer la vérification du certificat comme suit:

tr := http.DefaultTransport.(*http.Transport)
tr.TLSClientConfig.InsecureSkipVerify = true
7
Cornel Damian

Généralement, le domaine DNS de l'URL DOIT correspondre à l'objet du certificat du certificat.

Auparavant, vous pouviez définir le domaine en tant que cn du certificat ou en définissant le domaine en tant que nom alternatif de sujet. 

La prise en charge de cn était obsolète depuis longtemps (depuis 2000 dans RFC 2818 ) et le navigateur Chrome ne le regarde même plus. Aujourd'hui, vous devez disposer du domaine DNS de l'URL comme nom alternatif du sujet. .

RFC 6125 qui interdit de vérifier le cn si SAN pour le domaine DNS est présent, mais pas si SAN pour l'adresse IP est présent. La RFC 6125 répète également que cn est obsolète, ce qui avait déjà été dit dans la RFC 2818. Le forum du navigateur de l'autorité de certification est également présent, ce qui, combiné à la RFC 6125, signifie essentiellement que cn ne sera jamais vérifié pour le nom de domaine DNS.

0
jwilleke