utilizar servidor puede precio para instalar definicion como certificado perl ssl https lwp

perl - precio - el certificado no se puede utilizar como certificado de servidor ssl



¿Cómo puedo obtener LWP para validar certificados de servidor SSL? (8)

Aterricé en esta página buscando una forma de eludir la validación SSL, pero todas las respuestas fueron muy útiles. Aquí están mis hallazgos. Para aquellos que buscan eludir la validación de SSL (no se recomienda pero puede haber casos en los que sea absolutamente necesario), estoy en lwp 6.05 y esto funcionó para mí:

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

También probé en una página con POST y también funcionó. La clave es usar Net :: SSL junto con verify_hostname = 0.

¿Cómo puedo obtener LWP para verificar que el certificado del servidor al que me estoy conectando esté firmado por una autoridad de confianza y enviado al host correcto? Por lo que puedo decir, ni siquiera comprueba que el certificado dice ser el nombre de host al que me estoy conectando. Parece un gran agujero de seguridad (especialmente con las vulnerabilidades recientes del DNS).

Actualización: Resultó que lo que realmente quería era HTTPS_CA_DIR , porque no tengo un ca-bundle.crt. Pero HTTPS_CA_DIR=/usr/share/ca-certificates/ hizo el truco. Estoy marcando la respuesta como aceptada de todos modos, porque estaba lo suficientemente cerca.

Actualización 2: Resulta que HTTPS_CA_DIR y HTTPS_CA_FILE solo se aplican si está utilizando Net :: SSL como la biblioteca SSL subyacente. Pero LWP también trabaja con IO :: Socket :: SSL, que ignorará esas variables de entorno y se comunicará alegremente con cualquier servidor, independientemente del certificado que presente. ¿Hay una solución más general?

Actualización 3: Desafortunadamente, la solución aún no está completa. Ni Net :: SSL ni IO :: Socket :: SSL están verificando el nombre de host con el certificado. Esto significa que alguien puede obtener un certificado legítimo para algún dominio, y luego suplantar cualquier otro dominio sin quejarse LWP.

Actualización 4: LWP 6.00 finalmente resuelve el problema. Ver mi respuesta para más detalles.


Este agujero de seguridad de larga data finalmente se ha corregido en la versión 6.00 de libwww-perl . Comenzando con esa versión, LWP::UserAgent verifica de manera LWP::UserAgent que los servidores HTTPS presenten un certificado válido que coincida con el nombre de host esperado (a menos que $ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} tenga un valor falso o, para compatibilidad con versiones anteriores, si esa variable no está establecida, se ha $ENV{HTTPS_CA_FILE} o $ENV{HTTPS_CA_DIR} .

Esto se puede controlar con la nueva opción ssl_opts de LWP :: UserAgent. Consulte ese enlace para obtener detalles sobre cómo se encuentran los certificados de la Autoridad de certificación. Pero tenga cuidado , la forma en que LWP :: UserAgent solía funcionar, si proporciona un hash ssl_opts al constructor, luego verify_hostname predeterminado a 0 en lugar de 1. ( Este error se corrigió en LWP 6.03). Para estar seguro, siempre especifique verify_hostname => 1 en tu ssl_opts .

Entonces use LWP::UserAgent 6; debería ser suficiente para validar los certificados del servidor.


Hay dos maneras de hacerlo dependiendo del módulo SSL que haya instalado. Los documentos de LWP recomiendan instalar Crypt :: SSLeay . Si eso es lo que has hecho, establecer la variable de entorno HTTPS_CA_FILE para que apunte a tu ca-bundle.crt debería ser el truco. ( Crypt :: SSLeay docs menciona esto pero es un poco ligero en los detalles). Además, dependiendo de su configuración, puede que necesite establecer la variable de entorno HTTPS_CA_DIR lugar.

Ejemplo para 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

Tenga en cuenta que get no die , pero devuelve undef .

Alternativamente, puede usar el IO::Socket::SSL (también disponible desde el CPAN). Para que esto verifique el certificado del servidor, debe modificar los valores predeterminados del contexto 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");

Esta versión también hace que get() devuelva undef, pero imprime una advertencia a STDERR cuando lo ejecuta (así como un montón de depuración si importa los símbolos de depuración * de IO :: Socket :: 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)


Si usa LWP :: UserAgent directamente (no a través de LWP :: Simple) puede validar el nombre de host en el certificado agregando el encabezado "If-SSL-Cert-Subject" a su objeto HTTP :: Request. El valor del encabezado se trata como una expresión regular que se aplicará al sujeto del certificado, y si no coincide, la solicitud falla. Por ejemplo:

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

imprimirá

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


Simplemente ejecute el siguiente comando en Terminal: sudo cpan install Mozilla :: CA

Debería resolverlo.



Tiene razón en estar preocupado por esto. Desafortunadamente, no creo que sea posible hacerlo de forma 100% segura bajo ninguno de los enlaces SSL / TLS de bajo nivel que busqué para Perl.

Esencialmente, debe pasar el nombre de host del servidor que desea conectar a la biblioteca SSL antes de que comience el intercambio de información. Alternativamente, puede organizar que se realice una devolución de llamada en el momento correcto y cancelar el saludo desde adentro de la devolución de llamada si no se realiza. Las personas que escriben enlaces Perl a OpenSSL parecían tener problemas para hacer que la interfaz de devolución de llamada sea consistente.

El método para verificar el nombre de host contra el certificado del servidor también depende del protocolo. Entonces eso tendría que ser un parámetro para cualquier función perfecta.

Es posible que desee ver si hay enlaces a la biblioteca de Netscape / Mozilla NSS. Me pareció bastante bueno hacer esto cuando lo miré.


Todas las soluciones presentadas aquí contienen una gran falla de seguridad ya que solo verifican la validez de la cadena de confianza del certificado, pero no comparan el Nombre común del certificado con el nombre de host al que se está conectando. Por lo tanto, un hombre en el medio puede presentarle un certificado arbitrario y LWP lo aceptará con gusto siempre que lo firme un CA en quien confíe. El nombre común del certificado falso es irrelevante porque nunca es verificado por LWP.

Si está utilizando IO::Socket::SSL como back-end de LWP, puede habilitar la verificación del Nombre común configurando el parámetro verifycn_scheme esta manera:

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