Bozuk sertifika ile https talebi nasıl yapılır?


128

https://golang.orgProgramatik olarak almak istediğimi söyle . Şu anda golang.org (ssl) 'nin kötü bir sertifikası var ve *.appspot.combunu çalıştırdığımda So:

package main

import (
    "log"
    "net/http"
)

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

Anladım (beklediğim gibi)

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

Şimdi, bu sertifikaya kendim güvenmek istiyorum (parmak izini doğrulayabileceğim, kendi kendine verilen bir sertifika düşünün): nasıl bir istekte bulunabilir ve sertifikayı doğrulayabilir / güvenebilirim?

Sertifikayı indirmek, dosyama yüklemek ve tls.Configstruct'u doldurmak için muhtemelen openssl kullanmam gerekiyor!?


5
bu "kötü sertifika" değil, farklı bir CN'ye sahip bir sertifika. InsecureSkipVerify burada yasal bir kullanım değildir. Tls.Config'de ServerName'i bağlanmaya çalıştığınız şeyle eşleşecek şekilde ayarlamanız gerekir. Bu StackOverflow gönderisi, Go kodundaki bu büyük güvenlik açığının her yere yayılmasına neden oluyor. InsecureSkipVerify, HER ŞEYDE sertifikayı kontrol etmez. İstediğiniz şey, CN ana bilgisayar adıyla eşleşmese bile sertifikanın güvenilir bir varlık tarafından yasal olarak imzalandığını doğrulamaktır. Tüneller ve NATS yasal olarak bunun uyumsuzluğuna neden olabilir.
Rob

Yanıtlar:


284

Güvenlik notu: Güvenlik kontrollerini devre dışı bırakmak tehlikelidir ve bundan kaçınılmalıdır

Varsayılan istemcinin tüm istekleri için genel olarak güvenlik kontrollerini devre dışı bırakabilirsiniz:

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

Bir istemci için güvenlik kontrolünü devre dışı bırakabilirsiniz:

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

17
Bağlantının onsuz kullanılabilmesi için güvenilir bir sertifikayı nereye koyacağımı merak ediyorum InsecureSkipVerify: true. Mümkün mü?
2012'de

7
NameToCertificateyardımcı olabilir, tls.Configbelgelere bakın : golang.org/pkg/crypto/tls/#Config
cyberdelia

1
İşte özel CA sertifika havuzları eklemek için bir örnek: golang.org/pkg/crypto/tls/#example_Dial Bunu bir HTTP istemcisinde de kullanabilirsiniz.
Bitbored

7
Pek çok insan burada ana bilgisayar adı kontrollerini devre dışı bırakmaya çalışıyor (sertifika kontrollerini tamamen devre dışı bırakmıyor). Bu yanlış cevap. Go, bağlandığınız dns adı değilse, bağlanmakta olduğunuz ana bilgisayarın CN'si ile eşleşecek şekilde tls yapılandırmasında SunucuAdı'nı ayarlamanızı gerektirir. InsecureSkipVerify, bağlantı noktasına düz eski telnetten daha güvenli değildir. Bu ayarda HİÇBİR doğrulama yoktur. Bunun yerine Kullanıcı SunucuAdı!
Rob

8
Dikkat: Bu şekilde oluşturulan bir taşıma, alanlarının çoğu için sıfır değerleri kullanır ve bu nedenle tüm varsayılanları kaybeder . Gibi cevap aşağıda anlaşılacağı, onları buraya kopyalamak isteyebilirsiniz. Dosya tanımlayıcılarımızın neden tükendiğini anlamakta epey eğlendik çünkü Dialer.Timeout.
mknecht

26

İşte varsayılan ayarlarını kaybetmeden ve DefaultTransportkullanıcı yorumuna göre sahte isteğe ihtiyaç duymadan bunu yapmanın bir yolu .

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

// Create new Transport that ignores self-signed SSL
customTransport := &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},
}

GÜNCELLEME

Daha kısa yol:

customTransport := &(*http.DefaultTransport.(*http.Transport)) // make shallow copy
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

Doğru yol (Go 1.13 itibariyle) ( aşağıdaki yanıtla sağlanmıştır ):

customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

Uyarı : Yalnızca test / geliştirme amaçlıdır. Başka herhangi bir şey, kendi sorumluluğunuzdadır !!!


Varsayılan aktarım ayarlarını kullanarak mytransportsettings := &(*http.DefaultTransport.(*http.Transport))ve ardından TLS istemci yapılandırmasını değiştirerek basitçe kopyalamak daha kolay olmaz mıydı mytransportsettings.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}?
TheDiveO

Denemeye değer, sanırım gerçek DefaultTransport'u değiştirmediğimden emin olmaya çalışıyordum
Jonathan Lin

1
bu , sizin yaptığınız gibi sığ bir kopya oluşturmanızı sağlar ve bu, tartışılan kullanım durumu için yeterlidir. Aslında bunu çalışma kodunda kullanıyorum.
TheDiveO

19

Bütün bu cevaplar yanlış! Ana InsecureSkipVerifybilgisayar adıyla eşleşmeyen bir CN ile uğraşmak için kullanmayın . Go geliştiricileri akıllıca bir şekilde ana bilgisayar adı kontrollerini (meşru kullanımları olan tüneller, nats, paylaşılan küme sertifikaları vb.) Devre dışı bırakmama konusunda kararlıydılar ve aynı zamanda benzer görünen ancak aslında sertifika kontrolünü tamamen yok sayan bir şeye sahiplerdi . Sertifikanın geçerli olduğunu ve güvendiğiniz bir sertifika tarafından imzalandığını bilmeniz gerekir. Ancak yaygın senaryolarda, CN'nin bağlandığınız ana bilgisayar adıyla eşleşmeyeceğini bilirsiniz. Olanlar için, set ServerNameüzerinde tls.Config. Eğer tls.Config.ServerName== remoteServerCN ardından sertifika onay başarılı olacaktır. Senin istediğin bu. InsecureSkipVerifyHİÇBİR kimlik doğrulama olmadığı anlamına gelir; ve Ortadaki Adam için olgunlaşmış; TLS kullanma amacını ortadan kaldırmak.

Şunun meşru bir kullanımı vardır InsecureSkipVerify: bunu bir ana bilgisayara bağlanmak ve sertifikasını almak için kullanın, ardından hemen bağlantıyı kesin. Kodunuzu kullanmak için kurarsanız InsecureSkipVerify, bunun nedeni genellikle ServerNamedoğru şekilde ayarlamamış olmanızdır (bunun bir env var veya başka bir şeyden gelmesi gerekir - bu gereksinim konusunda karın ağrınız yok ... doğru yapın).

Özellikle, istemci sertifikalarını kullanır ve kimlik doğrulama için bunlara güvenirseniz, aslında artık oturum açmayan sahte bir girişiniz olur. İşe yarayan kodu reddedin yoksa InsecureSkipVerifyneyin yanlış olduğunu zor yoldan öğreneceksiniz!


1
Bunu test edebileceğim bir site biliyor musunuz? golang org artık bir hata atmıyor.
2017'yi 07

3
Bu cevap son derece yanıltıcıdır. Ana bilgisayar adı ne olursa olsun, geçerli olarak imzalanmış herhangi bir sertifikayı kabul ederseniz, yine de gerçek bir güvenlik elde edemezsiniz. Kontrol ettiğim tüm alanlar için geçerli bir sertifika kolayca edinebilirim; TLS kontrolü için sadece ana bilgisayar adımı belirtecekseniz, gerçekten söylediğim kişi olduğuma dair doğrulamayı kaybedersiniz. Bu noktada, sertifikanın "yasal" olması önemli değil; öyle hala yanlış ve sen hala ortada adama karşı savunmasız.
Daniel Farrell

5
Ticari CA'lardan hiçbirine gerçekten güvenmediğiniz (örneğin ABD dışındaysa) ve Teşebbüsünüz için bir CA ile değiştirdiğiniz bir Kuruluşta, bunun sertifikalarınızdan biri olduğunu doğrulamanız yeterlidir. Ana bilgisayar adı kontrolü, kullanıcıların ana bilgisayar adının eşleşmesini bekledikleri, ancak DNS'nin güvenli olmadığı durumlar içindir. Kuruluşta, genellikle ana bilgisayar adının / IP'nin eşleşmesinin mümkün olmadığı bir makine kümesine bağlanırsınız , çünkü bu, yeni IP'ler altında oluşturulan bir makinenin tam klonlarıdır. Dns adı sertifikayı bulur ve cert dns adı değil id'dir.
Rob

3
fikir, istemci kodunun yalnızca kurumsal CA'ya güvenmesidir. aslında şu anda kullanımda olan CA sisteminden çok daha güvenlidir. Bu durumda hiçbir şeye (Thawte, Versign, vb.) ... güvenilmez. Sadece çalıştırdığımız CA. Web tarayıcılarının çok büyük güven listeleri vardır. Birbirleriyle konuşan hizmetlerin güven dosyasında yalnızca bir CA bulunur.
Rob

1
teşekkür ederim @Rob Hizmetlerimizin yalnızca aynı, tek CA'ya güvendiği ve başka hiçbir şeye güvendiği aynı olmayan bir kurulumum var. Bu hayati bilgiler ve çok yardım.
user99999991

8

Varsayılan aktarım ayarlarını korumak istiyorsanız, bunu yapmanın doğru yolu şimdi (Go 1.13'ten itibaren):

customTransport := http.DefaultTransport.(*http.Transport).Clone()
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
client = &http.Client{Transport: customTransport}

Transport.Clone , taşımanın derin bir kopyasını çıkarır. Bu şekilde Transport, zamanla yapıya eklenen yeni alanları kaçırma konusunda endişelenmenize gerek kalmaz .


7

Yeni bir Taşıma ve İstemci nesnesi oluşturmanıza gerek kalmaması için http paketinden varsayılan ayarları kullanmak istiyorsanız, sertifika doğrulamasını şu şekilde göz ardı edecek şekilde değiştirebilirsiniz:

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

7
Bu neden olacaktır Doingpanic: runtime error: invalid memory address or nil pointer dereference
OscarRyz

6
Bundan önce varsayılan http istemcisini kullanmazsanız, varsayılan aktarımın başlatılması için sahte bir isteği zorlamalısınız
Cornel Damian

1
bu, ana bilgisayar adı kontrollerini devre dışı bırakmaz. tüm sertifika kontrollerini devre dışı bırakır. Go, sizi bağlandığınız şeyin sertifikasında SunucuAdı'nı CN'ye eşit ayarlamaya zorlar. InsecureSkipVerify, gerçek hizmetlere yönlendirme yapıyormuş gibi görünen hileli bir MITM sunucusuna bağlanacaktır. Bir InsecureSkipVerify için YALNIZCA meşru kullanım, uzak ucun sertifikasını almak ve bağlantıyı hemen kesmektir.
Rob

Bu yalnızca ayrıca bir VerifyPeerCertificate belirtmeniz durumunda uygundur. InsecureSkipVerify'ı yeni ayarlarsanız, hiç kontrol edilmez. Ancak, ihtiyacınız olan şeyi yapmak için çeki yeniden yazabilmeniz için bir VerifyPeerCertificate eklendi. Ana bilgisayar adını veya muhtemelen son kullanma tarihini göz ardı etmek isteyebilirsiniz. Google, bunu yapan çeşitli VerifyPeerCertificate uygulamaları için.
Rob

0

Genel olarak, URL’nin DNS Etki Alanı, sertifikanın Sertifika Konusuyla eşleşmelidir ZORUNLU.

Eskiden bu, alanı sertifikanın cn'si olarak ayarlayarak veya alan adını Konu Alternatif Adı olarak ayarlayarak olabilirdi.

Cn desteği uzun bir süredir kullanımdan kaldırıldı ( RFC 2818'de 2000'den beri ) ve Chrome tarayıcısı artık cn'ye bile bakmayacak, bu nedenle bugün URL'nin DNS Etki Alanını Konu Alternatif Adı olarak almanız gerekiyor .

RFC 6125 , DNS Etki Alanı için SAN varsa cn denetimini yasaklar, ancak IP Adresi için SAN varsa bunu yapmaz. RFC 6125 ayrıca, RFC 2818'de zaten söylendiği gibi cn'nin kullanımdan kaldırıldığını tekrarlar. Ve RFC 6125 ile birlikte esasen cn'nin DNS Etki Alanı adı için hiçbir zaman kontrol edilmeyeceği anlamına gelen Sertifika Yetkilisi Tarayıcı Forumu da mevcut olacaktır.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.