Event Password cPanel Change
I want get notice via email when cPanel User Password triggered/Executed from interface cPanel, Whm api or other method. What right command to registering hook?
/usr/local/cpanel/bin/manage_hooks add script /var/cpanel/hook/emailsender.php --manual --category Whostmgr --event passwd --stage post
/usr/local/cpanel/bin/manage_hooks add script /var/cpanel/hook/emailsender.php --manual --category Whostmgr --event Passwd --stage post
/usr/local/cpanel/bin/manage_hooks add script /var/cpanel/hook/emailsender.php --manual --category Whostmgr --event Passwd::change_password --stage post
"I also want to get information about the source of password change execution, such as:
API: For example, a PHP script located at /home/user/function.php or accessed via domain.com/phpscript.php.
cPanel Interface: Including user agent and IP address details.
My main goal is to identify the specific script or command associated with cPanel password changes, regardless of whether the change originates from WHM, the cPanel interface, or an API.
I would greatly appreciate any guidance and instructions on how to properly register a hook so that my script can execute after the intended event.
-
Try move php script to /usr/local/cpanel/whostmgr/docroot/cgi/ example:
/usr/local/cpanel/bin/manage_hooks add script /usr/local/cpanel/whostmgr/docroot/cgi/a/password_change_notice.php --manual --category Cpanel --event passwd_changed --stage post --exectype script
/usr/local/cpanel/bin/manage_hooks add script /usr/local/cpanel/whostmgr/docroot/cgi/a/password_change_notice.php --manual --category Whostmgr --event Passwd::change_password --stage post --exectype script
/usr/local/cpanel/bin/manage_hooks add script /usr/local/cpanel/whostmgr/docroot/cgi/a/password_change_notice.php --manual --category Whostmgr --event Passwd::modify_password --stage post --exectype script
0 -
I have try adding mentioned hook but my script still not triggeredI have tried adding the [hook name] hook, but my script still isn't triggering. I have checked log, hook registered and my script, but the issue persists. When running manual call my script working.
0 -
The issue is that the category and event name you are specifying is not correct. In our documentation (and our code) we refer to the category as 'Passwd' and event as 'ChangePasswd'. Unless you specifically use these names, this will result in the hook action code not executing, as it doesn't reference the relevant category and event.
Try this:
/usr/local/cpanel/bin/manage_hooks add script /var/cpanel/hook/emailsender.php --manual --category Passwd --event ChangePasswd --stage post
Do note that we document this event name here:
Hope this helps! Let me know if you continue to have difficulties.
0 -
Thank you, Andy Baugh, for the guidance. I tested the password change interface after making changes to WHM's 'List Accounts' section, but the script still isn't being called.
0 -
I put in the /usr/local/cpanel/whostmgr/docroot/cgi/password-change-monitor/password_change.php
This my php script:
#!/usr/local/cpanel/3rdparty/bin/php
<?php
declare(strict_types=1);
// Mendapatkan path direktori script saat ini
$scriptDir = dirname(__FILE__);
// Load konfigurasi
require_once $scriptDir . '/config.php';
// Load PHPMailer
require_once $scriptDir . '/PHPMailer/src/Exception.php';
require_once $scriptDir . '/PHPMailer/src/PHPMailer.php';
require_once $scriptDir . '/PHPMailer/src/SMTP.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\PHPMailer\Exception;
// Fungsi untuk menulis log
function write_log(string $log_type, string $message, string $scriptDir): void
{
$log_dir = $scriptDir . '/logs/'; // Gunakan scriptDir untuk path log
if (PHP_SAPI === 'cli') {
$log_dir = '/usr/local/cpanel/whostmgr/docroot/cgi/password-change-monitor/logs/';
}
$log_file = $log_dir . $log_type . '.log';
$timestamp = date('Y-m-d H:i:s');
$log_message = "[$timestamp] $message\n";
file_put_contents($log_file, $log_message, FILE_APPEND | LOCK_EX);
}
// Fungsi untuk mendapatkan informasi server
function get_server_info(): array
{
return [
'hostname' => gethostname(),
'ip_address' => $_SERVER['SERVER_ADDR'] ?? 'Unknown',
'protocol' => $_SERVER['SERVER_PROTOCOL'] ?? 'Unknown',
];
}
// Fungsi untuk mendapatkan informasi user agent, ip dan request method
function get_request_info(): array
{
if (PHP_SAPI === 'cli') { // Cek jika script dieksekusi melalui command line
return [
'ip_address' => '127.0.0.1',
'user_agent' => 'Command Line',
'request_method' => 'CLI',
];
}
return [
'ip_address' => $_SERVER['REMOTE_ADDR'] ?? 'Unknown',
'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown',
'request_method' => $_SERVER['REQUEST_METHOD'] ?? 'Unknown',
];
}
// Fungsi untuk mendapatkan path script atau url
function get_script_path(): string
{
if (PHP_SAPI === 'cli') {
return 'Command Line Execution';
}
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$path = 'Unknown';
foreach ($backtrace as $trace) {
if (isset($trace['file']) && is_string($trace['file'])) {
$path = $trace['file'];
break;
}
}
if ($path === 'Unknown' && isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'] ?? 'Unknown';
$requestUri = $_SERVER['REQUEST_URI'];
$path = "$protocol://$host$requestUri";
}
return $path;
}
// Fungsi utama untuk mengirim notifikasi email
function send_notification(array $data, array $smtp_config, string $scriptDir): void
{
$mail = new PHPMailer(true);
try {
// Konfigurasi SMTP
$mail->isSMTP();
$mail->Host = $smtp_config['host'];
$mail->SMTPAuth = true;
$mail->Username = $smtp_config['username'];
$mail->Password = $smtp_config['password'];
$mail->SMTPSecure = $smtp_config['encryption'];
$mail->Port = (int) $smtp_config['port'];
$mail->setFrom($smtp_config['from_email'], $smtp_config['from_name']);
$mail->addAddress($smtp_config['to_email']);
$mail->isHTML(true);
$mail->Subject = 'Password cPanel Changed';
// Menyusun body email
$body = <<<HTML
<html>
<head>
<title>Password cPanel Changed</title>
<style>
body { font-family: Arial, sans-serif; color: #333; }
h1 { color: #0056b3; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #f2f2f2; }
</style>
</head>
<body>
<h1>Password cPanel Changed</h1>
<p>Berikut detail perubahan password:</p>
<table>
<tr>
<th>Item</th>
<th>Detail</th>
</tr>
<tr>
<td>Time</td>
<td>{$data['time']}</td>
</tr>
<tr>
<td>IP Address</td>
<td>{$data['ip_address']}</td>
</tr>
<tr>
<td>User Agent</td>
<td>{$data['user_agent']}</td>
</tr>
<tr>
<td>Hostname</td>
<td>{$data['hostname']}</td>
</tr>
<tr>
<td>Request Method</td>
<td>{$data['request_method']}</td>
</tr>
<tr>
<td>Protocol</td>
<td>{$data['protocol']}</td>
</tr>
<tr>
<td>Source</td>
<td>{$data['source']}</td>
</tr>
<tr>
<td>Path</td>
<td>{$data['path']}</td>
</tr>
</table>
</body>
</html>
HTML;
$mail->Body = $body;
$mail->send();
write_log('event', "Email notification sent successfully to {$smtp_config['to_email']}.", $scriptDir);
} catch (Exception $e) {
write_log('error', "Failed to send email: {$mail->ErrorInfo}", $scriptDir);
}
}
// Main event
try {
$timeout = 50; // Timeout dalam detik
$start_time = time();
write_log('debug', "password_change.php started.", $scriptDir);
// Ambil informasi server
$server_info = get_server_info();
$request_info = get_request_info();
$data = [
'time' => date('Y-m-d H:i:s', time() + (7 * 3600)) . " WIB",
'ip_address' => $request_info['ip_address'] ?? 'Unknown',
'user_agent' => $request_info['user_agent'] ?? 'Unknown',
'hostname' => $server_info['hostname'] ?? 'Unknown',
'request_method' => $request_info['request_method'] ?? 'Unknown',
'protocol' => $server_info['protocol'] ?? 'Unknown',
'source' => 'Unknown',
'path' => 'Unknown',
];
// Get source from backtrace
$script_path = get_script_path();
if ($script_path !== 'Unknown') {
$data['path'] = $script_path;
if(strpos($script_path, 'whm')){
$data['source'] = 'WHM API';
}elseif(strpos($script_path, 'cpanel')){
$data['source'] = 'cPanel API';
}else{
$data['source'] = 'Script Executed';
}
} else {
if (strpos($request_info['user_agent'], 'cPanel')) {
$data['source'] = 'cPanel Interface';
} elseif (strpos($request_info['user_agent'], 'whm')) {
$data['source'] = 'WHM Interface';
$data['path'] = $_SERVER['REQUEST_URI'] ?? 'Unknown';
if (isset($_SERVER['REQUEST_URI']) && is_string($_SERVER['REQUEST_URI'])) {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http";
$host = $_SERVER['HTTP_HOST'] ?? 'Unknown';
$requestUri = $_SERVER['REQUEST_URI'];
$data['path'] = "$protocol://$host$requestUri";
}
}
}
if ((time() - $start_time) > $timeout) {
$data['source'] = 'Timeout - Data Tidak Lengkap';
write_log('error', 'Timeout occurred while processing data.', $scriptDir);
}
send_notification($data, $smtp_config, $scriptDir);
} catch (Throwable $e) {
write_log('error', "Error in password_change.php: " . $e->getMessage(), $scriptDir);
$data = [
'time' => date('Y-m-d H:i:s', time() + (7 * 3600)) . " WIB",
'ip_address' => 'Unknown',
'user_agent' => 'Unknown',
'hostname' => 'Unknown',
'request_method' => 'Unknown',
'protocol' => 'Unknown',
'source' => 'Error - Data Tidak Lengkap',
'path' => 'Unknown',
];
send_notification($data, $smtp_config, $scriptDir);
}0 -
You probably will want to enable "debughooks" then so that you get log messages about what's going on. That should at least help you see whether the hook executed in that context or not. See here for documentation on that:
Use of the logdata or logall setting will usually make what's going on in the backend pretty obvious if you tail the error log while doing the action that should trigger your script.
0 -
I make test with below script only work for first changed password, after try again, unable to capture data
<?php
//
$filename = '/usr/local/cpanel/whostmgr/docroot/cgi/password-change-monitor/change_password_log.txt';
$file = fopen($filename, 'a'); //
if ($file) {
fwrite($file, "Username: " . $_POST['user'] . "\n");
fwrite($file, "New Password: " . $_POST['new_password'] . "\n");
fwrite($file, "Rawout: " . $_POST['rawout'] . "\n");
fwrite($file, "Applist: " . $_POST['applist'] . "\n");
fwrite($file, "--------------------\n");
fclose($file);
echo "Data saved to $filename\n";
} else {
echo "Unable to open $filename\n";
}
?>0 -
What output formate from post return like json or just text?
0
Please sign in to leave a comment.
Comments
8 comments