ROOTPLOIT
Server: LiteSpeed
System: Linux in-mum-web1878.main-hosting.eu 5.14.0-570.21.1.el9_6.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Jun 11 07:22:35 EDT 2025 x86_64
User: u435929562 (435929562)
PHP: 7.4.33
Disabled: system, exec, shell_exec, passthru, mysql_list_dbs, ini_alter, dl, symlink, link, chgrp, leak, popen, apache_child_terminate, virtual, mb_send_mail
Upload Files
File: //home/u435929562/domains/tec-edu.in/public_html/wp-content/plugins/webarx/includes/hardening.php
<?php

// Do not allow the file to be called directly.
if (!defined('ABSPATH')) {
	exit;
}

/**
 * This class is used to provide several hardening options.
 */
class W_Hardening extends W_Core
{
    /**
     * Add the actions required for the hardening of the site.
	 * 
	 * @param Webarx $core
	 * @return void
	 */
	public function __construct($core)
	{
		parent::__construct($core);

        // The hardening features can only be used on an activated license.
        if (!$this->license_is_active()) {
            return;
		}
		
		// Disallowed modification of the theme files?
		if(!defined('DISALLOW_FILE_EDIT') && $this->get_option('webarx_pluginedit', true)){
			define('DISALLOW_FILE_EDIT', 1);
		}

		// Set security headers
        add_filter('wp_headers', array($this, 'set_security_headers'), 10, 1);

		// When country blocking is set.
		if($this->get_option('webarx_geo_block_enabled', false) && !empty($this->get_option('webarx_geo_block_countries', array()))){
			add_action('init', array($this, 'geo_block_check'), 10);
		}

		// Apply comment captcha?
        if ($this->get_option('webarx_captcha_on_comments', 0) && !is_user_logged_in()) {
			add_action('comment_form_after_fields', array($this, 'captcha_display'));
			add_filter('preprocess_comment', array($this, 'verify_recaptcha'));
		}
		
		// Disable the application passwords feature?
        if ($this->get_option('webarx_application_passwords_disabled', false) == true) {
            add_filter('wp_is_application_passwords_available', '__return_false');
		}

		// Block unauthorized XML-RPC requests?
        if ($this->get_option('webarx_xmlrpc_is_disabled', false) == true) {
            add_filter('xmlrpc_enabled', '__return_false');
		}

		// Block unauthorized wp-json requests?
		if ($this->get_option('webarx_json_is_disabled', false)) {
			add_filter('rest_authentication_errors', array($this, 'disable_wpjson'));
		}

		// Delete the readme file?
		if (get_site_option('webarx_rm_readme', false) == true) {
			$this->delete_readme();
		}

		// Block WPScan user agent?
		if ($this->get_option('webarx_basicscanblock')) {
			$this->detect_user_agent();
		}

		// Prevent user enumeration?
		if ($this->get_option('webarx_userenum')) {
		    $this->stop_user_enum();
		}

		// Attempt to hide the WordPress version?
		if ($this->get_option('webarx_hidewpversion')) {
			remove_action('wp_head', 'wp_generator');
			add_filter('the_generator', array($this, 'remove_generator'));
		}

		// Block email registration patterns?
		if ($this->get_option('webarx_register_email_blacklist', '') != '') {
			add_filter('registration_errors', array($this, 'check_email_pattern'), 1, 3);
			add_filter('wpmu_validate_user_signup', array($this, 'check_email_pattern_wpmu'), 1, 1);
		}

		// Auto update software?
		$update = get_site_option('webarx_auto_update', array());
		if (is_array($update)) {
			foreach ($update as $type) {
				if($type != 'vulnerable'){
					add_filter('auto_update_' . $type, '__return_true');
				}
			}
		}

		// Auto update plugins.
		add_action('webarx_update_plugins', array($this, 'update_vulnerable_plugins'));
	}

	/**
	 * Perform updates if the software upload call returns vulnerabilities.
	 * This is only executed when auto updates are enabled for vulnerable plugins.
	 * 
	 * @param array $plugins
	 * @return void
	 */
	public function update_vulnerable_plugins()
	{
		// Is the auto update setting for vulnerable plugins enabled?
		$update = get_site_option('webarx_auto_update', array());
		if (!is_array($update) || !in_array('vulnerable', $update)) {
			return;
		}

		// Do we even have any vulnerable plugins to auto update?
		$plugins = get_site_option('webarx_vulnerable_plugins', array());
		if (!is_array($plugins) || count($plugins) == 0) {
			return;
		}

		// Might not be necessary, but should prevent any hanging issues.
		@set_time_limit(180);
		
        // Require some files we need to execute the upgrade.
        @include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        if (file_exists(ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php')) {
            @include_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
        }

        @include_once ABSPATH . 'wp-admin/includes/plugin.php';
        @include_once ABSPATH . 'wp-admin/includes/misc.php';
        @include_once ABSPATH . 'wp-admin/includes/file.php';
        @wp_update_plugins();
        $all_plugins = get_plugins();

        // New array with all available plugins and the ones we want to upgrade.
        $upgrade = array();
        foreach ($all_plugins as $path => $data) {
            if (in_array($path, $plugins)) {
                array_push($upgrade, $path);
            }
		}

        // Upgrade the plugins.
        $upgrader = new Plugin_Upgrader(new Automatic_Upgrader_Skin());
		$upgrader->bulk_upgrade($upgrade);

		// Reset the option that holds the vulnerable plugins.
		update_site_option('webarx_vulnerable_plugins', array());

		// Resend the sofware data to the API.
		do_action('webarx_send_software_data');
	}

	/**
	 * Determine the country of the user and if we should block the user.
	 * 
	 * @return void
	 */
	public function geo_block_check()
	{
		$countries = $this->get_option('webarx_geo_block_countries', array());
		$ip = $this->get_ip();

		// Don't block Patchstack.
		if(in_array($ip, $this->plugin->ips)){
			return;
		}

		// Load the required libraries.
		try {
			require_once __DIR__ . '/../lib/geoip2-php/autoload.php';
			$reader = new GeoIp2\Database\Reader(__DIR__ . '/../lib/GeoLite2-Country.mmdb');
			$record = $reader->country($ip);

			// Determine if we want to do an inverse check or not.
			$isMatch = in_array($record->country->isoCode, $countries);
			$isMatch = $this->get_option('webarx_geo_block_inverse', false) ? !$isMatch : $isMatch;

			// Check if there's a match.
			if ($isMatch) {
				$this->plugin->firewall_base->display_error_page(22);
			}			
		} catch (\Exception $e) { }
	}

	/**
	 * Prevent unauthorized users from accessing wp-json.
	 * 
	 * @return void|WP_Error
	 */
	public function disable_wpjson()
	{
		if (!is_user_logged_in()) {
			$msg = apply_filters('disable_wp_rest_api_error', __('The WP REST API cannot be accessed by unauthorized users.', 'disable-wp-rest-api'));
			return new WP_Error('rest_authorization_required', $msg, array('status' => rest_authorization_required_code()));
		}
	}

    /**
     * Set security headers if the option is enabled.
	 * 
	 * @param array $headers
	 * @return void|array
     */
    public function set_security_headers($headers)
    {
        if (get_site_option('webarx_add_security_headers')) {
            $headers['Referrer-Policy'] = 'strict-origin-when-cross-origin';
            $headers['X-Frame-Options'] = 'SAMEORIGIN';
            $headers['X-XSS-Protection'] = '1; mode=block';
            $headers['X-Content-Type-Options'] = 'nosniff';
            $headers['X-Powered-By'] = null;
            $headers['Server'] = null;
            $headers['Strict-Transport-Security'] = 'max-age=31536000';
		}
		
		return $headers;
    }

	/**
	 * Determine if the reCAPTCHA is valid upon comment submission.
	 * 
	 * @param array $comment_data
	 * @return void|array
	 */
	public function verify_recaptcha($comment_data)
	{
        $result = $this->captcha_check();
        if (!$result['response'] && ($result['reason'] === 'VERIFICATION_FAILED' || $result['reason'] === 'RECAPTCHA_EMPTY_RESPONSE')) {
            wp_clear_auth_cookie();
			wp_die('reCaptcha was not solved or response was empty', 'Error');
        }

        return $comment_data;
    }

	/**
	 * Add the captcha to the comments form.
	 * 
	 * @return void
	 */
	public function captcha_display()
	{
		if ($this->get_option('webarx_captcha_type') == 'v2') {
			$site_key = trim($this->get_option('webarx_captcha_public_key'));
			require_once dirname(__FILE__) . '/views/captcha_v2.php';
        } else {
			$site_key = trim($this->get_option('webarx_captcha_public_key_v3'));
			require_once dirname(__FILE__) . '/views/captcha_invisible.php';
		}
    }

	/**
	 * Check if the submitted reCAPTCHA is valid.
	 *
	 * @return array
	 */
	public function captcha_check()
	{
        if ($this->get_option('webarx_captcha_type') == 'v2') {
            $secret_key = trim($this->get_option('webarx_captcha_private_key'));
		    $site_key = trim($this->get_option('webarx_captcha_public_key'));
        } else {
            $secret_key = trim($this->get_option('webarx_captcha_private_key_v3'));
            $site_key = trim($this->get_option('webarx_captcha_public_key_v3'));
        }

		if (!$secret_key || !$site_key) {
			return array('response' => false, 'reason' => 'ERROR_NO_KEYS');
		}

		if (!isset($_POST['g-recaptcha-response']) || empty($_POST['g-recaptcha-response'])) {
			return array('response' => false, 'reason' => 'RECAPTCHA_EMPTY_RESPONSE');
		}

		$response = $this->plugin->hardening->get_captcha_response($secret_key);
		if (isset($response['success']) && !empty($response['success'])) {
			return array('response' => true, 'reason' => '');
		}

		return array('response' => false, 'reason' => 'VERIFICATION_FAILED');
	}

	/**
	 * Query Google for reAPTCHA validation and response.
	 *
	 * @param string $privatekey
	 * @return array
	 */
	public function get_captcha_response($privatekey)
	{
		$args = array(
			'body' => array(
				'secret' => $privatekey,
				'response' => $_POST['g-recaptcha-response']
			),
			'sslverify' => false
		);
		$resp = wp_remote_post('https://www.google.com/recaptcha/api/siteverify', $args);
		return json_decode(wp_remote_retrieve_body($resp), true);
	}

	/**
	 * Delete the readme.html file.
	 * 
	 * @return void
	 */
	public function delete_readme()
	{
		if (!file_exists(ABSPATH . 'readme.html')) {
			return;
		}

		require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php');
		require_once(ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php');
		$fs = new WP_Filesystem_Direct('');
		$fs->delete(ABSPATH . 'readme.html');
	}

    /**
     * Disable user enumeration with ?author=
     *
	 * @return void
     */
	public function stop_user_enum()
    {
		$uri_parts = explode('?', $_SERVER['REQUEST_URI'], 2);
		
        if (isset($_GET['author']) && $uri_parts[0] == '/') {
            $user = get_userdata($_GET['author']);
            if ($user) {
                die(wp_redirect(get_site_url()));
            }
        }
    }

	/**
	 * Block WPScan user agent.
	 * 
	 * @return void
	 */
	public function detect_user_agent()
	{
		if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('/WPScan/i', $_SERVER['HTTP_USER_AGENT'])) {
			exit;
		}
	}

	/**
	 * Hide the WordPress generator version in response.
	 * 
	 * @return string
	 */
	public function remove_generator()
	{
		return '';
	}

	/**
	 * Determine if the email address of a new registration matches the defined patterns.
	 * This filter is called on regular sites.
	 * 
	 * @param object $errors
	 * @param string $sanitized_user_login
	 * @param string $user_email
	 * @return object
	 */
	public function check_email_pattern($errors, $sanitized_user_login, $user_email)
	{
		$patterns = explode(',', $this->get_option('webarx_register_email_blacklist'));
		foreach ($patterns as $pattern) {
			if (stripos($user_email, $pattern) !== false) {
				$errors->add('user_email', __('An invalid email address has been supplied.', 'webarx'));
			}
		}

		return $errors;
	}

	/**
	 * Determine if the email address of a new registration matches the defined patterns.
	 * This filter is called on network sites.
	 * 
	 * @param array $result
	 * @return array
	 */
	public function check_email_pattern_wpmu($result)
	{
		if (isset($result['user_email'])) {
			$patterns = explode(',', $this->get_option('webarx_register_email_blacklist'));
			foreach ($patterns as $pattern) {
				if (stripos($result['user_email'], $pattern) !== false) {
					$result['errors']->add('user_email', __('An invalid email address has been supplied.', 'webarx'));
				}
			}
		}

		return $result;
	}
}