it-swarm-ko.tech

LWP가 SSL 서버 인증서의 유효성을 검사하도록하려면 어떻게해야합니까?

LWP 을 사용하여 연결중인 서버의 인증서가 신뢰할 수있는 기관에 의해 서명되고 올바른 호스트에 발급되었는지 확인할 수 있습니까? 내가 알 수있는 한, 인증서가 내가 연결하고있는 호스트 이름임을 주장하지는 않습니다. 이는 주요 보안 허점 인 것 같습니다 (특히 최근 DNS 취약점의 경우).

Update : 내가 정말로 원하는 것은 HTTPS_CA_DIR, ca-bundle.crt가 없기 때문에. 하지만 HTTPS_CA_DIR=/usr/share/ca-certificates/ 트릭을 수행했습니다. 어쨌든 대답이 충분히 가깝기 때문에 대답을 수락 된 것으로 표시하고 있습니다.

업데이트 2 : HTTPS_CA_DIRHTTPS_CA_FILE는 Net :: SSL을 기본 SSL 라이브러리로 사용하는 경우에만 적용됩니다. 그러나 LWP는 IO :: Socket :: SSL 과도 작동합니다.이 인증서는 해당 환경 변수를 무시하고 인증서가 무엇이든 관계없이 모든 서버와 즐겁게 대화합니다. 더 일반적인 해결책이 있습니까?

업데이트 3 : 불행히도, 해결책은 아직 완성되지 않았습니다. Net :: SSL 및 IO :: Socket :: SSL이 인증서와 비교하여 호스트 이름을 확인하지 않습니다. 즉, 누군가는 일부 도메인에 대한 합법적 인 인증서를 얻은 다음 LWP 불평없이 다른 도메인을 가장 할 수 있습니다.

업데이트 4 : LWP 6. 마침내 문제를 해결합니다. 자세한 내용은 my answer 를 참조하십시오.

44
cjm

이 오랜 보안 허점은 마침내 libwww-Perl 버전 6.00에서 수정되었습니다. 해당 버전부터 기본적으로 LWP :: UserAgent HTTPS 서버가 예상되는 호스트 이름과 일치하는 유효한 인증서를 제공하는지 확인합니다 ($ENV{Perl_LWP_SSL_VERIFY_HOSTNAME}이 (가) false 값으로 설정되었거나 해당 변수가 전혀 설정되지 않은 경우 이전 버전과의 호환성을 위해 $ENV{HTTPS_CA_FILE} 또는 $ENV{HTTPS_CA_DIR}이 설정되었습니다.

이것은 LWP :: UserAgent의 새로운 ssl_opts 옵션으로 제어 할 수 있습니다. 인증 기관 인증서의 위치에 대한 자세한 내용은 해당 링크를 참조하십시오. 그러나 주의해야합니다 . LWP :: UserAgent가 ssl_opts 생성자에 해시 한 다음 verify_hostname의 기본값은 1 대신 0 입니다. ( 이 버그 는 LWP 6.03에서 수정되었습니다.) 안전을 위해 항상 verify_hostname => 1에서 ssl_opts.

그래서 use LWP::UserAgent 6;은 서버 인증서의 유효성을 검사하기에 충분해야합니다.

37
cjm

설치 한 SSL 모듈에 따라 두 가지 방법이 있습니다. LWP 문서는 Crypt :: SSLeay 설치를 권장합니다. 이것이 당신이 한 일이라면, HTTPS_CA_FILE 환경 변수가 ca-bundle.crt를 가리 키도록 설정하는 것이 트릭입니다. ( Crypt :: SSLeay docs 는 언급하지만 자세한 내용은 약간 밝습니다). 또한 설정에 따라 HTTPS_CA_DIR 환경 변수를 대신 설정해야 할 수도 있습니다.

Crypt :: SSLeay의 예 :


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

Get은 die는 아니지만 undef을 반환합니다.

또는 IO::Socket::SSL 모듈 (CPAN에서도 사용 가능)을 사용할 수 있습니다. 서버 인증서를 확인하려면 SSL 컨텍스트 기본값을 수정해야합니다.


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");

이 버전은 또한 get()이 undef를 반환하지만 실행할 때 경고를 STDERR에 인쇄합니다 (IO :: Socket에서 debug * 기호를 가져 오는 경우 여러 디버깅뿐만 아니라). : SSL) :


% 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 검증을 우회하는 방법을 찾기 위해이 페이지를 방문했지만 모든 답변이 여전히 도움이되었습니다. 여기 내 결과가 있습니다. SSL 유효성 검사를 우회하려는 사람들 (권장하지 않지만 반드시해야 할 경우가있을 수 있음)의 경우 lwp 6.05에 있으며 이것은 나를 위해 일했습니다.

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 인 페이지에서 테스트했으며 작동했습니다. 키는 verify_hostname = 0과 함께 Net :: SSL을 사용하는 것입니다.

6
bshok

여기에 제시된 모든 솔루션에는 인증서의 트러스트 체인의 유효성 만 확인하지만 인증서의 공통 이름을 연결중인 호스트 이름과 비교하지 않는다는 점에서 주요 보안 결함이 있습니다. 따라서 중간에있는 사람이 귀하에게 임의의 인증서를 제시 할 수 있으며 LWP는 귀하가 신뢰하는 CA가 서명 한 한이를 행복하게 수락합니다. 가짜 인증서의 일반 이름은 LWP에 의해 확인되지 않으므로 관련이 없습니다.

IO::Socket::SSL를 LWP의 백엔드로 verifycn_scheme 다음과 같은 매개 변수 :

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

LWP :: UserAgent를 사용하지 않고 LWP :: UserAgent를 직접 사용하는 경우 "If-SSL-Cert-Subject"헤더를 HTTP :: Request 객체에 추가하여 인증서의 호스트 이름을 확인할 수 있습니다. 헤더의 값은 인증서 주체에 적용 할 정규식으로 취급되며, 일치하지 않으면 요청이 실패합니다. 예를 들면 다음과 같습니다.

#!/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"

인쇄합니다

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

당신은 이것에 대해 걱정할 권리가 있습니다. 불행히도, 내가 Perl을 찾은 저수준 SSL/TLS 바인딩에서 100 % 안전하게 수행하는 것이 불가능하다고 생각합니다.

기본적으로 핸드 셰이 킹을 시작하기 전에 SSL 라이브러리에 연결하려는 서버의 호스트 이름을 전달해야합니다. 또는 적절한 순간에 콜백이 발생하도록 준비하고 콜백이 체크 아웃되지 않으면 콜백 내부에서 핸드 셰이크를 중단 할 수 있습니다. OpenSSL에 Perl 바인딩을 작성하는 사람들은 콜백 인터페이스를 일관되게 만드는 데 문제가있는 것 같습니다.

서버의 인증서와 비교하여 호스트 이름을 확인하는 방법도 프로토콜에 따라 다릅니다. 따라서 그것은 완벽한 기능을위한 매개 변수가되어야합니다.

Netscape/Mozilla NSS 라이브러리에 대한 바인딩이 있는지 확인할 수 있습니다. 내가 볼 때이 작업을 수행하는 것이 꽤 좋아 보였습니다.

1
Marsh Ray

Net :: SSLGlue ( http://search.cpan.org/dist/Net-SSLGlue/lib/Net/SSLGlue.pm )를 고려할 수도 있지만 최근 IO에 의존합니다. :: 소켓 :: SSL 및 Net :: SSLeay 버전.

1
goneri

터미널에서 다음 명령을 실행하십시오. Sudo cpan install Mozilla :: CA

해결해야합니다.

0
Bojoer