403Webshell
Server IP : 217.160.0.135  /  Your IP : 216.73.217.25
Web Server : Apache
System : Linux www 6.18.52-i1-ampere #1203 SMP Mon Sep 14 18:29:59 CEST 2026 aarch64
User : sws1074145052 ( 1074145052)
PHP Version : 8.3.32
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /home/www/public/wp-content/mu-plugins/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /home/www/public/wp-content//mu-plugins/000-ionos-wp-template-guard.php
<?php
/**
 * Plugin Name: IONOS WordPress Template Guard
 * Description: Temporary mitigation for CVE-2026-87902. Remove after updating WordPress and verifying the upstream fix.
 * Version: 1.0.1
 * Requires at least: 4.7
 * Requires PHP: 5.6
 * License: GPL-2.0-or-later
 *
 * Install this file directly in wp-content/mu-plugins/.
 * Uses PHP's already parsed fields; never reads php://input or uploaded files.
 * This is not a replacement for the WordPress core update and cannot intercept
 * arbitrary PHP include/require calls made directly by another plugin/theme.
 */

if (!defined('ABSPATH')) {
    exit;
}

final class IONOS_WP_Template_Guard_87902
{
    /** Register before ordinary plugins and themes load. */
    public static function register()
    {
        // MU-plugins load before wp_magic_quotes(). PHP has already decoded
        // query/form keys, parsed multipart fields, and applied its input limits.
        self::check_query_vars($_GET);
        self::check_query_vars($_POST);

        // Also inspect pagename derived from permalink rewrites or query filters.
        add_filter('request', array(__CLASS__, 'check_query_vars'), PHP_INT_MAX);

        // get_page_template() has already built its decoded and original names;
        // this filter runs before locate_template(), including on WordPress 4.7.
        add_filter('page_template_hierarchy', array(__CLASS__, 'check_candidates'), PHP_INT_MAX);

        // Check paths returned by page/template filters before normal inclusion.
        add_filter('page_template', array(__CLASS__, 'check_template_path'), PHP_INT_MAX);
        add_filter('template_include', array(__CLASS__, 'check_template_include'), PHP_INT_MAX);

        // Available since WordPress 6.1. On older versions the page-template
        // guards above still work, but direct load_template() calls lack this hook.
        add_action('wp_before_load_template', array(__CLASS__, 'check_template_path'), -PHP_INT_MAX, 1);
    }

    private static function block()
    {
        if (!headers_sent()) {
            status_header(403);
            nocache_headers();
            header('Content-Type: text/plain; charset=utf-8');
        }
        exit("Forbidden\n");
    }

    private static function has_traversal($path)
    {
        // Same traversal shape as the upstream fix, including backslashes and
        // components containing extra dots or trailing spaces.
        return 0 !== preg_match('~(?:^|/)\.\.[. ]*(?:/|$)~', wp_normalize_path($path));
    }

    private static function check_name($name)
    {
        if (!is_string($name) || strlen($name) > 4096 || false !== strpos($name, "\0")) {
            self::block();
        }
        if (0 !== validate_file($name) || self::has_traversal($name)) {
            self::block();
        }
    }

    public static function check_query_vars($vars)
    {
        if (!is_array($vars)) {
            self::block();
        }
        if (!array_key_exists('pagename', $vars)) {
            return $vars;
        }

        $name = $vars['pagename'];
        for ($depth = 0; $depth <= 4; ++$depth) {
            self::check_name($name);
            $decoded = urldecode($name);
            if ($decoded === $name) {
                return $vars;
            }
            if (4 === $depth) {
                self::block();
            }
            $name = $decoded;
        }

        return $vars;
    }

    public static function check_candidates($templates)
    {
        if (!is_array($templates)) {
            self::block();
        }
        foreach ($templates as $name) {
            // Inspect actual filesystem candidates; do not decode them again.
            self::check_name($name);
        }
        return $templates;
    }

    public static function check_template_include($path)
    {
        // WordPress accepts template wrappers implementing __toString(), as
        // used by Cherry Framework. Resolve once and return the checked string
        // so inclusion cannot trigger a second conversion with another result.
        if (is_object($path) && method_exists($path, '__toString')) {
            $path = (string) $path;
        }
        return self::check_template_path($path);
    }

    public static function check_template_path($path)
    {
        // WordPress filters may return an empty value to suppress inclusion.
        if (false === $path || null === $path || '' === $path) {
            return $path;
        }
        if (!is_string($path) || false !== strpos($path, "\0")) {
            self::block();
        }

        // Match the upstream traversal-specific restriction. Ordinary absolute
        // plugin templates and block-theme template-canvas.php remain supported.
        if (!self::has_traversal($path)) {
            return $path;
        }

        $resolved = realpath($path);
        if (false === $resolved) {
            self::block();
        }
        $resolved = wp_normalize_path($resolved);
        $stylesheet = get_stylesheet_directory();
        $template = get_template_directory();
        $roots = array($stylesheet, $template, ABSPATH . WPINC . '/theme-compat');

        // Preserve the nested-theme compatibility exceptions in the core fix.
        if (false !== strpos(get_stylesheet(), '/')) {
            $roots[] = dirname($stylesheet);
        }
        if (false !== strpos(get_template(), '/')) {
            $roots[] = dirname($template);
        }

        foreach ($roots as $root) {
            $root = realpath($root);
            if (false !== $root) {
                // The trailing slash prevents /theme-other matching /theme.
                $root = trailingslashit(wp_normalize_path($root));
                if (0 === strpos($resolved, $root)) {
                    return $path;
                }
            }
        }
        self::block();
    }
}

IONOS_WP_Template_Guard_87902::register();

Youez - 2016 - github.com/yon3zu
LinuXploit