feature-user-preferences: fiix potential xss vulnerabilities

This commit is contained in:
Starbeamrainbowlabs 2021-09-03 01:01:38 +01:00
parent 1f51bf31c6
commit 2d6bf1df70
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
3 changed files with 19 additions and 18 deletions

View File

@ -330,8 +330,8 @@ function slugify(string $text) : string {
* Hides an email address from bots. Returns a fragment of HTML that contains the mangled email address.
* @package core
* @param string $str The original email address
* @param string $display_text The display text for the resulting HTML - if null then the original email address is used.
* @return string The mangled email address.
* @param string $display_text The display text for the resulting HTML - if null then the original email address is used. Note that because it's base64 encoded and then textContent is used, one does not need to run either htmlentities() or rawurlencode() over this value as it's completely safe.
* @return string The mangled email address as a fragment of HTML.
*/
function hide_email(string $email, string $display_text = null) : string
{

View File

@ -5,7 +5,7 @@
register_module([
"name" => "User Preferences",
"version" => "0.4.1",
"version" => "0.4.2",
"author" => "Starbeamrainbowlabs",
"description" => "Adds a user preferences page, letting people do things like change their email address and password.",
"id" => "feature-user-preferences",
@ -65,11 +65,11 @@ register_module([
$content .= "</figure></a><br />\n";
}
$content .= "<label for='username'>Username:</label>\n";
$content .= "<input type='text' name='username' value='$env->user' readonly />\n";
$content .= "<input type='text' name='username' value='".htmlentities($env->user)."' readonly />\n";
$content .= "<form method='post' action='?action=save-preferences'>\n";
$content .= " <label for='email-address'>Email Address:</label>\n";
$content .= " <input type='email' id='email-address' name='email-address' placeholder='e.g. bob@bobsrockets.com' value='{$env->user_data->emailAddress}' />\n";
$content .= " <p><small>Used to send you notifications etc. Never shared with anyone except $settings->admindetails_name, $settings->sitename's administrator.</small></p>\n";
$content .= " <input type='email' id='email-address' name='email-address' placeholder='e.g. bob@bobsrockets.com' value='".htmlentities($env->user_data->emailAddress)."}' />\n";
$content .= " <p><small>Used to send you notifications etc. Never shared with anyone except ".htmlentities($settings->admindetails_name).", $settings->sitename's administrator.</small></p>\n";
if($settings->email_verify_addresses) {
$content .= " <p>Email verification status: <strong>".(empty($env->user_data->emailAddressVerified) ? "not " : "")."verified</strong> <small><em>(Email address verification is required in order to receive emails (other than the verification email itself, of course). Click the link in the verification email sent to you to verify your address, or change it here to get another verification email - changing it to the same email address is ok)</em></small></p>";
}
@ -113,12 +113,12 @@ register_module([
if(isset($_POST["email-address"])) {
if(mb_strlen($_POST["email-address"]) > 320) {
http_response_code(413);
exit(page_renderer::render_main("Error Saving Email Address - $settings->sitename", "<p>The email address you supplied (<code>{$_POST['email-address']}</code>) is too long. Email addresses can only be 320 characters long. <a href='javascript:window.history.back();'>Go back</a>."));
exit(page_renderer::render_main("Error Saving Email Address - $settings->sitename", "<p>The email address you supplied (<code>".htmlentities($_POST['email-address'])."</code>) is too long. Email addresses can only be 320 characters long. <a href='javascript:window.history.back();'>Go back</a>."));
}
if(mb_strpos($_POST["email-address"], "@") === false) {
http_response_code(422);
exit(page_renderer::render_main("Error Saving Email Address - $settings->sitename", "<p>The email address you supplied (<code>{$_POST['email-address']}</code>) doesn't appear to be valid. <a href='javascript:window.history.back();'>Go back</a>."));
exit(page_renderer::render_main("Error Saving Email Address - $settings->sitename", "<p>The email address you supplied (<code>".htmlentities($_POST['email-address'])."</code>) doesn't appear to be valid. <a href='javascript:window.history.back();'>Go back</a>."));
}
$old_address = $env->user_data->emailAddress ?? null;
$env->user_data->emailAddress = $_POST["email-address"];
@ -131,7 +131,7 @@ register_module([
if(empty($env->user_data->emailAddressVerified) && !email_verify_addresses($env->user)) {
http_response_code(503);
exit(page_renderer::render_main("Server error sending verification code - $settings->sitename", "<p>$settings->sitename tried to send you an email to verify your email address, but was unable to do so. The changes to your settings have not been saved. Please contact $settings->admindetails_name, whose email address can be found at the bottom of this page.</p>"));
exit(page_renderer::render_main("Server error sending verification code - $settings->sitename", "<p>$settings->sitename tried to send you an email to verify your email address, but was unable to do so. The changes to your settings have not been saved. Please contact ".htmlentities($settings->admindetails_name).", whose email address can be found at the bottom of this page.</p>"));
}
}
}
@ -139,10 +139,10 @@ register_module([
// Save the user's preferences
if(!save_userdata()) {
http_response_code(503);
exit(page_renderer::render_main("Error Saving Preferences - $settings->sitename", "<p>$settings->sitename had some trouble saving your preferences! Please contact $settings->admindetails_name, $settings->sitename's administrator and tell them about this error if it still occurs in 5 minutes. They can be contacted by email at this address: ".hide_email($settings->admindetails_email).".</p>"));
exit(page_renderer::render_main("Error Saving Preferences - $settings->sitename", "<p>$settings->sitename had some trouble saving your preferences! Please contact ".htmlentities($settings->admindetails_name).", $settings->sitename's administrator and tell them about this error if it still occurs in 5 minutes. They can be contacted by email at this address: ".hide_email($settings->admindetails_email, $settings->admindetails_name).".</p>"));
}
exit(page_renderer::render_main("Preferences Saved Successfully - $settings->sitename", "<p>Your preferences have been saved successfully! You could go back your <a href='?action=user-preferences'>preferences page</a>, or on to the <a href='?page=" . rawurlencode($settings->defaultpage) . "'>$settings->defaultpage</a>.</p>
exit(page_renderer::render_main("Preferences Saved Successfully - $settings->sitename", "<p>Your preferences have been saved successfully! You could go back your <a href='?action=user-preferences'>preferences page</a>, or on to the <a href='?page=" . rawurlencode($settings->defaultpage) . "'>".htmlentities($settings->defaultpage)."</a>.</p>
<p>If you changed your email address, a verification code will have been sent to the email address you specified. Click on the link provided to verify your new email address.</p>"));
});
@ -163,7 +163,7 @@ register_module([
http_response_code(307);
header("x-status: failed");
header("x-problem: not-logged-in");
exit(page_renderer::render_main("Not logged in - $settings->sitename", "<p>You aren't logged in, so you can't verify your email address. Try <a href='?action=login&amp;returnto=".rawurlencode("?action=email-address-verify&code=".($_GET["code"]??""))."'>logging in</a>.</p>"));
exit(page_renderer::render_main("Not logged in - $settings->sitename", "<p>You aren't logged in, so you can't verify your email address. Try <a href='?action=login&amp;returnto=".rawurlencode("?action=email-address-verify&code=".rawurlencode($_GET["code"]??""))."'>logging in</a>.</p>"));
}
if($env->user_data->emailAddressVerified) {
@ -175,7 +175,7 @@ register_module([
http_response_code(400);
header("x-status: failed");
header("x-problem: no-code-specified");
exit(page_renderer::render_main("No verification code specified - $settings->sitename", "<p>No verification code specified. Do so with the <code>code</code> GET parameter.</p>"));
exit(page_renderer::render_main("No verification code specified - $settings->sitename", "<p>No verification code specified. Do so with the <code>code</code> GET parameter, or try making sure you copied the email address from the email you were sent correctly.</p>"));
}
if($env->user_data->emailAddressVerificationCode !== $_GET["code"]) {
@ -193,7 +193,7 @@ register_module([
http_response_code(503);
header("x-status: failed");
header("x-problem: server-error-disk-io");
exit(page_renderer::render_main("Server error - $settings->sitename", "<p>Your verification code was correct, but $settings->sitename was unable to update your user details because it failed to write the changes to disk. Please contact $settings->admindetails_name, whose email address can be found at the bottom of the page.</p>"));
exit(page_renderer::render_main("Server error - $settings->sitename", "<p>Your verification code was correct, but $settings->sitename was unable to update your user details because it failed to write the changes to disk. Please contact ".htmlentities($settings->admindetails_name).", whose email address can be found at the bottom of the page.</p>"));
}
header("x-status: success");
@ -230,7 +230,7 @@ register_module([
// Save the userdata back to disk
if(!save_userdata()) {
http_response_code(503);
exit(page_renderer::render_main("Error Saving Password - $settings->sitename", "<p>While you entered your old password correctly, $settings->sitename encountered an error whilst saving your password to disk! Your password has not been changed. Please contact $settings->admindetails_name for assistance (you can find their email address at the bottom of this page)."));
exit(page_renderer::render_main("Error Saving Password - $settings->sitename", "<p>While you entered your old password correctly, $settings->sitename encountered an error whilst saving your password to disk! Your password has not been changed. Please contact ".htmlentities($settings->admindetails_name)." for assistance (you can find their email address at the bottom of this page)."));
}
http_response_code(307);
@ -299,18 +299,19 @@ register_module([
http_response_code(307);
header("x-reason: found-local-avatar");
header("location: ?action=preview&size=$size&page=" . urlencode("Users/$requested_username/Avatar"));
header("content-type: text/plain");
exit("This user's avatar can be found at Files/$requested_username/Avatar");
});
// Display a help section on the user preferences, but only if the user
// is logged in and so able to access them
if($env->is_logged_in) {
add_help_section("910-user-preferences", "User Preferences", "<p>As you are logged in, $settings->sitename lets you configure a selection of personal preferences. These can be viewed and tweaked to you liking over on the <a href='?action=user-preferences'>preferences page</a>, which can be accessed at any time by clicking the cog icon (it looks something like this: <a href='?action=user-preferences'>$settings->user_preferences_button_text</a>), though the administrator of $settings->sitename ($settings->admindetails_name) may have changed its appearance.</p>");
add_help_section("910-user-preferences", "User Preferences", "<p>As you are logged in, $settings->sitename lets you configure a selection of personal preferences. These can be viewed and tweaked to you liking over on the <a href='?action=user-preferences'>preferences page</a>, which can be accessed at any time by clicking the cog icon (it looks something like this: <a href='?action=user-preferences'>$settings->user_preferences_button_text</a>), though the administrator of $settings->sitename (".htmlentities($settings->admindetails_name).") may have changed its appearance.</p>");
}
if($settings->avatars_show) {
add_help_section("915-avatars", "Avatars", "<p>$settings->sitename allows you to upload an avatar and have it displayed next to your name. If you don't have an avatar uploaded yet, then $settings->sitename will take a <a href='https://www.techopedia.com/definition/19744/hash-function'>hash</a> of your email address and ask <a href='https://gravatar.com'>Gravatar</a> for for your Gravatar instead. If you haven't told $settings->sitename what your email address is either, a hash of your username is used instead. If you don't have a gravatar, then $settings->sitename asks Gravatar for an identicon instead.</p>
<p>Your avatar on $settings->sitename currently looks like this: <img class='avatar' src='?action=avatar&user=" . urlencode($env->user) . "' />" . ($settings->upload_enabled ? " - you can upload a new one by going to your <a href='?action=user-preferences'>preferences</a>, or <a href='?action=upload&avatar=yes' />clicking here</a>." : ", but $settings->sitename currently has uploads disabled, so you can't upload a new one directly to $settings->sitename. You can, however, set your email address in your <a href='?action=user-preferences'>preferences</a> and <a href='https://en.gravatar.com/'>create a Gravatar</a>, and then it should show up here on $settings->sitename shortly.") . "</p>");
<p>Your avatar on $settings->sitename currently looks like this: <img class='avatar' src='?action=avatar&user=" . rawurlencode($env->user) . "' />" . ($settings->upload_enabled ? " - you can upload a new one by going to your <a href='?action=user-preferences'>preferences</a>, or <a href='?action=upload&avatar=yes' />clicking here</a>." : ", but $settings->sitename currently has uploads disabled, so you can't upload a new one directly to $settings->sitename. You can, however, set your email address in your <a href='?action=user-preferences'>preferences</a> and <a href='https://en.gravatar.com/'>create a Gravatar</a>, and then it should show up here on $settings->sitename shortly.") . "</p>");
}
}
]);

View File

@ -279,7 +279,7 @@ function generate_page_list($pagelist)
{
foreach($pageindex->$pagename->tags as $tag)
{
$tags .= "<a href='?action=list-tags&amp;tag=" . rawurlencode($tag) . "' class='mini-tag'>$tag</a>, ";
$tags .= "<a href='?action=list-tags&amp;tag=" . rawurlencode($tag) . "' class='mini-tag'>".htmlentities($tag)."</a>, ";
}
$tags = substr($tags, 0, -2); // Remove the last ", " from the tag list
}