Fix CVE-2026-8450: send_file() RCE via 2-arg open() shell-magic
Backport upstream fix (commit 945d351) for CVE-2026-8450 in
perl-HTTP-Daemon. The send_file() method used 2-arg open()
which allowed shell-magic interpretation of filenames (pipe
commands, redirections), enabling RCE and arbitrary file write
when filenames were derived from attacker-controlled input.
The fix switches to 3-arg open() with explicit '<' mode,
adds binmode error handling, and returns '0E0' for
empty-but-successful transfers.
CVE: CVE-2026-8450
Upstream patches:
- 945d35141d.patch
Resolves: RHEL-184821
This commit was backported by Ymir, a Red Hat Enterprise Linux software maintenance AI agent.
Assisted-by: Ymir
This commit is contained in:
parent
25c071a09c
commit
73c2c63253
108
perl-HTTP-Daemon-6.16-CVE-2026-8450.patch
Normal file
108
perl-HTTP-Daemon-6.16-CVE-2026-8450.patch
Normal file
@ -0,0 +1,108 @@
|
||||
From 04756e6d63242b15e26d8c2bb988668e810433e8 Mon Sep 17 00:00:00 2001
|
||||
From: Olaf Alders <olaf@wundersolutions.com>
|
||||
Date: Thu, 14 May 2026 00:09:58 +0000
|
||||
Subject: [PATCH] Fix CVE-2026-8450: send_file() honoured 2-arg open()
|
||||
shell-magic
|
||||
|
||||
HTTP::Daemon::ClientConn::send_file() used the 2-arg form
|
||||
open(FILE, $file), which interprets shell-magic prefixes in the
|
||||
path argument: '| cmd' (write pipe -- RCE), 'cmd |' (read pipe --
|
||||
RCE plus response-body exfiltration via the sysread / print loop
|
||||
below), '> path' (write-truncate -- arbitrary file write), and
|
||||
'>> path', '+< path', '<&fd', and leading-whitespace variants of
|
||||
the above.
|
||||
|
||||
Any HTTP::Daemon-based application that passed attacker-influenced
|
||||
bytes to send_file($string) -- for example, a download endpoint
|
||||
that derived the filename from a query parameter -- granted command
|
||||
execution and/or arbitrary file write at the daemon's UID.
|
||||
|
||||
Switch to 3-arg open(my $fh, '<', $file): the explicit '<' mode
|
||||
makes the path argument a literal filename, so every magic shape
|
||||
above is opened (and fails, returning undef) as an ordinary file by
|
||||
that exact name. The localized typeglob is no longer needed and is
|
||||
replaced with a lexical filehandle.
|
||||
|
||||
Two collateral hardening changes ride along:
|
||||
|
||||
- binmode() failure now closes the handle and returns undef,
|
||||
rather than streaming the file with a wrong PerlIO layer.
|
||||
|
||||
- send_file() returns '0E0' (true zero) on a successful zero-byte
|
||||
transfer so callers using "send_file or die" can distinguish
|
||||
open failure (undef) from an empty-but-successful copy.
|
||||
|
||||
The POD now documents the new return-value contract and spells
|
||||
out that the fix only neutralises 2-arg open() shell-magic;
|
||||
callers remain responsible for validating attacker-influenced
|
||||
paths against symlinks, character/block devices (e.g. /dev/zero),
|
||||
named pipes, and document-root escapes.
|
||||
|
||||
Reported and patched by Stig Palmquist (stigtsp).
|
||||
|
||||
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
||||
---
|
||||
lib/HTTP/Daemon.pm | 35 ++++++++++++++++++++++++++++++-----
|
||||
1 file changed, 30 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/lib/HTTP/Daemon.pm b/lib/HTTP/Daemon.pm
|
||||
index f9b3216..0707b9b 100644
|
||||
--- a/lib/HTTP/Daemon.pm
|
||||
+++ b/lib/HTTP/Daemon.pm
|
||||
@@ -592,11 +592,10 @@ sub send_dir {
|
||||
sub send_file {
|
||||
my ($self, $file) = @_;
|
||||
my $opened = 0;
|
||||
- local (*FILE);
|
||||
if (!ref($file)) {
|
||||
- open(FILE, $file) || return undef;
|
||||
- binmode(FILE);
|
||||
- $file = \*FILE;
|
||||
+ open(my $fh, '<', $file) || return undef;
|
||||
+ binmode($fh) || do { close($fh); return undef };
|
||||
+ $file = $fh;
|
||||
$opened++;
|
||||
}
|
||||
my $cnt = 0;
|
||||
@@ -608,7 +607,11 @@ sub send_file {
|
||||
print $self $buf;
|
||||
}
|
||||
close($file) if $opened;
|
||||
- $cnt;
|
||||
+
|
||||
+ # Return a "true zero" for empty-but-successful copies so callers
|
||||
+ # using `send_file or die` can distinguish open failure (undef)
|
||||
+ # from a successful zero-byte transfer.
|
||||
+ $cnt || '0E0';
|
||||
}
|
||||
|
||||
sub daemon {
|
||||
@@ -902,6 +905,28 @@ Copy the file to the client. The file can be a string (which
|
||||
will be interpreted as a filename) or a reference to an C<IO::Handle>
|
||||
or glob.
|
||||
|
||||
+Returns the number of bytes copied on success, or C<undef> if the
|
||||
+filename form failed to open. An empty file returns the string
|
||||
+C<'0E0'> (zero numerically, true in boolean context) so that callers
|
||||
+using C<< send_file or die >> can distinguish open failure from a
|
||||
+successful zero-byte transfer.
|
||||
+
|
||||
+The filename form uses Perl's 3-argument C<open> with an explicit C<<
|
||||
+< >> mode, so the path is no longer interpreted as a 2-argument
|
||||
+C<open> shell-magic shape such as C<< | cmd >>, C<< cmd | >>, or
|
||||
+C<< > path >>. See
|
||||
+L<CVE-2026-8450|https://www.cve.org/CVERecord?id=CVE-2026-8450> for
|
||||
+the prior 2-argument C<open> behaviour this replaces.
|
||||
+
|
||||
+Note that this fix only neutralises 2-argument C<open> shell-magic.
|
||||
+Callers remain responsible for validating attacker-influenced paths:
|
||||
+C<send_file> will still happily open symlinks, character/block devices
|
||||
+(e.g. C</dev/zero>, C</dev/stdin>), named pipes (which may block the
|
||||
+worker), and files outside an intended document root. If C<$filename>
|
||||
+can be derived from request input, validate it (canonicalise, reject
|
||||
+C<..> segments, require C<-f _> and a vetted prefix) before passing it
|
||||
+in.
|
||||
+
|
||||
=item $c->daemon
|
||||
|
||||
Return a reference to the corresponding C<HTTP::Daemon> object.
|
||||
@ -3,13 +3,16 @@
|
||||
|
||||
Name: perl-HTTP-Daemon
|
||||
Version: 6.16
|
||||
Release: 7%{?dist}
|
||||
Release: 8%{?dist}
|
||||
Summary: Simple HTTP server class
|
||||
License: GPL-1.0-or-later OR Artistic-1.0-Perl
|
||||
URL: https://metacpan.org/release/HTTP-Daemon
|
||||
Source0: https://cpan.metacpan.org/authors/id/O/OA/OALDERS/HTTP-Daemon-%{version}.tar.gz
|
||||
# Use Makefile.PL without unneeded dependencies
|
||||
Patch0: HTTP-Daemon-6.04-EU-MM-is-not-deprecated.patch
|
||||
# https://issues.redhat.com/browse/RHEL-184821
|
||||
# https://github.com/libwww-perl/HTTP-Daemon/commit/945d35141d94490f749640bd4390acd6a2193995
|
||||
Patch1: perl-HTTP-Daemon-6.16-CVE-2026-8450.patch
|
||||
BuildArch: noarch
|
||||
BuildRequires: coreutils
|
||||
BuildRequires: make
|
||||
@ -83,6 +86,7 @@ with "%{_libexecdir}/%{name}/test".
|
||||
%prep
|
||||
%setup -q -n HTTP-Daemon-%{version}
|
||||
%patch -P0 -p1
|
||||
%patch -P1 -p1
|
||||
# Help generators to recognize Perl scripts
|
||||
for F in $(find t/ -name '*.t'); do
|
||||
perl -i -MConfig -ple 'print $Config{startperl} if $. == 1 && !s{\A#!\s*perl}{$Config{startperl}}' "$F"
|
||||
@ -118,6 +122,10 @@ make test
|
||||
%{_libexecdir}/%{name}
|
||||
|
||||
%changelog
|
||||
* Wed Aug 05 2026 RHEL Packaging Agent <redhat-ymir-agent@redhat.com> - 6.16-8
|
||||
- Fix CVE-2026-8450: send_file() shell-magic via 2-arg open()
|
||||
Resolves: RHEL-184821
|
||||
|
||||
* Tue Oct 29 2024 Troy Dawson <tdawson@redhat.com> - 6.16-7
|
||||
- Bump release for October 2024 mass rebuild:
|
||||
Resolves: RHEL-64018
|
||||
|
||||
Loading…
Reference in New Issue
Block a user