Guide to API Privilege Escalation - Legacy Method

Introduction

Warning:

Poor implementations of this system may cause root-privilege vulnerabilities and compromised servers. Read the Security requirements section of this document before you use this system.

In cPanel & WHM version 11.36 and earlier, you must write the scripts to allow functions to run with elevated privileges. These scripts must directly manipulate the data that passes through the  setuid  wrapper.

  • Download an example .tar.gz file.

Notes:

  • Never use this any of these example files on a production system.
  • For information about privilege escalation in cPanel & WHM version 11.38 and later, read our API Privilege Escalationdocumentation.

Security requirements

 

      MultiExcerpt named '
securityrequirements
    ' was not found
The page: Guide to API Privilege Escalation was found, but the multiexcerpt named 'securityrequirements' was not found. Please check/update the page name used in the 'multiexcerpt-include macro.

 

Files

Privilege escalation systems in cPanel & WHM version 11.36 and earlier require the following key components: 

  • The Cpanel::AdminBin module
  • The admin script
  • A wrapper binary  

The admin binary and wrapper scripts follow a strict naming convention.

  • You must prefix the admin and wrap files with a unique identifier.
  • For example, if you create the admin binary and the example wrapper script, name the files exampleadmin and examplewrap, respectively.

The  Cpanel::AdminBin module

The Cpanel::AdminBin Perl module (/usr/local/cpanel/Cpanel/AdminBin.pm) passes information between the wrapper scripts and the system processes that run the code.

Notes:

  • This document's examples focus on two functions. The /usr/local/cpanel/Cpanel/AdminBin.pm file contains additional functions to use.
  • The example file for this method provides examples of how to use this code in the Test.pm file.

Click a tab to view information about a function:

Adminrun()

The adminrun() function returns strings from the admin binary.

To call this function, use the following format:

adminrun($name$cmd@args )

This example uses the following variables:

  • $name — The admin script's filename's identifier prefix.
  • $cmd — The command to pass to the wrapper.
  • $args — A list of command arguments.

For example, to create the file wrapper script and a READ function that accepts path arguments via the adminrun() function, create a function that is similar to the following code:

my $file_contents = Cpanel::AdminBin::adminrun('file''READ'$OPTS{'path'});
  • This function executes the /usr/local/cpanel/bin/filewrap binary as setuid root and writes READ $path to it through STDIN
  • The filewrap binary executes the /usr/local/cpanel/bin/fileadmin binary and writes $uid READ $path to STDIN.

The admin script

The admin script contains the code that runs as the root user. The script accepts data from STDIN and prints data to STDOUT, after which the wrapper binary executes the data.

  • You must store this script in the /usr/local/cpanel/bin/ directory with executable permissions.
  • You must prefix the admin script's filename with a unique identifier.

Note:

The example file for this method provides examples of how to use this code in the testadmin file.

When the script writes data to STDIN, use the following format:

$uid $cmd $args

This example uses the following variables:

  • $uid — The authenticated user's ID. The admin binary automatically prefixes this value.
  • $cmd — The command to execute.
  • $args — A list of command arguments.
adminfetchnocache()

The adminrun() function returns strings from the admin binary.

To call this function, use the following format:

adminrun($name$cmd@args )

This example uses the following variables:

  • $name — The admin script's filename's identifier prefix.
  • $cmd — The command to pass to the wrapper.
  • $args — A list of command arguments.

For example, to create the file wrapper script and a READ function that accepts path arguments via the adminrun() function, create a function that is similar to the following code:

my $file_contents = Cpanel::AdminBin::adminrun('file''READ'$OPTS{'path'});
  • This function executes the /usr/local/cpanel/bin/filewrap binary as setuid root and writes READ $path to it through STDIN
  • The filewrap binary executes the /usr/local/cpanel/bin/fileadmin binary and writes $uid READ $path to STDIN.

The admin script

The admin script contains the code that runs as the root user. The script accepts data from STDIN and prints data to STDOUT, after which the wrapper binary executes the data.

  • You must store this script in the /usr/local/cpanel/bin/ directory with executable permissions.
  • You must prefix the admin script's filename with a unique identifier.

Note:

The example file for this method provides examples of how to use this code in the testadmin file.

When the script writes data to STDIN, use the following format:

$uid $cmd $args

This example uses the following variables:

  • $uid — The authenticated user's ID. The admin binary automatically prefixes this value.
  • $cmd — The command to execute.
  • $args — A list of command arguments.

cPanel & WHM version 11.36 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
my %commands = (
    'LS' => sub {
        # pull in the values that were in @args         my ($dir) = @_;
        # Sanitize our input         if ( !defined $dir || $dir eq '' ) {
            print "Directory not defined\n";
            exit;
        }
 
        if ( !-d $dir ) {
            print "provided directory does not exist\n";
            exit;
        }
        my @files;
        # perform the action         opendir( my $dir_dh, $dir ) || die "Can't open directory: $dir";
        #build our data structure         foreach my $file ( readdir $dir_dh ) {
            push @files$file;
        }
        closedir($dir_dh) || die "Can't close directory: $dir";
        # print out in YAML format         print Cpanel::YAML::Dump(\@files);
    },
  • Line 19 prints the @files data structure to STDOUT in the YAML format. 
    • This passes a data structure back to the subroutine that initiated the call. 
    • Call this file via the adminfetch() or adminfetchnocache() functions.

cPanel & WHM version 11.34 and earlier

my %commands = (
    'LS' => sub {
        # pull in the values that were in @args         my ($dir) = @_;
        # Sanitize our input         if ( !defined $dir || $dir eq '' ) {
            print "Directory not defined\n";
            exit;
        }
 
        if ( !-d $dir ) {
            print "provided directory does not exist\n";
            exit;
        }
        my @files;
        # perform the action         opendir( my $dir_dh, $dir ) || die "Can't open directory: $dir";
        #build our data structure         foreach my $file ( readdir $dir_dh ) {
            push @files$file;
        }
        closedir($dir_dh) || die "Can't close directory: $dir";
        # print out in Storable format         Storable::nstore_fd( \@files, \*STDOUT );
    },

 

  • Line 19 prints a Storable file to STDOUT
    • This passes a data structure back to the subroutine that initiated the call. 
    • Call this file via the adminfetch() or adminfetchnocache() functions.


The wrapper binary

Build the wrapper binary from the source code in the /usr/local/cpanel/src/wrap/wrap.c file. It is a setuid binary, which you store in the /usr/local/cpanel/bin/ directory.

This binary handles the following tasks:

  • The user's privilege escalation.
  • The parent process that executes the binary is a cPanel process.
  • The flow of data between the admin script and the API call process.

You can modify and distribute the code in the /usr/local/cpanel/src/wrap/wrap.c file for use with cPanel & WHM systems if you meet the following conditions:

  • You may only distribute the code for non-commercial use.

    Note:

    To distribute the code for commercial use, you must obtain written approval from cPanel, Inc. Contact copyright@cpanel.net for details.

  • You must make an uncompiled version of this code publicly available.
  • You must ensure that users understand that cPanel, Inc does not provide support for modified versions of this code.
  • You must ensure that all copyright notices are intact in the modified version.
  • You must list the contact information for the modified version's maintainer within the source code.

When you modify this binary, you must modify the exec_list array to point to the correct admin script and use a unique identifier.

For example, the unmodified binary includes the following code:

1
2
3
struct executable_properties exec_list [1] = {
        "testwrap",      "/usr/local/cpanel/bin/testadmin",      "root""wheel", 1, 0 }
    };

After you make the appropriate changes, the code should resemble the following example:

1
2
3
struct executable_properties exec_list [1] = {
        "myappwrap",      "/usr/local/cpanel/bin/myappadmin",      "root""wheel", 1, 0 }
    };

Note:

You must also change the PROG_NAME variable in the Makefile file.

  • 0 Users Found This Useful
Was this answer helpful?

Related Articles

The cPanel Interface

For  cPanel  &  WHM  version  58 Overview The cPanel interface is...

User Preferences

For cPanel & WHM version 58 Overview This document outlines how to access your cPanel...

Manage External Authentications

For cPanel & WHM version 58 Overview Manage credentials Additional documentation...

What is cPanelID?

In This Article:  Overview ServicesHow to get a cPanelID cPanelID External...

Guide to cPanel Interface Customization - cPanel Style Development

Introduction You can develop custom styles that modify the appearance of the cPanel interface....