it-swarm-tr.com

LWP'nin SSL sunucu sertifikalarını doğrulamasını nasıl sağlayabilirim?

Bağlandığım sunucunun sertifikasının güvenilir bir otorite tarafından imzalandığını ve doğru ana bilgisayara verildiğini doğrulamak için nasıl LWP alabilirim? Söyleyebileceğim kadarıyla, bağlandığım ana bilgisayar adı için sertifikanın olduğunu iddia etmiyor bile. Bu büyük bir güvenlik boşluğu gibi görünüyor (özellikle son DNS açıkları ile).

Güncelleme: Gerçekten istediğim şey HTTPS_CA_DIR oldu, çünkü bir ca-bundle.crt 'a sahip değilim. Ama hileyi HTTPS_CA_DIR=/usr/share/ca-certificates/ yaptı. Cevabı yine de kabul edildi olarak işaretliyorum, çünkü yeterince yakındı.

Güncelleme 2:HTTPS_CA_DIR ve HTTPS_CA_FILE öğelerinin yalnızca, temel SSL kütüphanesi olarak Net :: SSL kullanıyorsanız geçerli olduğu ortaya çıktı. Ancak LWP, hangi çevre sertifikası olursa olsun, bu ortam değişkenlerini görmezden gelecek ve herhangi bir sunucuyla mutlu bir şekilde konuşacak olan IO :: Socket :: SSL ile de çalışır. Daha genel bir çözüm var mı?

Güncelleme 3: Maalesef, çözüm hala tamamlanmadı. Ne Net :: SSL ne de IO :: Socket :: SSL, Ana Bilgisayar adını sertifikaya karşı kontrol etmiyor. Bu, birinin bir alan adı için yasal bir sertifika alabileceği ve LWP şikayet etmeden başka bir alanı taklit edebileceği anlamına gelir.

Güncelleme 4:LWP 6.00 sonunda sorunu çözdü. Detaylar için cevabım .

44
cjm

Bu uzun süredir devam eden bu güvenlik deliği nihayet 6.00 - Perl 6. Bu sürümden başlayarak, varsayılan olarak LWP :: UserAgent , HTTPS sunucularının beklenen ana bilgisayar adıyla eşleşen geçerli bir sertifika sunduğunu doğrular ($ENV{Perl_LWP_SSL_VERIFY_HOSTNAME}, sahte bir değere ayarlanmadığı sürece veya değişken hiçbir şekilde ayarlanmadı, $ENV{HTTPS_CA_FILE} veya $ENV{HTTPS_CA_DIR} ayarlandı).

Bu, LWP :: UserAgent'ın yeni ssl_opts seçeneğiyle kontrol edilebilir. Sertifika Yetkilisi sertifikalarının nasıl bulunduğu ile ilgili ayrıntılar için bu bağlantıya bakın. Fakat , LWP :: UserAgent öğesinin çalışma biçiminde dikkatli olun , yapıcıya bir ssl_opts karma sağlarsanız, sonra verify_hostname, 1 yerine 0 olarak varsayılan olarak ayarlandı. ( Bu hata LWP 6.03'te düzeltildi.) Güvenli olmak için, her zaman verify_hostname => 1 in ssl_opts.

Bu nedenle use LWP::UserAgent 6; sunucu sertifikalarının doğrulanması için yeterli olmalıdır.

37
cjm

Taktığınız SSL modülüne bağlı olarak bunu yapmanın iki yolu vardır. LWP belgeleri Crypt :: SSLeay 'nin kurulmasını tavsiye eder. Yaptığınız şey buysa, HTTPS_CA_FILE ortam değişkenini ca-bundle.crt'inize işaret edecek şekilde ayarlamak, işe yarayacaktır. ( Crypt :: SSLeay docs bundan bahseder, ancak ayrıntılara biraz ışık tutar). Ayrıca, kurulumunuza bağlı olarak, bunun yerine HTTPS_CA_DIR ortam değişkenini ayarlamanız gerekebilir.

Crypt :: SSLeay için örnek:


use LWP::Simple qw(get);
$ENV{HTTPS_CA_FILE} = "/path/to/your/ca/file/ca-bundle";
$ENV{HTTPS_DEBUG} = 1;

print get("https://some-server-with-bad-certificate.com");

__END__
SSL_connect:before/connect initialization
SSL_connect:SSLv2/v3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:unknown CA
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv3 write client hello A
SSL_connect:SSLv3 read server hello A
SSL3 alert write:fatal:bad certificate
SSL_connect:error in SSLv3 read server certificate B
SSL_connect:before/connect initialization
SSL_connect:SSLv2 write client hello A
SSL_connect:error in SSLv2 read server hello B

Unutmayın ki get die değildir, ancak bir undef döndürür.

Alternatif olarak, IO::Socket::SSL modülünü kullanabilirsiniz (ayrıca CPAN'dan da alınabilir). Bunu sunucu sertifikasını doğrulamak için SSL bağlamı varsayılanlarını değiştirmeniz gerekir:


use IO::Socket::SSL qw(debug3);
use Net::SSLeay;
BEGIN {
    IO::Socket::SSL::set_ctx_defaults(
        verify_mode => Net::SSLeay->VERIFY_PEER(),
        ca_file => "/path/to/ca-bundle.crt",
      # ca_path => "/alternate/path/to/cert/authority/directory"
    );
}
use LWP::Simple qw(get);

warn get("https:://some-server-with-bad-certificate.com");

Bu sürüm ayrıca get() işlevinin undef döndürmesine neden olur, ancak çalıştırdığınızda STDERR için bir uyarı yazdırır (yanı sıra hata ayıklama * sembollerini IO :: Socket :: SSL'den içe aktarırsanız bir grup hata ayıklama):


% Perl ssl_test.pl
DEBUG: .../IO/Socket/SSL.pm:1387: new ctx 139403496
DEBUG: .../IO/Socket/SSL.pm:269: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:271: socket connected
DEBUG: .../IO/Socket/SSL.pm:284: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:327: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1135: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed

DEBUG: .../IO/Socket/SSL.pm:333: fatal SSL error: SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1422: free ctx 139403496 open=139403496
DEBUG: .../IO/Socket/SSL.pm:1425: OK free ctx 139403496
DEBUG: .../IO/Socket/SSL.pm:1135: IO::Socket::INET configuration failederror:00000000:lib(0):func(0):reason(0)
500 Can't connect to some-server-with-bad-certificate.com:443 (SSL connect attempt failed with unknown errorerror:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed) 
9
Brian Phillips

SSL doğrulamasını atlamanın bir yolunu aramak için bu sayfaya girdim, ancak tüm cevaplar hala çok yardımcı oldu. İşte benim bulgularım. SSL doğrulamasını atlamak isteyenler için (önerilmiyor ancak mutlaka yapmanız gerekecek durumlar olabilir), 6.06'dayım ve bu benim için çalıştı:

use strict;
use warnings;
use LWP::UserAgent;
use HTTP::Request::Common qw(GET);
use Net::SSL;

my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 0 }, );
my $req = GET 'https://github.com';
my $res = $ua->request($req);
if ($res->is_success) {
    print $res->content;
} else {
    print $res->status_line . "\n";
}

POST ile bir sayfada test ettim ve de çalıştı. Anahtar, Net :: SSL'yi verify_hostname = 0 ile birlikte kullanmaktır.

6
bshok

Burada sunulan tüm çözümler, yalnızca sertifikanın güven zincirinin geçerliliğini doğrulamaları, ancak sertifikanın Ortak Adını, bağlandığınız ana bilgisayar adı ile karşılaştırmamalarında büyük bir güvenlik açığı içerir. Bu nedenle, ortadaki bir adam size keyfi bir sertifika sunabilir ve LWP güvendiğiniz bir CA tarafından imzalandığı sürece mutlu bir şekilde kabul eder. Sahte sertifikanın Ortak Adı alakasızdır, çünkü hiçbir zaman LWP tarafından kontrol edilmez.

LWP'nin arka ucu olarak IO::Socket::SSL kullanıyorsanız, verifycn_scheme parametresini şöyle ayarlayarak Ortak Adın doğrulanmasını sağlayabilirsiniz:

use IO::Socket::SSL;
use Net::SSLeay;
BEGIN {
    IO::Socket::SSL::set_ctx_defaults(
        verify_mode => Net::SSLeay->VERIFY_PEER(),
        verifycn_scheme => 'http',
        ca_path => "/etc/ssl/certs"
    );
}
2
blumentopf

Doğrudan LWP :: UserAgent kullanıyorsanız (LWP :: Simple aracılığıyla değil), HTTP :: Request nesnesine "If-SSL-Cert-Subject" başlığını ekleyerek sertifikadaki ana bilgisayar adını doğrulayabilirsiniz. Başlığın değeri, sertifika konusuna uygulanacak düzenli ifade olarak kabul edilir ve eşleşmezse istek başarısız olur. Örneğin:

#!/usr/bin/Perl 
use LWP::UserAgent;
my $ua = LWP::UserAgent->new();
my $req = HTTP::Request->new(GET => 'https://yourdomain.tld/whatever');
$req->header('If-SSL-Cert-Subject' => '/CN=make-it-fail.tld');

my $res = $ua->request( $req );

print "Status: " . $res->status_line . "\n"

basacak

Status: 500 Bad SSL certificate subject: '/C=CA/ST=Ontario/L=Ottawa/O=Your Org/CN=yourdomain.tld' !~ //CN=make-it-fail.tld/
2
dave0

Bu konuda endişelenme hakkın var. Ne yazık ki, Perl için baktığım düşük seviyeli SSL/TLS bağlarından hiçbirinde% 100 güvenli bir şekilde yapmanın mümkün olduğunu sanmıyorum.

Temel olarak, tokalaşma gerçekleşmeden önce SSL kütüphanesine bağlanmak istediğiniz sunucunun ana bilgisayar adını girmeniz gerekir. Alternatif olarak, doğru zamanda bir geri arama yapılması için düzenleme yapabilir ve teslim almadığı takdirde el sıkışmasını geri arama içinden iptal edebilirsiniz. Perl'i OpenSSL'ye bağlayan insanlar geri arama arayüzünü tutarlı bir şekilde yapmakta zorlanıyorlardı.

Ana bilgisayar adını sunucunun sertifikalarına karşı denetleme yöntemi de protokole bağlıdır. Bu nedenle, herhangi mükemmel bir işlevin parametresi olmalı.

Netscape/Mozilla NSS kütüphanesinde herhangi bir cilt olup olmadığını görmek isteyebilirsiniz. Baktığımda bunu yapmak oldukça iyi görünüyordu.

1
Marsh Ray

Ayrıca Net :: SSLGlue ( http://search.cpan.org/dist/Net-SSLGlue/lib/Net/SSLGlue.pm ) 'yi de düşünebilirsiniz. :: SSL ve Net :: SSLeay sürümleri.

1
goneri

Terminal'de aşağıdaki komutu uygulamanız yeterlidir: Sudo cpan install Mozilla :: CA

Çözmeli.

0
Bojoer