From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 922876C573 for ; Fri, 6 Aug 2021 17:44:45 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 903BF102A8 for ; Fri, 6 Aug 2021 17:44:45 +0200 (CEST) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS id AB47A1028C for ; Fri, 6 Aug 2021 17:44:43 +0200 (CEST) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 8308E42F03 for ; Fri, 6 Aug 2021 17:44:43 +0200 (CEST) From: Stoiko Ivanov To: pve-devel@lists.proxmox.com Date: Fri, 6 Aug 2021 17:44:27 +0200 Message-Id: <20210806154429.1675997-2-s.ivanov@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20210806154429.1675997-1-s.ivanov@proxmox.com> References: <20210806154429.1675997-1-s.ivanov@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.425 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [acme.pm, neverssl.com] Subject: [pve-devel] [PATCH proxmox-acme 1/3] acme client: fix #3536 untaint data returned from acme server X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 06 Aug 2021 15:44:45 -0000 The data returned from the acme server (e.g. boulder) should be considered tainted. To see which places might need untainted I checked where $self->{ua} was used (in $self->do) and a quick scan identified __get_result as the consumer of the tainted data. In all but one uses the data is decoded from json (which would die if the result is not valid json). The remaining use-case yields a certificate in PEM format (and is handled at the caller of __get_result). The issue is currently only visible if a proxy is set, because AFAICT somewhere in SSLeay (or IO::Socket::SSL, which uses SSLeay) a taint flag is not set on the return value. A reproducer for the issue: ``` use strict; use warnings; use HTTP::Request; use LWP::UserAgent; $ENV{PATH} = "/usr/bin:/bin"; my $ua = LWP::UserAgent->new(env_proxy => 0); my $request = HTTP::Request->new('GET', 'https://google.com/'); my $resp = $ua->request($request); my $text = substr($resp->decoded_content, 0, 5);; system("echo \"$text\""); # does work $request = HTTP::Request->new('GET', 'http://neverssl.com/'); $resp = $ua->request($request); $text = substr($resp->decoded_content, 0, 5);; system("echo \"$text\""); # does not work ``` Signed-off-by: Stoiko Ivanov --- src/PVE/ACME.pm | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/PVE/ACME.pm b/src/PVE/ACME.pm index c5b8d66..265482d 100644 --- a/src/PVE/ACME.pm +++ b/src/PVE/ACME.pm @@ -69,7 +69,9 @@ sub tojs($;%) { # shortcut for to_json with utf8=>1 } sub fromjs($) { - return from_json($_[0]); + my ($data) = @_; + ($data) = ($data =~ /^(.*)$/s); # untaint from_json croaks on error anyways. + return from_json($data); } sub fatal($$;$$) { @@ -449,7 +451,13 @@ sub get_certificate { if !$order->{certificate}; my $r = $self->do(POST => $order->{certificate}, ''); - my $return = eval { __get_result($r, 200, 1); }; + my $return = eval { + my $res = __get_result($r, 200, 1); + if ($res =~ /^(-----BEGIN CERTIFICATE-----)(.+)(-----END CERTIFICATE-----)$/s) { # untaint + return $1 . $2 . $3; + } + die "Server reply does not look like a PEM encoded certificate\n"; + }; $self->fatal("POST of '$order->{certificate}' failed - $@", $r) if $@; return $return; } -- 2.30.2