Skip to content

Commit

Permalink
Add the ability to allow unauthenticated access from internal referrers
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jkeasley committed Oct 19, 2023
1 parent e7f5ef2 commit 9948a1e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 1 deletion.
35 changes: 35 additions & 0 deletions redirect.php
Original file line number Diff line number Diff line change
Expand Up @@ -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')) {
Expand Down Expand Up @@ -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'));
Expand Down
20 changes: 19 additions & 1 deletion settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -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');
}

/**
Expand Down Expand Up @@ -53,6 +53,24 @@ function dxw_members_only_options_page()

</table>

<h3><?php _e('Referrer Allow list') ?></h3>
<p><?php _e('Enter a list of internal referrers to whitelist.', 'dxwmembersonly') ?></p>
<p><?php _e('This is for enabling certain plugins such as Nelio AB to function correctly, do not use unless required', 'dxwmembersonly') ?></p>

<table class="form-table">

<tr valign="top">
<th scope="row"><label for="dxw_members_only_referrer_allow_list"><?php _e('List of referrers', 'dxwmembersonly') ?></label></th>
<td>
<textarea cols="30" rows="5" name="dxw_members_only_referrer_allow_list" id="dxw_members_only_referrer_allow_list" class="large-text code"><?php echo esc_html(get_option('dxw_members_only_referrer_allow_list')) ?></textarea>
<br>
<span class="description"><?php _e('One address per line, do not include the domain (eg /admin.php?page=test)', 'dxwmembersonly') ?></span>
</td>
</tr>

</table>
<?php echo get_option('dxw_members_only_referrer_whitelist'); ?>

<h3><?php _e('Redirection', 'dxwmembersonly') ?></h3>
<p><?php _e('In both the following options, <code>%return_path%</code> will be converted to the URL that was originally visited. i.e. <code>/wp-login.php?redirect_to=http://example.com/private-page</code>', 'dxwmembersonly') ?></p>

Expand Down

0 comments on commit 9948a1e

Please sign in to comment.