在 14.04 上執行 apt-get dist-upgrade Perl 腳本將不再忽略無效的 SSL 憑證

在 14.04 上執行 apt-get dist-upgrade Perl 腳本將不再忽略無效的 SSL 憑證

大家早安,

上週,我決定在 14.04 伺服器上執行命令來升級軟體包,以確保我已針對最近發現的 Bash 漏洞進行了修補。根據這裡的資訊(http://www.ubuntu.com/usn/usn-2362-1/)我運行了 apt-get dist-upgrade。作為參考,我運行了 apt-get update、apt-get dist-upgrade,然後運行了 apt-get Upgrade 來嘗試並確保我擁有最新版本的所有內容(不過,我通常運行 apt-get Upgrade)。

成功完成此操作後,我發現我的許多 Perl 腳本不再起作用。作為參考,我使用 Nagios 的此伺服器來監視所有其他伺服器。現在失敗的相關腳本都透過 https 連接到系統,登入主機並查詢各種資訊。

在升級之前,我可以為每個 Perl 腳本添加一行以使其忽略 SSL:

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0 } 

但是,升級後,這似乎沒有任何影響,而且腳本全部失敗,因為它們無法驗證 SSL 憑證(全部自簽署)。

以下是我所看到的一些片段:

腳本執行:

    nagios@nagios:/usr/local/nagios/libexec$ ./check_esx.pl -H 192.168.22.18 -u root -p password -l cpu
CHECK_ESX.PL CRITICAL - Can't connect to 192.168.22.18:443 (certificate verify failed)

LWP::Protocol::https::Socket: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/share/perl5/LWP/Protocol/http.pm line 41.

這個特定的 Perl 腳本利用「VMware Infrastructure (VI) Perl Toolkit」來運作。我正在呼叫的腳本 check_esx.pl 可用這裡

這是上述錯誤中引用的行周圍的文件 http.pm 的片段;第 41 行是「die」行。

sub _new_socket
{
    my($self, $host, $port, $timeout) = @_;

    local($^W) = 0;  # IO::Socket::INET can be noisy
    my $sock = $self->socket_class->new(PeerAddr => $host,
                                        PeerPort => $port,
                                        LocalAddr => $self->{ua}{local_address},
                                        Proto    => 'tcp',
                                        Timeout  => $timeout,
                                        KeepAlive => !!$self->{ua}{conn_cache},
                                        SendTE    => 1,
                                        $self->_extra_sock_opts($host, $port),
                                       );

    unless ($sock) {
        # IO::Socket::INET leaves additional error messages in $@
        my $status = "Can't connect to $host:$port";
        if ($@ =~ /\bconnect: (.*)/ ||
            $@ =~ /\b(Bad hostname)\b/ ||
            $@ =~ /\b(certificate verify failed)\b/ ||
            $@ =~ /\b(Crypt-SSLeay can't verify hostnames)\b/
        ) {
            $status .= " ($1)";
        }
        die "$status\n\n$@";
    }

    # perl 5.005's IO::Socket does not have the blocking method.
    eval { $sock->blocking(0); };

    $sock;
}

所以我想我在這裡尋找的是兩件事之一

要嘛: (A) 有沒有新的/更好的/更正確的方法讓 Perl 忽略 SSL 憑證?或 (B) 有沒有辦法將自簽名 SSL 憑證從另一台主機匯入 Ubuntu,以便 Perl 腳本能夠識別並信任它?或者:(B-2) 有沒有辦法讓 Ubuntu 識別我的 Windows 活動目錄證書頒發機構,以便我可以從我的 CA 向相關係統頒發 SSL 證書,並讓 Perl 腳本識別它?

預先感謝大家!

答案1

$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0

這是 LWP (CVE-2014-3230) 中的一個錯誤,已在較新版本中修復。 PERL_LWP_SSL_VERIFY_HOSTNAME 僅用於省略驗證憑證中的主機名,而不是憑證鏈。但是,由於您使用的是自簽名憑證鏈,驗證將會失敗。

僅在從舊的 Crypt::SSLeay 後端遷移到新的 IO::Socket::SSL 後端時引入此選項。 Crypt::SSLeay 不支援主機名稱驗證(因此容易受到中間人攻擊),而 IO::Socket::SSL 則支援。對於 LWP 版本 6,預設後端是 IO::Socket::SSL。

若要完全停用 LWP 的 ssl_opts 中的憑證集驗證SSL_verify_mode => SSL_VERIFY_NONE(您需要use IO::Socket::SSL有權存取 SSL_VERIFY_NONE 常數,或僅使用 0)。沒有環境變數可以執行此操作。

例子:

use LWP::UserAgent;
use IO::Socket::SSL;
my $ua = LWP::UserAgent->new(..., ssl_opts => { SSL_verify_mode => SSL_VERIFY_NONE });
$ua->get(...); # or $ua->post(...) or $ua->request(...)

不幸的是,我在您引用的腳本中看不到 LWP 的任何使用,因此我不知道在哪裡修復它。

至於你的選擇B:

(B) 有沒有辦法將自簽名 SSL 憑證從另一台主機匯入 Ubuntu,以便 Perl 腳本識別並信任它?或者:(B-2) 有沒有辦法讓 Ubuntu 識別我的 Windows 活動目錄證書頒發機構,以便我可以從我的 CA 向相關係統頒發 SSL 證書,並讓 Perl 腳本識別它?

您應該能夠使用環境變數 PERL_LWP_SSL_CA_FILE 來指定您接受哪些 CA 或自簽章憑證為可信任的檔案。

答案2

我認為這是一個 perl 版本問題,請檢查您之前使用什麼 perl 版本來運行該腳本。

我確信 Ubuntu 會安裝每個軟體的最新穩定版本。舉個例子,如果你有一個在 ubuntu 12.04 上運行的 python3 腳本,它可能無法在 ubuntu 14.04 上運行,原因是前者有 python 3.2,而後者有 python 3.4 版本。

我假設同樣的情況也發生在你的 perl 腳本上,檢查 perl 版本和新版本的發行說明。

相關內容