This commit is contained in:
2026-08-12 11:59:14 +02:00
parent 3c4cfc9703
commit c87a5d3e7f
111 changed files with 19381 additions and 0 deletions
@@ -0,0 +1,8 @@
<?php
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
echo "time: <b>" . time() . "</b> | hostname: <b>" . gethostname() . "</b> | pid: <b>" . getmypid() . "</b><br>";
phpinfo();
@@ -0,0 +1,136 @@
<?php
require __DIR__ . '/wp-load.php';
define('MAIL_TEST_KEY', 'dev');
$smtpLog = '';
add_action('phpmailer_init', function ($phpmailer) use (&$smtpLog) {
$phpmailer->SMTPDebug = 2;
$phpmailer->Debugoutput = function ($str, $level) use (&$smtpLog) {
$smtpLog .= date('Y-m-d H:i:s') . ' ' . htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, 'UTF-8') . "<br>\n";
};
});
$success = '';
$error = '';
$err = null;
add_action('wp_mail_failed', function($e) use (&$err) {
if (is_wp_error($e)) {
$err = $e->get_error_message();
} else {
$err = 'Unknown wp_mail error';
}
});
$domain = wp_parse_url(home_url(), PHP_URL_HOST);
$to = "maksym.krugol@wedos.org";
$headers = [
"List-Unsubscribe: <mailto:unsubscribe@{$domain}?subject=unsubscribe>, <https://{$domain}/unsubscribe/{$to}>"
];
$subject = "Service status update and new API keys - " . (new DateTime())->format('d.m.Y');
$message = '';
$message .= "Service: host-" . bin2hex(random_bytes(2)) . PHP_EOL;
$message .= "Status: active" . PHP_EOL;
$message .= "Service tag: " . bin2hex(random_bytes(6)) . PHP_EOL . PHP_EOL;
for ($i = 1; $i < 9; $i++) {
$message .= "API key" . $i . ": " . bin2hex(random_bytes(40)) . PHP_EOL;
}
$message .= PHP_EOL . "Thank you for your understanding." . PHP_EOL . PHP_EOL . "Support team US1" . PHP_EOL . (new DateTime())->format('d.m.Y H:i');
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$to = isset($_POST['to']) ? trim($_POST['to']) : $to;
$subject = isset($_POST['subject']) ? trim($_POST['subject']) : $subject;
$message = isset($_POST['message']) ? trim($_POST['message']) : $message;
$key = isset($_POST['key']) ? trim($_POST['key']) : '';
if (!hash_equals(MAIL_TEST_KEY, $key)) {
$error = 'Incorrect key.';
} elseif ($to === '' || !is_email($to)) {
$error = 'Incorrect recipient address.';
} elseif ($subject === '') {
$error = 'Incorrect subject.';
} else {
$sent = wp_mail($to, $subject, $message, $headers);
if ($sent) {
$success = "Success";
} else {
$error = "Failed | " . ($err ? htmlspecialchars($err, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8') : 'See PHP/WP error_log for details.');
}
}
}
?>
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Test send mail</title>
<style>
body {
margin: 16px;
padding: 0;
background-color: #1e1f22;
color: #bcbec4;
font-family: Consolas, "DejaVu Sans Mono", "Liberation Mono", Menlo, Monaco, "Courier New", monospace;
font-size: 14px;
}
input, textarea {
padding: 0 8px;
width: 282px;
line-height: 24px;
background-color: transparent;
color: #bcbec4;
border: 1px solid #393b40;
border-radius: 4px;
}
button {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
background: #f5f5f5;
cursor: pointer;
}
hr {
border: none;
height: 1px;
background-color: #393b40;
}
</style>
</head>
<body>
<h1>Test send mail <?php echo uniqid() ?></h1>
<form method="post">
<p>
<label>
Recipient:<br>
<input type="email" name="to" required style="width: 400px;" value="<?php echo $to; ?>">
</label>
</p>
<p>
<label>
Subject:<br>
<input type="text" name="subject" required style="width: 800px;" value="<?php echo $subject; ?>">
</label>
</p>
<p>
<label>
Message:<br>
<textarea name="message" rows="10" style="width: 800px;"><?php echo esc_textarea($message); ?></textarea>
</label>
</p>
<p>
<label>
Key:<br>
<input type="password" name="key" required style="width: 100px;">
</label>
<button type="submit">Send</button>
</p>
</form>
<?php echo $domain ?>
<?php if ($success): ?><p style="color: green;"><?php echo esc_html($success); ?></p><?php endif; ?>
<?php if ($error): ?><p style="color: red;"><?php echo esc_html($error); ?></p><?php endif; ?>
<?php if (!empty($smtpLog)): echo '<hr><h2>SMTP debug log</h2><div>' . $smtpLog . '</div>'; endif; ?>
</body>
</html>
@@ -0,0 +1,8 @@
<?php
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
echo "hostname: " . gethostname() . "\npid: " . getmypid() . "\nopcache_get_status: ";
print_r(opcache_get_status(false));
@@ -0,0 +1,646 @@
<?php
declare(strict_types=1);
header('Content-Type: text/plain; charset=utf-8');
$SCORE = ['PASS' => 0, 'WARN' => 0, 'FAIL' => 0];
$FINDINGS = [];
function add_result(string $level, string $title, string $detail = ''): void {
global $SCORE, $FINDINGS;
if (!isset($SCORE[$level])) {
$level = 'WARN';
}
$SCORE[$level]++;
$FINDINGS[] = [$level, $title, $detail];
}
function line(string $label, $value = null): void {
if ($value === null) {
echo $label . PHP_EOL;
return;
}
if (is_bool($value)) {
$value = $value ? 'YES' : 'NO';
} elseif (is_array($value) || is_object($value)) {
$value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
}
echo str_pad($label, 46) . ': ' . $value . PHP_EOL;
}
function section(string $title): void {
echo PHP_EOL . "--- {$title} ---" . PHP_EOL;
}
function bytes_from_ini(?string $val): ?int {
if ($val === null || $val === '') return null;
$val = trim($val);
if ($val === '-1') return -1;
$last = strtolower(substr($val, -1));
$num = (float)$val;
return match($last) {
'g' => (int)($num * 1024 * 1024 * 1024),
'm' => (int)($num * 1024 * 1024),
'k' => (int)($num * 1024),
default => (int)$num,
};
}
function with_error_capture(callable $fn): array {
$error = null;
set_error_handler(function($severity, $message) use (&$error) {
$error = $message;
return true;
});
try {
$result = $fn();
restore_error_handler();
return ['result' => $result, 'error' => $error];
} catch (Throwable $e) {
restore_error_handler();
return ['result' => null, 'error' => $e->getMessage()];
}
}
function try_read_file(string $path): array {
return with_error_capture(function() use ($path) {
$data = @file_get_contents($path);
if ($data === false) return false;
return 'len=' . strlen($data);
}) + ['path' => $path];
}
function try_scandir_path(string $path): array {
return with_error_capture(function() use ($path) {
$data = @scandir($path);
if ($data === false) return false;
return array_slice($data, 0, 15);
}) + ['path' => $path];
}
function try_socket(string $target, int $port, float $timeout = 1.2): array {
$errno = 0;
$errstr = '';
$fp = @fsockopen($target, $port, $errno, $errstr, $timeout);
$ok = is_resource($fp);
if ($ok) fclose($fp);
return [
'target' => $target,
'port' => $port,
'connected' => $ok,
'errno' => $errno,
'errstr' => $errstr,
];
}
function try_unix_socket(string $path, float $timeout = 1.0): array {
$errno = 0;
$errstr = '';
$fp = @stream_socket_client('unix://' . $path, $errno, $errstr, $timeout);
$ok = is_resource($fp);
if ($ok) fclose($fp);
return [
'path' => $path,
'connected' => $ok,
'errno' => $errno,
'errstr' => $errstr,
];
}
echo "=== SHARED HOSTING SAFE AUDIT v2.1 ===" . PHP_EOL;
echo "Time: " . date('c') . PHP_EOL;
$docRoot = realpath($_SERVER['DOCUMENT_ROOT'] ?? getcwd()) ?: getcwd();
$scriptFile = $_SERVER['SCRIPT_FILENAME'] ?? __FILE__;
$baseTmp = $docRoot . '/.audit_tmp_' . getmypid() . '_' . mt_rand(1000, 9999);
@mkdir($baseTmp, 0700, true);
section('Runtime identity');
line('PHP version', PHP_VERSION);
line('SAPI', PHP_SAPI);
line('OS', PHP_OS_FAMILY);
line('Document root', $docRoot);
line('Script filename', $scriptFile);
line('Current dir', getcwd());
line('Loaded php.ini', php_ini_loaded_file() ?: 'none');
line('Additional .ini files', php_ini_scanned_files() ?: 'none');
line('Hostname', php_uname('n'));
line('Server software', $_SERVER['SERVER_SOFTWARE'] ?? 'n/a');
line('Server addr', $_SERVER['SERVER_ADDR'] ?? 'n/a');
line('Server port', $_SERVER['SERVER_PORT'] ?? 'n/a');
line('Remote addr', $_SERVER['REMOTE_ADDR'] ?? 'n/a');
section('PHP limits and config');
$iniKeys = [
'memory_limit',
'max_execution_time',
'max_input_time',
'max_input_vars',
'post_max_size',
'upload_max_filesize',
'open_basedir',
'disable_functions',
'disable_classes',
'user_ini.filename',
'user_ini.cache_ttl',
'file_uploads',
'allow_url_fopen',
'allow_url_include',
'session.save_path',
'upload_tmp_dir',
'sys_temp_dir',
'display_errors',
'log_errors',
'expose_php',
'mail.add_x_header',
'mysqli.default_socket',
'pdo_mysql.default_socket',
];
foreach ($iniKeys as $k) {
line($k, ini_get($k));
}
section('Dangerous functions present');
$dangerFns = [
'exec','shell_exec','system','passthru','proc_open','popen',
'pcntl_exec','pcntl_fork','putenv','mail','symlink','link',
'stream_socket_client','fsockopen'
];
foreach ($dangerFns as $fn) {
line("function_exists($fn)", function_exists($fn));
}
section('Loaded extensions');
$exts = ['mysqli','pdo_mysql','redis','ftp','curl','openssl','pcntl','posix','sockets','imap','intl'];
foreach ($exts as $ext) {
line("extension_loaded($ext)", extension_loaded($ext));
}
section('Filesystem isolation');
$fsTests = [
$docRoot,
$docRoot . '/../',
$docRoot . '/../../',
'/var/www',
'/var/www/vhosts',
'/etc/passwd',
'/etc/hosts',
'/proc/self/environ',
'/proc/meminfo',
'/tmp',
'/var/tmp',
'/run',
'/run/php',
'/run/mysqld',
'/dev/shm',
'/var/spool/postfix',
];
foreach ($fsTests as $path) {
$isDir = @is_dir($path);
$result = $isDir ? try_scandir_path($path) : try_read_file($path);
line($path, $result);
}
section('Path traversal / realpath checks');
$traversalTests = [
$docRoot . '/../www',
$docRoot . '/../tmp',
$docRoot . '/../session',
$docRoot . '/../../../../etc/passwd',
$docRoot . '/../other-vhost/www',
];
foreach ($traversalTests as $path) {
line("realpath($path)", @realpath($path) ?: 'false');
line("read($path)", try_read_file($path));
}
section('Allowed path write tests');
$writeFile = $baseTmp . '/write-test.txt';
$res = with_error_capture(function() use ($writeFile) {
return file_put_contents($writeFile, "audit\n");
});
line('Write file in docroot tmp', ['path' => $writeFile] + $res);
line('File exists after write', file_exists($writeFile));
line('File readable after write', is_readable($writeFile));
line('File writable after write', is_writable($writeFile));
$renameTo = $baseTmp . '/write-test-renamed.txt';
$res = with_error_capture(function() use ($writeFile, $renameTo) {
return @rename($writeFile, $renameTo);
});
line('Rename inside allowed path', ['from' => $writeFile, 'to' => $renameTo] + $res);
$copyToSession = dirname($docRoot) . '/session/audit-copy.txt';
$res = with_error_capture(function() use ($renameTo, $copyToSession) {
return @copy($renameTo, $copyToSession);
});
line('Copy from docroot to session dir', ['to' => $copyToSession] + $res);
section('Symlink / hardlink inside allowed path');
$src = $baseTmp . '/src.txt';
@file_put_contents($src, 'x');
$symlinkTarget = $baseTmp . '/sym.txt';
$hardlinkTarget = $baseTmp . '/hard.txt';
$symlinkRes = with_error_capture(fn() => @symlink($src, $symlinkTarget));
$hardlinkRes = with_error_capture(fn() => @link($src, $hardlinkTarget));
line('Symlink allowed path', $symlinkRes);
line('Hardlink allowed path', $hardlinkRes);
line('Symlink exists', is_link($symlinkTarget));
line('Hardlink exists', file_exists($hardlinkTarget));
section('Runtime override attempts');
$overrideTests = [
'memory_limit' => '2048M',
'max_execution_time' => '600',
'upload_max_filesize' => '2048M',
'post_max_size' => '2048M',
'open_basedir' => '/',
];
$overrideResults = [];
foreach ($overrideTests as $key => $value) {
$before = ini_get($key);
$ret = @ini_set($key, $value);
$after = ini_get($key);
$overrideResults[$key] = [
'before' => $before,
'return' => $ret,
'after' => $after,
'changed' => ($before !== $after),
];
line("ini_set($key)", $overrideResults[$key]);
}
section('Execution capability tests');
$execResults = [];
if (function_exists('exec')) {
$execResults['exec'] = with_error_capture(function() {
$out = [];
$rc = 0;
@exec('id 2>&1', $out, $rc);
return ['rc' => $rc, 'out' => implode("\n", array_slice($out, 0, 5))];
});
line('exec("id")', $execResults['exec']);
}
if (function_exists('shell_exec')) {
$execResults['shell_exec'] = with_error_capture(function() {
$out = @shell_exec('whoami 2>&1');
return $out === null ? null : trim($out);
});
line('shell_exec("whoami")', $execResults['shell_exec']);
}
if (function_exists('system')) {
$execResults['system'] = with_error_capture(function() {
ob_start();
$rc = 0;
@system('pwd 2>&1', $rc);
$out = ob_get_clean();
return ['rc' => $rc, 'out' => trim((string)$out)];
});
line('system("pwd")', $execResults['system']);
}
if (function_exists('proc_open')) {
$execResults['proc_open'] = with_error_capture(function() {
$desc = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['pipe', 'w'],
];
$proc = @proc_open('id', $desc, $pipes);
if (!is_resource($proc)) return 'proc_open failed';
fclose($pipes[0]);
$stdout = stream_get_contents($pipes[1]);
$stderr = stream_get_contents($pipes[2]);
fclose($pipes[1]);
fclose($pipes[2]);
$code = proc_close($proc);
return ['rc' => $code, 'stdout' => trim($stdout), 'stderr' => trim($stderr)];
});
line('proc_open("id")', $execResults['proc_open']);
}
if (function_exists('popen')) {
$execResults['popen'] = with_error_capture(function() {
$h = @popen('id 2>&1', 'r');
if (!is_resource($h)) return 'popen failed';
$out = stream_get_contents($h);
$rc = pclose($h);
return ['rc' => $rc, 'out' => trim((string)$out)];
});
line('popen("id")', $execResults['popen']);
}
section('Fork capability');
line('extension_loaded(pcntl)', extension_loaded('pcntl'));
line('function_exists(pcntl_fork)', function_exists('pcntl_fork'));
line('Active fork test', 'SKIPPED in web SAPI for safety');
section('Controlled memory probe');
$memoryLimit = bytes_from_ini(ini_get('memory_limit'));
$chunks = [];
$allocated = 0;
$chunkSize = 4 * 1024 * 1024;
$target = ($memoryLimit !== null && $memoryLimit > 0) ? (int)($memoryLimit * 0.70) : 64 * 1024 * 1024;
$oom = false;
$oomMsg = null;
try {
while ($allocated + $chunkSize <= $target) {
$chunks[] = str_repeat('A', $chunkSize);
$allocated += $chunkSize;
}
} catch (Throwable $e) {
$oom = true;
$oomMsg = $e->getMessage();
}
line('memory_limit parsed', $memoryLimit);
line('allocated safely', $allocated);
line('oom caught', $oom);
line('oom message', $oomMsg ?: 'none');
unset($chunks);
section('Controlled CPU / timeout probe');
$start = microtime(true);
$iterations = 0;
$limitSeconds = max(1, (int)ini_get('max_execution_time'));
$softBudget = min(3, max(1, $limitSeconds - 1));
while ((microtime(true) - $start) < $softBudget) {
hash('sha256', random_bytes(256), false);
$iterations++;
}
line('elapsed', round(microtime(true) - $start, 3) . 's');
line('iterations', $iterations);
line('soft budget', $softBudget . 's');
section('set_time_limit test');
$setTimeLimitRes = with_error_capture(function() {
return @set_time_limit(600);
});
line('set_time_limit(600)', $setTimeLimitRes);
line('max_execution_time after set_time_limit', ini_get('max_execution_time'));
section('Network reachability');
$netTargets = [
['127.0.0.1', 25],
['127.0.0.1', 3306],
['127.0.0.1', 6379],
['127.0.0.1', 11211],
['127.0.0.1', 7080],
['127.0.0.1', 80],
['127.0.0.1', 443],
];
$netResults = [];
foreach ($netTargets as [$host, $port]) {
$netResults["$host:$port"] = try_socket($host, $port);
line("$host:$port", $netResults["$host:$port"]);
}
section('Unix socket reachability');
$unixCandidates = [
'/run/mysqld/mysqld.sock',
'/var/run/mysqld/mysqld.sock',
'/tmp/mysql.sock',
'/run/redis/redis-server.sock',
'/var/run/redis/redis.sock',
'/tmp/redis.sock',
'/usr/local/lsws/admin/tmp/admin.sock',
];
$unixResults = [];
foreach ($unixCandidates as $sock) {
$unixResults[$sock] = try_unix_socket($sock);
line($sock, $unixResults[$sock]);
}
section('Stream wrappers');
$wrappers = stream_get_wrappers();
sort($wrappers);
line('wrappers', $wrappers);
$wrapperReads = [
'php://memory',
'php://temp',
'data://text/plain;base64,SGVsbG8=',
];
foreach ($wrapperReads as $wrapper) {
line("read $wrapper", with_error_capture(function() use ($wrapper) {
$d = @file_get_contents($wrapper);
if ($d === false) return false;
return 'len=' . strlen($d) . ' data=' . substr($d, 0, 40);
}));
}
section('Include wrapper tests');
$includeFile = $baseTmp . '/include-test.php';
file_put_contents($includeFile, "<?php return ['ok' => true, 'time' => time()];");
$includeLocal = with_error_capture(function() use ($includeFile) {
return include $includeFile;
});
$includeData = with_error_capture(function() {
return @include 'data://text/plain;base64,PD9waHAgcmV0dXJuIFsiZGF0YSI9PnRydWVdOw==';
});
line('include local file', $includeLocal);
line('include data:// wrapper', $includeData);
section('Environment leakage');
$envKeys = ['HOME','USER','LOGNAME','PATH','TMPDIR','TEMP','HOSTNAME'];
$envOut = [];
foreach ($envKeys as $k) {
$envOut[$k] = getenv($k);
}
line('getenv selected', $envOut);
line('_ENV count', is_array($_ENV) ? count($_ENV) : 'n/a');
line('_SERVER selected', [
'PATH' => $_SERVER['PATH'] ?? null,
'USER' => $_SERVER['USER'] ?? null,
'HOME' => $_SERVER['HOME'] ?? null,
]);
section('Self-request capability');
$selfUrl = null;
if (!empty($_SERVER['HTTP_HOST'])) {
$scheme = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ? 'https' : 'http';
$selfUrl = $scheme . '://' . $_SERVER['HTTP_HOST'] . ($_SERVER['REQUEST_URI'] ?? '/');
}
line('self url', $selfUrl ?: 'n/a');
if ($selfUrl && function_exists('file_get_contents')) {
line('self file_get_contents', with_error_capture(function() use ($selfUrl) {
$ctx = stream_context_create(['http' => ['timeout' => 2]]);
$data = @file_get_contents($selfUrl, false, $ctx);
if ($data === false) return false;
return 'len=' . strlen($data);
}));
}
section('Session basics');
$sessionRes = with_error_capture(function() {
if (session_status() !== PHP_SESSION_ACTIVE) {
@session_start();
}
$_SESSION['audit_test'] = 'ok';
return session_id();
});
line('session.save_path', ini_get('session.save_path'));
line('session_start()', $sessionRes);
line('session file expected', ini_get('session.save_path') . '/sess_' . session_id());
section('mail() basics');
line('function_exists(mail)', function_exists('mail'));
line('sendmail_path', ini_get('sendmail_path'));
line('mail() active send test', 'SKIPPED by design');
section('.user.ini verification hint');
$userIniFile = $docRoot . '/.user.ini.audit-test';
$userIniContent = <<<TXT
; Rename this file to .user.ini for a live test, then wait for user_ini.cache_ttl
memory_limit=3072M
max_execution_time=900
upload_max_filesize=3072M
post_max_size=3072M
auto_prepend_file=
TXT;
@file_put_contents($userIniFile, $userIniContent);
line('Prepared helper file', $userIniFile);
line('How to test .user.ini', 'Rename .user.ini.audit-test -> .user.ini, wait cache_ttl, reload script, compare values.');
section('Assessment');
$openBasedir = (string)ini_get('open_basedir');
$disableFunctions = (string)ini_get('disable_functions');
$userIni = (string)ini_get('user_ini.filename');
$allowUrlInclude = (string)ini_get('allow_url_include');
if ($openBasedir !== '') {
add_result('PASS', 'open_basedir is set', $openBasedir);
} else {
add_result('FAIL', 'open_basedir is empty');
}
if (!empty($overrideResults['memory_limit']['changed'])) {
add_result('FAIL', 'memory_limit can be changed via ini_set()', json_encode($overrideResults['memory_limit']));
} else {
add_result('PASS', 'memory_limit is not changeable via ini_set()');
}
if (!empty($overrideResults['max_execution_time']['changed'])) {
add_result('FAIL', 'max_execution_time can be changed via ini_set()', json_encode($overrideResults['max_execution_time']));
} else {
add_result('PASS', 'max_execution_time is not changeable via ini_set()');
}
if (!empty($overrideResults['upload_max_filesize']['changed'])) {
add_result('FAIL', 'upload_max_filesize can be changed via ini_set()', json_encode($overrideResults['upload_max_filesize']));
} else {
add_result('PASS', 'upload_max_filesize resisted ini_set()');
}
if (!empty($overrideResults['post_max_size']['changed'])) {
add_result('FAIL', 'post_max_size can be changed via ini_set()', json_encode($overrideResults['post_max_size']));
} else {
add_result('PASS', 'post_max_size resisted ini_set()');
}
if (!empty($overrideResults['open_basedir']['changed'])) {
add_result('FAIL', 'open_basedir can be changed via ini_set()', json_encode($overrideResults['open_basedir']));
} else {
add_result('PASS', 'open_basedir resisted ini_set()');
}
$dangerousAvailable = [];
foreach (['exec','shell_exec','system','passthru','proc_open','popen'] as $fn) {
if (function_exists($fn) && !str_contains($disableFunctions, $fn)) {
$dangerousAvailable[] = $fn;
}
}
if ($dangerousAvailable) {
add_result('FAIL', 'Command execution functions are available', implode(', ', $dangerousAvailable));
} else {
add_result('PASS', 'Command execution functions are blocked');
}
if (extension_loaded('pcntl')) {
add_result('FAIL', 'pcntl extension is loaded', 'Not recommended for shared hosting web SAPI');
} else {
add_result('PASS', 'pcntl extension is not loaded');
}
if ($userIni === '' || strtolower($userIni) === 'none') {
add_result('PASS', '.user.ini appears disabled');
} else {
add_result('WARN', '.user.ini appears enabled', $userIni);
}
if ($allowUrlInclude === '' || $allowUrlInclude === '0') {
add_result('PASS', 'allow_url_include is off');
} else {
add_result('FAIL', 'allow_url_include is on');
}
if (is_link($symlinkTarget)) {
add_result('WARN', 'Symlink creation works inside allowed path', $symlinkTarget);
} else {
add_result('PASS', 'Symlink creation did not work');
}
if (file_exists($hardlinkTarget)) {
add_result('WARN', 'Hardlink creation works inside allowed path', $hardlinkTarget);
} else {
add_result('PASS', 'Hardlink creation did not work');
}
$localhostSensitiveOpen = [];
foreach (['127.0.0.1:25','127.0.0.1:3306','127.0.0.1:6379','127.0.0.1:7080'] as $k) {
if (!empty($netResults[$k]['connected'])) {
$localhostSensitiveOpen[] = $k;
}
}
if ($localhostSensitiveOpen) {
add_result('WARN', 'Sensitive localhost TCP ports reachable', implode(', ', $localhostSensitiveOpen));
} else {
add_result('PASS', 'Sensitive localhost TCP ports not reachable');
}
$reachableUnix = [];
foreach ($unixResults as $sock => $res) {
if (!empty($res['connected'])) {
$reachableUnix[] = $sock;
}
}
if ($reachableUnix) {
add_result('WARN', 'Sensitive UNIX sockets reachable', implode(', ', $reachableUnix));
} else {
add_result('PASS', 'Sensitive UNIX sockets not reachable');
}
section('Score');
line('PASS', $SCORE['PASS']);
line('WARN', $SCORE['WARN']);
line('FAIL', $SCORE['FAIL']);
section('Findings');
foreach ($FINDINGS as [$level, $title, $detail]) {
echo '[' . $level . '] ' . $title;
if ($detail !== '') {
echo ' :: ' . $detail;
}
echo PHP_EOL;
}
section('Cleanup');
$cleanupFiles = [
$renameTo,
$copyToSession,
$src,
$symlinkTarget,
$hardlinkTarget,
$includeFile,
$userIniFile,
];
foreach ($cleanupFiles as $f) {
if (is_link($f) || file_exists($f)) {
@unlink($f);
}
}
@rmdir($baseTmp);
echo PHP_EOL . "Done." . PHP_EOL;
@@ -0,0 +1,5 @@
<?php
if (is_readable('/var/www/shared/mu-plugins/load.php')) {
require_once('/var/www/shared/mu-plugins/load.php');
}
@@ -0,0 +1,45 @@
<?php
/**
* Plugin Name: MU Test Plugin
* Description: MU Test plugin.
* Author: WEDOS
* Version: 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
add_action('admin_notices', function () {
if (!current_user_can('manage_options')) {
return;
}
echo '<div class="notice notice-success is-dismissible">';
echo '<p><strong>MU TEST OK</strong> — shared MU plugin.</p>';
echo '</div>';
});
add_action('admin_bar_menu', function ($wp_admin_bar) {
if (!current_user_can('manage_options')) {
return;
}
$wp_admin_bar->add_node([
'id' => 'mu-test-ok',
'title' => 'MU TEST OK',
'href' => admin_url('plugins.php?plugin_status=mustuse'),
'meta' => [
'title' => 'MU plugin',
],
]);
}, 100);
add_action('wp_footer', function () {
if (!current_user_can('manage_options')) {
return;
}
echo '<div style="position:fixed;right:16px;bottom:16px;z-index:99999;padding:10px 14px;background:#16a34a;color:#fff;border-radius:8px;font:14px/1.4 sans-serif;box-shadow:0 4px 16px rgba(0,0,0,.2);">MU TEST OK</div>';
});
@@ -0,0 +1,7 @@
<?php
if (!defined('SODEW_SMTP_ENABLE') || SODEW_SMTP_ENABLE === true) {
if (is_readable(__DIR__ . '/sodew-smtp.php')) {
require(__DIR__ . '/sodew-smtp.php');
}
}
@@ -0,0 +1,46 @@
<?php
/**
* @author Maksym Krugol <maksym.krugol@wedos.org>
* @copyright SODEW, s.r.o.
*
* @wordpress-plugin
* Plugin Name: SODEW SMTP config
* Plugin URI: https://sodew.ai
* Description: SMTP config
* Author: SODEW
* Author URI: https://sodew.ai
* Version: 1.1
*/
defined('ABSPATH') || exit;
add_action('phpmailer_init', function ($phpmailer) {
$domain = wp_parse_url(home_url(), PHP_URL_HOST);
$fromName = defined('SODEW_SMTP_FROM_NAME') ? SODEW_SMTP_FROM_NAME : 'WordPress';
$replyTo = defined('SODEW_SMTP_REPLY_TO') ? SODEW_SMTP_REPLY_TO : "wordpress@$domain";
$replyToName = defined('SODEW_SMTP_REPLY_TO_NAME') ? SODEW_SMTP_REPLY_TO_NAME : $fromName;
$phpmailer->isSMTP();
$phpmailer->XMailer = 'sodewMailer 1.1';
$phpmailer->Host = 'postfix';
$phpmailer->Port = 587;
$phpmailer->SMTPAuth = true;
$phpmailer->SMTPSecure = 'tls';
$phpmailer->SMTPAutoTLS = true;
$phpmailer->SMTPOptions = [
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
'peer_name' => SODEW_SMTP_HOST,
'allow_self_signed' => true,
],
];
$phpmailer->Username = SODEW_SMTP_USER;
$phpmailer->Password = SODEW_SMTP_PASS;
$phpmailer->setFrom(SODEW_SMTP_POSTMASTER, $fromName, false);
$phpmailer->Sender = SODEW_SMTP_POSTMASTER;
$phpmailer->clearReplyTos();
$phpmailer->addReplyTo($replyTo, $replyToName);
});