From 9948a1e9ac41566f7d9670f0d7a91d9b8bbab5dd Mon Sep 17 00:00:00 2001 From: James Keasley Date: Wed, 18 Oct 2023 15:20:49 +0100 Subject: [PATCH] Add the ability to allow unauthenticated access from internal referrers This commit adds the Referrer Allow list option, which can be used to whitelist traffic arriving from certain referrers (internal only) which is intended to allow plugins like Nelio AB Testing to be usable on sites which use this plugin to control access to the site. internal referrer urls can contain query strings, but the input config should omit the site url, as this is set inside the plugin, to prevent external referrers from being configured. The new functionality also only accepts as valid referrer headers where the configured allowed referrer string appears at the start of the referrer header, to prevent whitelisted items being passed as parameters of a referrer to circumvent the access controls. loading an allow listed referrer url directly in the browser while unauthenticated does not allow the user to bypass the access control as when the plugin performs redirection it does not, itself, send the HTTP_REFERER header. --- redirect.php | 35 +++++++++++++++++++++++++++++++++++ settings.php | 20 +++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/redirect.php b/redirect.php index c2038a6..c6c6537 100644 --- a/redirect.php +++ b/redirect.php @@ -83,6 +83,34 @@ function dxw_members_only_current_ip_in_whitelist() return false; } +function dxw_members_only_referrer_in_allow_list() +{ + $referrer_list = explode("\n", get_option('dxw_members_only_referrer_allow_list')); + /* + * If there is no referrer header, or if we have no configured referrers to + * whitelist we can stop here. + */ + if (isset($_SERVER['HTTP_REFERER']) && count($referrer_list) > 0) { + foreach ($referrer_list as $referrer) { + /* + * Add the site url to the referrer string to ensure that external + * referrers can't be used here. + */ + $whitelisted_referrer = get_site_url().$referrer; + $referrer_check = strpos($_SERVER['HTTP_REFERER'],$whitelisted_referrer); + /* + * Check that there is a match, and that match is at the start of the referrer string. + * This is to ensure that the referrer being whitelisted can't be fooled by having + * a whitelisted referrer passed in as a parameter on the referrer string. + */ + if ($referrer_check !==false && $referrer_check == 0){ + return true; + } + } + } + return false; +} + add_action('init', function () { // Fix for wp-cli if (defined('WP_CLI_ROOT')) { @@ -122,6 +150,13 @@ function dxw_members_only_current_ip_in_whitelist() return; } + // Referrer whitelist + if (dxw_members_only_referrer_in_allow_list()) { + header('Cache-Control: private, max-age=' . $max_age); + dxw_members_only_serve_uploads(); + return; + } + // List $hit = false; $list = explode("\n", get_option('dxw_members_only_list_content')); diff --git a/settings.php b/settings.php index c157c1d..6b4a142 100644 --- a/settings.php +++ b/settings.php @@ -5,7 +5,7 @@ function dxw_members_only_metasettings() { $ms = new dmometasettings(__FILE__, 'dxw_members_only'); - $ms->add_settings(__('dxw Members Only', 'dxwmembersonly'), ['list_type', 'list_content', 'ip_whitelist', 'redirect', 'redirect_root', 'upload_default', 'max_age'], 'dxw_members_only_options_page'); + $ms->add_settings(__('dxw Members Only', 'dxwmembersonly'), ['list_type', 'list_content', 'ip_whitelist', 'referrer_allow_list', 'redirect', 'redirect_root', 'upload_default', 'max_age'], 'dxw_members_only_options_page'); } /** @@ -53,6 +53,24 @@ function dxw_members_only_options_page() +

+

+

+ + + + + + + + +
+ +
+ +
+ +

%return_path% will be converted to the URL that was originally visited. i.e. /wp-login.php?redirect_to=http://example.com/private-page', 'dxwmembersonly') ?>