Creating a Basic cPanel Plugin Issue

mega_soft

Member
Dec 25, 2014
7
0
51
Egypt
cPanel Access Level
Root Administrator
I try to development my first cPanel plugin, i passed to write live page and install plugin

PHP:
<?php
ini_set('display_startup_errors', 1);
error_reporting(-1);
include("/usr/local/cpanel/php/cpanel.php");  // Instantiate the CPANEL object.
$cpanel = new CPANEL();                       // Connect to cPanel - only do this once.
print $cpanel->header( "Purge Web Server cache" );

// Get domain user data.
$get_userdata = $cpanel->uapi(
    'DomainInfo', 'domains_data',
    array(
        'format'    => 'hash',
        'return_https_redirect_status' => '1',
    )
);

            $domainListApiCall = $cpanel->api2('DomainLookup', 'getbasedomains', array());
            $domainList = $domainListApiCall['cpanelresult']['data'];
            echo '<form class="form-horizontal" action = "" method = "POST" role="form">';
            echo '<div class="form-group"><label for="domain" class="col-sm-2 control-label">Domain Name</label>';
            echo "<div class='col-sm-4'><select name='domainName' class='form-control'>";
            foreach ($domainList as $domain) {
                echo "<option>" . $domain['domain'] . "</option>";
            }
            echo "</select></div>";
        
    echo '<div class="col-sm-6">';
    echo '<input id="next" class="btn btn-primary" type="submit" value="Purge">';
    echo '<div id="status"></div></div>';
    echo "</div></form>";

if(isset($_POST['domainName'])) {

echo shell_exec('bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh '.htmlspecialchars($_POST['domainName']));
echo '<br /><br /><span style="color:Green;text-align:center;"><strong>Web Cache for domain '.htmlspecialchars($_POST['domainName']).' has been Purged</strong></span>';
}

print $cpanel->footer();                      // Add the footer.
$cpanel->end();                               // Disconnect from cPanel - only do this once.
?>
My only problem at execute bash script with root privilege at this line, it return error message Permission denied

echo shell_exec('bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh '.htmlspecialchars($_POST['domainName']));
Please note that i don't have enough experience with Perl scripting

Is there any assist?
 
Last edited by a moderator:

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,880
2,261
463
Hello @mega_soft,

It looks like you are inquiring about this topic as part of support ticket number 11880443. I'm monitoring the support ticket and will update this thread with the outcome once it's closed.

Thank you.
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,880
2,261
463

mega_soft

Member
Dec 25, 2014
7
0
51
Egypt
cPanel Access Level
Root Administrator
Hello,

Thank you for your update

Basically i don't have enough experience at perl language, So if i create a plugin with perl i can't future update or modiffe

But if you can convert current plugin at my first reply to perl language i will be glade
 

cPanelMichael

Administrator
Staff member
Apr 11, 2011
47,880
2,261
463
Hello @mega_soft,

It's outside the scope of support we can offer to develop a custom Perl plugin, however I'm happy to offer advice or link you to an example if you can provide some additional information about the exact functionality you are attempting to include in your plugin.

Thank you.
 

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator
Code:
echo shell_exec('bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh '.htmlspecialchars($_POST['domainName']));
Are you able to run your bash script from the command line? First thing that comes to mind is making sure BASH_FILE.sh has execute permissions.
Code:
chmod +x /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh
Second thing is to look at which user your php script is running as when trying to execute shell_exec and make sure they have permission. I don't recall what the user cpanel uses by default. But you can check when running your script by inserting:
Code:
echo shell_exec("whoami");
Third, maybe BASH_FILE.sh is executing but that code is generating the error. Hard to tell without seeing the code.

Rather than echo for debuggin, a more graceful approach is to bring some logging in so you can see what's going on.
Code:
// Log an error to the LiveAPI error log.
$cpanel->debug_log('1','This is an error message.','false');
Note by default, LiveAPI environments log debugging data to the /home/user/.cpanel/LiveAPI.log.rand file, where user is the cPanel account's username, and rand is a random string that cPanel & WHM generates
Guide to the LiveAPI System - The debug_log() Method - Developer Documentation - cPanel Documentation

You can capture the output of shell_exec and log it like so:
Code:
// Get current user
$output = shell_exec("whoami");
// Log an error to the LiveAPI error log.
$cpanel->debug_log('1',$output,'false');
 

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator
so the file BASH_FILE.sh must executed as root privilege.
Find out what user the php script is running as I mentioned in my previous post, usually apache if using apache. Then add the appropriate privileges to the sudeors. For security purposes I recommend limiting root privileges for apache to the specific script you're trying to run. Like so:

Code:
# from the command line edit /etc/sudoers as root using command visudo
# don't edit it directly, you must use visudo.
visudo

# add the following line, change apache to your php user if needed
# note the wildcard (*) at the end is needed to let the script run with
# any parameters
apache ALL=(ALL) NOPASSWD: /bin/bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh *
 

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator
Ah yes, that makes sense. Here's what you're looking for Guide to Standardized Hooks - Privilege Escalation - Developer Documentation - cPanel Documentation

You should just need to add this to your describe array
Code:
'escalateprivs' => 1,
For future reference, in order to use privilege escalation function the action hook has to be a script, not module.

Scripted hook action code that runs as the cPanel user can escalate that user's privileges.
Hookable events that occur in code that runs as the cPanel user can escalate privileges.
A script must contain the hook action code in order to escalate privileges. Hook action code in Perl modules always executes as the default user for that event.
 
Last edited:

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator
Can you provide me with more details, and what actually i should do?
Oh sorry, I was on mobile and didn't look at the original post. What I said about escalate privileges using the describe array only applies to an action hook. My research indicates cPanel plugins can only run as the calling cpanel user.

What you're looking for is this: Guide to API Privilege Escalation - Developer Documentation - cPanel Documentation

They only provide examples in perl so I'm not sure this can be done with php. But basically, you put your privileged code in a cPanel admin module where it can be run with escalated privileges using Cpanel::AdminBin::Script::Call. Then from your unprivileged plugin script you can call your privileged functions in your admin module.

The workaround, although I wouldn't recommend due to security, is to allow the cpanel user group or even anyone to execute your bash script with root privileges by editing sudoers like mentioned before:
Code:
# from the command line edit /etc/sudoers as root using command visudo
# don't edit it directly, you must use visudo.
visudo

# add the following line, change apache to your php user if needed
# note the wildcard (*) at the end is needed to let the script run with
# any parameters
apache ALL=(ALL) NOPASSWD: /bin/bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh *

# allow GROUP_NAME to run BASH_FILE.sh as root
# this can be a security issue so use with caution
%GROUP_NAME ALL=(ALL) NOPASSWD: /bin/bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh *

# allow any user to run BASH_FILE.sh as root
# this can be a security issue so use with caution
ALL ALL=NOPASSWD: /bin/bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh *
If this is the way you want to proceed then I would make sure your bash script is validating and sanitizing appropriately. Also, any recent sudo version should allow hash integrity checking to ensure the script hasn't been modified. The complete process would be something like this:
Code:
# Generate hash of your completed bash script from command line
$ sha256sum /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh
# copy hash somewhere
# edit /etc/sudoers
$ visudo

# add the following, replace HASH_HERE with your generated hash
# you can use the * at the end like before to allow any args,
# but more secure to specify only the args your script is using
# edit: just realized domain_arg is changing so you'll probably need *
Cmnd_Alias MY_BASH_FILE= sha256:HASH_HERE /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh domain_arg

# allow any user to run MY_BASH_FILE as root
# again this can be a security issue depending on your script so use with caution
# you probably don't need to include /bin/bash from previous example
ALL ALL=NOPASSWD: MY_BASH_FILE
edit: just wanted to mention that the entries you add using visudo need to go at the end to override any previous entries in the file.

2nd edit: you probably need to include 'sudo' in your shell_exec() to run BASH_FILE.sh with privileges. I don't think it just does it automatically for you.

Maybe someone else can chime in with an alternative.
 
Last edited:

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator

mega_soft

Member
Dec 25, 2014
7
0
51
Egypt
cPanel Access Level
Root Administrator
Hello,

I did the following:

Create index.live.pl instead of index.live.php and locate at /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME

Code:
#!/usr/bin/perl
 
# Instantiate the Cpanel::LiveAPI object.
use Cpanel::LiveAPI ();
 
# Connect to cPanel - only do this once.
my $cpliveapi = Cpanel::LiveAPI->new();
 
# Get domain user data.
my $get_userdata = $cpliveapi->uapi(
    'DomainInfo', 'domains_data',
    {
        'format'    => 'hash',
    }
);
 
# Perform the desired actions.


# Disconnect from cPanel - only do this once.
$cpanel->end();
then create a bin file and conf with paths

/usr/local/cpanel/bin/admin/PLUGIN_NAME/PLUGIN_NAME.conf
Code:
mode=full
/usr/local/cpanel/bin/admin/PLUGIN_NAME/PLUGIN_NAME
Code:
#!/usr/local/cpanel/3rdparty/bin/perl

package purgecache::purgecache;

use strict;

use parent 'Cpanel::AdminBin::Script::Call';

__PACKAGE__->run() if !caller;

sub _actions { return qw( DO_GOOD ) }

sub DO_GOOD {
 my ($self, $arg1, $arg2) = @_;
 return "I did good with "$arg1" and "$arg2->[0]".";
}

1;
righ now i need assist to convert PHP to Perl code
PHP:
            $domainListApiCall = $cpanel->api2('DomainLookup', 'getbasedomains', array());
            $domainList = $domainListApiCall['cpanelresult']['data'];
            echo '<form class="form-horizontal" action = "" method = "POST" role="form">';
            echo '<div class="form-group"><label for="domain" class="col-sm-2 control-label">Domain Name</label>';
            echo "<div class='col-sm-4'><select name='domainName' class='form-control'>";
            foreach ($domainList as $domain) {
                echo "<option>" . $domain['domain'] . "</option>";
            }
            echo "</select></div>";
       
    echo '<div class="col-sm-6">';
    echo '<input id="next" class="btn btn-primary" type="submit" value="Purge">';
    echo '<div id="status"></div></div>';
    echo "</div></form>";

if(isset($_POST['domainName'])) {

echo shell_exec('bash /usr/local/cpanel/base/frontend/paper_lantern/PLUGIN_NAME/BASH_FILE.sh '.htmlspecialchars($_POST['domainName']));
echo '<br /><br /><span style="color:Green;text-align:center;"><strong>Web Cache for domain '.htmlspecialchars($_POST['domainName']).' has been Purged</strong></span>';
}
then what next i can do

sorry for the inconvenience, But i was forced from my boss to complete this plugin because he thought that development is apart of sysadmins tasks :(
 

kdub

Active Member
Apr 19, 2019
29
8
3
California
cPanel Access Level
Root Administrator
@mega_soft I totally get where you are coming from. I mean no offense, but you're unlikely to get anyone to freely write this plugin for you. I suggest you look into hiring someone. It's a fairly simple plugin so I'm guessing the cost would be minimal, and well worth the time saved and headache avoided. You can google for cpanel developers. I'm not affiliated with upwork or any of the service providers listed here but maybe these will help:

- Removed -
System Administration Services | cPanel Forums
 
Last edited by a moderator:
  • Like
Reactions: cPanelMichael