POC Safe eval of .page files

This commit is contained in:
Squidly271
2025-10-03 23:43:59 -04:00
parent 95bc8968f0
commit 8662f6f9e7
5 changed files with 79 additions and 12 deletions

27
emhttp/plugins/dynamix/include/DefaultPageLayout.php Normal file → Executable file
View File

@@ -78,6 +78,7 @@ if (count($pages)) {
@unlink($nchan_pid);
}
}
?>
<!DOCTYPE html>
<html <?= $display['rtl'] ?>lang="<?= strtok($locale, '_') ?: 'en' ?>" class="<?= $themeHelper->getThemeHtmlClass() ?>">
@@ -132,22 +133,30 @@ if (count($pages)) {
<?php require_once "$docroot/webGui/include/DefaultPageLayout/HeadInlineJS.php"; ?>
<?php
foreach ($buttonPages as $button) {
annotate($button['file']);
includePageStylesheets($button);
eval('?>' . parse_text($button['text']));
}
foreach ($buttonPages as $button) {
annotate($button['file']);
includePageStylesheets($button);
$evalContent = '?>' . parse_text($button['text']);
$evalFile = $button['file'];
if ( filter_var($button['Eval']??false, FILTER_VALIDATE_BOOLEAN) ) {
eval($evalContent);
} else {
include "$docroot/webGui/include/DefaultPageLayout/evalContent.php";
}
}
foreach ($pages as $page) {
annotate($page['file']);
includePageStylesheets($page);
}
foreach ($pages as $page) {
annotate($page['file']);
includePageStylesheets($page);
}
?>
<?php include "$docroot/plugins/dynamix.my.servers/include/myservers1.php" ?>
</head>
<body>
<unraid-modals></unraid-modals>
<?php include "$docroot/webGui/include/DefaultPageLayout/MiscElementsTop.php"; ?>
<?php include "$docroot/webGui/include/DefaultPageLayout/Header.php"; ?>
<?php include "$docroot/webGui/include/DefaultPageLayout/Navigation/Main.php"; ?>

View File

@@ -43,7 +43,13 @@
if (isset($page['text'])) {
$skipIndexIncrement = true;
annotate($page['file']);
eval('?>'.generateContent($page));
$evalContent = '?>'.generateContent($page);
$evalFile = $page['file'];
if ( filter_var($page['Eval']??false, FILTER_VALIDATE_BOOLEAN) ) {
eval($evalContent);
} else {
include "$docroot/webGui/include/DefaultPageLayout/evalContent.php";
}
}
continue;
}
@@ -60,7 +66,15 @@
>
<?= generatePanels($page, $path, $defaultIcon, $docroot) ?>
<? eval('?>'.generateContent($page)); ?>
<?
$evalContent = '?>'.generateContent($page);
$evalFile = $page['file'];
if ( filter_var($page['Eval']??false, FILTER_VALIDATE_BOOLEAN) ) {
eval($evalContent);
} else {
include "$docroot/webGui/include/DefaultPageLayout/evalContent.php";
}
?>
</section>
<?
if ($skipIndexIncrement) {

View File

@@ -19,7 +19,15 @@
<?= generatePanels($page, $path, $defaultIcon, $docroot, true) ?>
<? eval('?>'.generateContent($page)); ?>
<?
$evalContent = '?>'.generateContent($page);
$evalFile = $page['file'];
if ( filter_var($page['Eval']??false, FILTER_VALIDATE_BOOLEAN) ) {
eval($evalContent);
} else {
include "$docroot/webGui/include/DefaultPageLayout/evalContent.php";
}
?>
<? endforeach; ?>
</div>
</div>

View File

@@ -0,0 +1,35 @@
<?php
// This evaluates the contents of PHP code. Has to be "included" because the code is evaluated in the context of the calling page.
// $evalContent is the PHP code to evaluate.
// $evalFile is the file that the code is being evaluated in
// If an error occurs, a banner warning (disappearing in 10 seconds) is added to the page.
// The PHP error logged will also include the path of the .page file for easier debugging
ob_start();
try {
set_error_handler(function($severity, $message, $file, $line) {
throw new ErrorException($message, 0, $severity, $file, $line);
});
eval($evalContent);
restore_error_handler();
ob_end_flush();
} catch (Throwable $e) {
restore_error_handler();
error_log("Error evaluating content in $evalFile: " . $e->getMessage() . "\nStack trace:\n" . $e->getTraceAsString());
ob_clean();
echo "
<script>
$(function() {
try {
console.log('Fatal error in ".htmlspecialchars($evalFile)." Code not executed.');
let phpErrorBanner = addBannerWarning('Fatal error in ".htmlspecialchars($evalFile)." Code not executed.',true,true);
setTimeout(function() {
removeBannerWarning(phpErrorBanner);
}, 10000);
} catch (e) {
console.error('Failed to add banner warning: ' + e);
}
});
</script>";
ob_end_flush();
}
?>