security: harden signup username validation + fix reflected XSS (#184) (#187)

This commit is contained in:
Ferywir
2026-06-09 13:57:56 +02:00
committed by GitHub
parent fabe77e3b8
commit d30bef0a40
3 changed files with 15 additions and 7 deletions
+9 -1
View File
@@ -77,9 +77,17 @@ class Account {
} else {
if (strlen($_POST['name']) < USRNM_MIN_LENGTH) {
$form->addError("name", USRNM_SHORT);
} elseif (strlen($_POST['name']) > (defined('USRNM_MAX_LENGTH') ? USRNM_MAX_LENGTH : 15)) {
// Hard upper bound on the username length (issue #184).
$form->addError("name", USRNM_CHAR);
} elseif (!USRNM_SPECIAL && preg_match('/[^0-9A-Za-z]/', $_POST['name'])) {
$form->addError("name", USRNM_CHAR);
} elseif (USRNM_SPECIAL && preg_match("/[:,\\. \\n\\r\\t\\s\\<\\>]+/", $_POST['name'])) {
} elseif (USRNM_SPECIAL && !preg_match('/^[A-Za-z0-9._-]+(?: [A-Za-z0-9._-]+)*$/D', $_POST['name'])) {
// SECURITY (issue #184): positive ASCII allowlist instead of the old
// negative filter. Allows letters, digits, . _ - and single internal
// spaces only (no leading/trailing/double spaces, no trailing newline).
// Blocks & = ' " < > ; ( ) and ALL multibyte/emoji input, which were
// previously accepted and led to stored XSS / display corruption.
$form->addError("name", USRNM_CHAR);
} elseif (strtolower($_POST['name']) === 'natars') {
$form->addError("name", USRNM_TAKEN);
+4 -4
View File
@@ -61,28 +61,28 @@ if(REG_OPEN == true){ ?>
<p><?php echo BEFORE_REGISTER; ?></p>
<form name="snd" method="post" action="anmelden.php">
<input type="hidden" name="invited" value="<?php echo $invited; ?>" />
<input type="hidden" name="invited" value="<?php echo htmlspecialchars($invited, ENT_QUOTES, 'UTF-8'); ?>" />
<input type="hidden" name="ft" value="a1" />
<table cellpadding="1" cellspacing="1" id="sign_input">
<tbody>
<tr class="top">
<th><?php echo NICKNAME; ?></th>
<td><input class="text" type="text" name="name" value="<?php echo $form->getValue('name'); ?>" maxlength="30" />
<td><input class="text" type="text" name="name" value="<?php echo htmlspecialchars($form->getValue('name'), ENT_QUOTES, 'UTF-8'); ?>" maxlength="30" />
<span class="error"><?php echo $form->getError('name'); ?></span>
</td>
</tr>
<tr>
<th><?php echo EMAIL; ?></th>
<td>
<input class="text" type="text" name="email" value="<?php echo stripslashes($form->getValue('email')); ?>" />
<input class="text" type="text" name="email" value="<?php echo htmlspecialchars(stripslashes($form->getValue('email')), ENT_QUOTES, 'UTF-8'); ?>" />
<span class="error"><?php echo $form->getError('email'); ?></span>
</td>
</tr>
<tr>
<th><?php echo PASSWORD; ?></th>
<td>
<input class="text" type="password" name="pw" value="<?php echo stripslashes($form->getValue('pw')); ?>" maxlength="100" />
<input class="text" type="password" name="pw" value="<?php echo htmlspecialchars(stripslashes($form->getValue('pw')), ENT_QUOTES, 'UTF-8'); ?>" maxlength="100" />
<span class="error"><?php echo $form->getError('pw'); ?></span>
</td>
</tr>
+2 -2
View File
@@ -193,7 +193,7 @@ Element.implement({
</tr>
<tr class="btm">
<th><?php echo PASSWORD; ?></th>
<td><input class="text" type="password" name="pw" value="<?php echo $form->getValue("pw");?>" maxlength="100" autocomplete='off' /> <span class="error"><?php echo $form->getError("pw"); ?></span></td>
<td><input class="text" type="password" name="pw" value="<?php echo htmlspecialchars($form->getValue("pw"), ENT_QUOTES, 'UTF-8');?>" maxlength="100" autocomplete='off' /> <span class="error"><?php echo $form->getError("pw"); ?></span></td>
</tr>
</tbody>
</table>
@@ -217,7 +217,7 @@ if($form->getError("activate") != "") {
echo "<p class=\"error_box\">
<span class=\"error\">".EMAIL_NOT_VERIFIED."</span><br>
".EMAIL_FOLLOW."<br>
<a href=\"activate.php?usr=".$form->getError("activate")."\">".VERIFY_EMAIL."</a>
<a href=\"activate.php?usr=".urlencode($form->getError("activate"))."\">".VERIFY_EMAIL."</a>
</p>";
}
if($form->getError("vacation") != "") {