diff --git a/ajax/adblock/update_blocklist.php b/ajax/adblock/update_blocklist.php index 46f7798e..f21ed4cd 100644 --- a/ajax/adblock/update_blocklist.php +++ b/ajax/adblock/update_blocklist.php @@ -1,9 +1,8 @@ $path .'/hostapd.conf', "tmp" => "/tmp/hostapddata", "dest" => RASPI_HOSTAPD_CONFIG), - array("src" => $path .'/dhcpcd.conf', "tmp" => "/tmp/dhcpddata", "dest" => RASPI_DHCPCD_CONFIG), - array("src" => $path .'/090_wlan0.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'wlan0.conf'), - array("src" => $path .'/090_raspap.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'raspap.conf'), - ); +$return = 0; +$path = "../../config"; +$configs = array( + array("src" => $path .'/hostapd.conf', "tmp" => "/tmp/hostapddata", "dest" => RASPI_HOSTAPD_CONFIG), + array("src" => $path .'/dhcpcd.conf', "tmp" => "/tmp/dhcpddata", "dest" => RASPI_DHCPCD_CONFIG), + array("src" => $path .'/090_wlan0.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'wlan0.conf'), + array("src" => $path .'/090_raspap.conf', "tmp" => "/tmp/dnsmasqdata", "dest" => RASPI_DNSMASQ_PREFIX.'raspap.conf'), +); - foreach ($configs as $config) { - try { - $tmp = file_get_contents($config["src"]); - file_put_contents($config["tmp"], $tmp); - system("sudo cp ".$config["tmp"]. " ".$config["dest"]); - } catch (Exception $e) { - $return = $e->getCode(); - } +foreach ($configs as $config) { + try { + $tmp = file_get_contents($config["src"]); + file_put_contents($config["tmp"], $tmp); + system("sudo cp ".$config["tmp"]. " ".$config["dest"]); + } catch (Exception $e) { + $return = $e->getCode(); } - $jsonData = ['return'=>$return]; - echo json_encode($jsonData); - -} else { - handleInvalidCSRFToken(); } +$jsonData = ['return'=>$return]; +echo json_encode($jsonData); + diff --git a/ajax/networking/get_all_interfaces.php b/ajax/networking/get_all_interfaces.php index b88e987b..0fb33fe1 100644 --- a/ajax/networking/get_all_interfaces.php +++ b/ajax/networking/get_all_interfaces.php @@ -1,9 +1,8 @@ getToken(); + } + + public static function verify(): bool + { + $token = $_POST['csrf_token']; + return self::instance()->csrfValidateRequest() && + self::instance()->CSRFValidate($_POST['csrf_token'] ?? ''); + } + + public static function metaTag(): string + { + return self::instance()->CSRFMetaTag(); + } + + public static function hiddenField(): string + { + return self::instance()->CSRFTokenFieldTag(); + } + + public static function handleInvalidToken(): void + { + self::instance()->handleInvalidCSRFToken(); + } + + /** + * Validates a CSRF Request + * + * @return bool + */ + public static function validateRequest(): bool + { + return self::instance()->csrfValidateRequest(); + } +} + +if (\RaspAP\Tokens\CSRF::validateRequest()) { + if (!\RaspAP\Tokens\CSRF::verify()) { + error_log("CSRF verification failed. Token: " . ($_POST['csrf_token'] ?? 'not provided')); + \RaspAP\Tokens\CSRF::handleInvalidToken(); + } +} + diff --git a/includes/autoload.php b/includes/autoload.php index d39bd0c9..87177471 100755 --- a/includes/autoload.php +++ b/includes/autoload.php @@ -9,31 +9,13 @@ */ spl_autoload_register(function ($class) { - // project-specific namespace prefix - $prefix = ''; + // base directory where all class files are stored + $base_dir = __DIR__ . '/../src/'; - // base directory for the namespace prefix - $base_dir = 'src/'; + // convert the fully qualified class name into a file path + $file = $base_dir . str_replace('\\', '/', $class) . '.php'; - // normalize the base directory with a trailing separator - $base_dir = rtrim($base_dir, DIRECTORY_SEPARATOR) . '/'; - - // does the class use the namespace prefix? - $len = strlen($prefix); - if (strncmp($prefix, $class, $len) !== 0) { - // no, move to the next registered autoloader - return; - } - - // get the relative class name - $relative_class = substr($class, $len); - - // replace the namespace prefix with the base directory, replace namespace - // separators with directory separators in the relative class name, append - // with .php - $file = $base_dir . str_replace('\\', '/', $relative_class) . '.php'; - - // if the file exists, require it + // require the file if it exists if (file_exists($file)) { require $file; } diff --git a/includes/csrf.php b/includes/csrf.php deleted file mode 100755 index 4e098e5b..00000000 --- a/includes/csrf.php +++ /dev/null @@ -1,7 +0,0 @@ -getVpnManged($vpn); - } + $vpnManaged = $vpn ? $dashboard->getVpnManaged($vpn) : null; $firewallManaged = $firewallStatus = ""; $firewallInstalled = array_filter($plugins, fn($p) => str_ends_with($p, 'Firewall')) ? true : false; if (!$firewallInstalled) { diff --git a/includes/exceptions.php b/includes/exceptions.php deleted file mode 100755 index c52c04ed..00000000 --- a/includes/exceptions.php +++ /dev/null @@ -1,6 +0,0 @@ - - diff --git a/includes/functions.php b/includes/functions.php index 54b4939c..6ef53ea4 100755 --- a/includes/functions.php +++ b/includes/functions.php @@ -306,82 +306,6 @@ function filter_comments($var) return $var[0] != '#'; } -/** - * Saves a CSRF token in the session - */ -function ensureCSRFSessionToken() -{ - if (empty($_SESSION['csrf_token'])) { - $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); - } -} - -/** - * Add CSRF Token to form - */ -function CSRFTokenFieldTag() -{ - $token = htmlspecialchars($_SESSION['csrf_token']); - return ''; -} - -/** - * Retuns a CSRF meta tag (for use with xhr, for example) - */ -function CSRFMetaTag() -{ - $token = htmlspecialchars($_SESSION['csrf_token']); - return ''; -} - -/** - * Validate CSRF Token - */ -function CSRFValidate() -{ - if (empty($_SESSION['csrf_token']) || !is_string($_SESSION['csrf_token'])) { - error_log('Session expired or CSRF token is missing.'); - header('Location: /login'); - exit; - } - - $post_token = $_POST['csrf_token'] ?? null; - $header_token = $_SERVER['HTTP_X_CSRF_TOKEN'] ?? null; - - if (empty($post_token) && is_null($header_token)) { - error_log('CSRF token missing in the request'); - return false; - } - $request_token = $post_token ?: $header_token; - - if (hash_equals($_SESSION['csrf_token'], $request_token)) { - return true; - } else { - error_log('CSRF token mismatch'); - return false; - } -} - -/** - * Should the request be CSRF-validated? - */ -function csrfValidateRequest() -{ - $request_method = strtolower($_SERVER['REQUEST_METHOD']); - return in_array($request_method, [ "post", "put", "patch", "delete" ]); -} - -/** - * Handle invalid CSRF - */ -function handleInvalidCSRFToken() -{ - header('HTTP/1.1 500 Internal Server Error'); - header('Content-Type: text/plain'); - echo 'Invalid CSRF token'; - exit; -} - /** * Test whether array is associative */ diff --git a/index.php b/index.php index 26652630..a677a79f 100755 --- a/index.php +++ b/index.php @@ -23,13 +23,12 @@ * as you leave these references intact in the header comments of your source files. */ -require 'includes/session.php'; -require 'includes/csrf.php'; -ensureCSRFSessionToken(); - -require_once 'includes/exceptions.php'; require_once 'includes/config.php'; require_once 'includes/autoload.php'; +$handler = new RaspAP\Exceptions\ExceptionHandler; + +require_once 'includes/CSRF.php'; +require_once 'includes/session.php'; require_once 'includes/defaults.php'; require_once 'includes/locale.php'; require_once 'includes/functions.php'; @@ -59,7 +58,7 @@ initializeApp(); >
- + diff --git a/src/RaspAP/Auth/HTTPAuth.php b/src/RaspAP/Auth/HTTPAuth.php index a28f9212..d5fcf215 100755 --- a/src/RaspAP/Auth/HTTPAuth.php +++ b/src/RaspAP/Auth/HTTPAuth.php @@ -79,6 +79,7 @@ class HTTPAuth */ public function logout(): void { + session_regenerate_id(true); // generate a new session id session_unset(); // unset all session variables session_destroy(); // destroy the session $redirectUrl = $_SERVER['REQUEST_URI']; diff --git a/src/RaspAP/Tokens/CSRFTokenizer.php b/src/RaspAP/Tokens/CSRFTokenizer.php new file mode 100644 index 00000000..d3925f45 --- /dev/null +++ b/src/RaspAP/Tokens/CSRFTokenizer.php @@ -0,0 +1,136 @@ + + * @author Martin Glaß