Skip to content
Permalink
Browse files Browse the repository at this point in the history
hash_equals函数添加及其应用;CloseTags函数进行了修正;
  • Loading branch information
rainbowsoft committed May 21, 2020
1 parent 17c12c1 commit a67607f
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 33 deletions.
1 change: 1 addition & 0 deletions phpcs.xml
Expand Up @@ -42,6 +42,7 @@
<exclude name="PHPCompatibility.FunctionUse.NewFunctions.rrmdir.Found" />
<exclude name="PHPCompatibility.FunctionUse.NewFunctions.gzdecode.Found" />
<exclude name="PHPCompatibility.FunctionUse.NewFunctions.array_replace_recursive.Found" />
<exclude name="PHPCompatibility.FunctionUse.NewFunctions.hash_equals.Found" />
<exclude name="PHPCompatibility.Constants.NewConstants.PHP_VERSION_ID.Found" />
<exclude name="PHPCompatibility.Constants.NewConstants.FNM_PATHNAME.Found" />
<exclude name="PHPCompatibility.Constants.NewConstants.FNM_NOESCAPE.Found" />
Expand Down
40 changes: 10 additions & 30 deletions zb_system/function/c_system_common.php
Expand Up @@ -1218,42 +1218,22 @@ function TransferHTML($source, $param)
*/
function CloseTags($html)
{
// strip fraction of open or close tag from end (e.g. if we take first x characters, we might cut off a tag at the end!)
$html = preg_replace('/<[^>]*$/', '', $html); // ending with fraction of open tag

// put open tags into an array
preg_match_all('#<([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
$opentags = $result[1];

// put all closed tags into an array
preg_match_all('#<(?!meta|img|br|hr|input\b)\b([a-z]+)(?: .*)?(?<![/|/ ])>#iU', $html, $result);
$openedtags = $result[1];
preg_match_all('#</([a-z]+)>#iU', $html, $result);
$closetags = $result[1];

$len_opened = count($opentags);

// if all tags are closed, we can return
if (count($closetags) == $len_opened) {
$closedtags = $result[1];
$len_opened = count($openedtags);
if (count($closedtags) == $len_opened) {
return $html;
}

// close tags in reverse order that they were opened
$opentags = array_reverse($opentags);

// self closing tags
$sc = array('br', 'input', 'img', 'hr', 'meta', 'link');
// ,'frame','iframe','param','area','base','basefont','col'
// should not skip tags that can have content inside!

for ($i = 0; $i < $len_opened; $i++) {
$ot = strtolower($opentags[$i]);

if (!in_array($opentags[$i], $closetags) && !in_array($ot, $sc)) {
$html .= '</' . $opentags[$i] . '>';
$openedtags = array_reverse($openedtags);
for ($i=0; $i < $len_opened; $i++) {
if (!in_array($openedtags[$i], $closedtags)) {
$html .= '</'.$openedtags[$i].'>';
} else {
unset($closetags[array_search($opentags[$i], $closetags)]);
unset($closedtags[array_search($openedtags[$i], $closedtags)]);
}
}

return $html;
}

Expand Down
51 changes: 50 additions & 1 deletion zb_system/function/c_system_compat.php
Expand Up @@ -446,8 +446,57 @@ function recurse($array, $array1)
$array = recurse($array, $args[$i]);
}
}

return $array;
}

}


if (!function_exists('hash_equals')) {

/**
* Timing attack safe string comparison
*
* Compares two strings using the same time whether they're equal or not.
* This function should be used to mitigate timing attacks; for instance, when testing crypt() password hashes.
*
* @param string $known_string The string of known length to compare against
* @param string $user_string The user-supplied string
* @return boolean Returns TRUE when the two strings are equal, FALSE otherwise.
*/
function hash_equals($known_string, $user_string)
{
if (func_num_args() !== 2) {
// handle wrong parameter count as the native implentation
trigger_error('hash_equals() expects exactly 2 parameters, ' . func_num_args() . ' given', E_USER_WARNING);
return null;
}
if (is_string($known_string) !== true) {
trigger_error('hash_equals(): Expected known_string to be a string, ' . gettype($known_string) . ' given', E_USER_WARNING);
return false;
}
$known_string_len = strlen($known_string);
$user_string_type_error = 'hash_equals(): Expected user_string to be a string, ' . gettype($user_string) . ' given'; // prepare wrong type error message now to reduce the impact of string concatenation and the gettype call
if (is_string($user_string) !== true) {
trigger_error($user_string_type_error, E_USER_WARNING);
// prevention of timing attacks might be still possible if we handle $user_string as a string of diffent length (the trigger_error() call increases the execution time a bit)
$user_string_len = strlen($user_string);
$user_string_len = $known_string_len + 1;
} else {
$user_string_len = $known_string_len + 1;
$user_string_len = strlen($user_string);
}
if ($known_string_len !== $user_string_len) {
$res = $known_string ^ $known_string; // use $known_string instead of $user_string to handle strings of diffrent length.
$ret = 1; // set $ret to 1 to make sure false is returned
} else {
$res = $known_string ^ $user_string;
$ret = 0;
}
for ($i = strlen($res) - 1; $i >= 0; $i--) {
$ret |= ord($res[$i]);
}
return $ret === 0;
}

}
2 changes: 1 addition & 1 deletion zb_system/function/lib/zblogphp.php
Expand Up @@ -1316,7 +1316,7 @@ public function Verify_Final($name, $password, &$member = null)
}
$m = $this->GetMemberByName($name);
if ($m->ID != null) {
if (strcasecmp($m->Password, $password) == 0) {
if (hash_equals($m->Password, $password) === true) {
$member = $m;

return true;
Expand Down
2 changes: 1 addition & 1 deletion zb_users/plugin/passwordvisit/include.php
Expand Up @@ -31,7 +31,7 @@ function passwordvisit_input_password(&$template)
if (isset($_POST['password']) && $_POST['password'] != '') {
$article = $template->GetTags('article');
if ($article->Metas->passwordvisit_password != '') {
if (GetVars('password', 'POST') == $article->Metas->passwordvisit_password) {
if (GetVars('password', 'POST') === $article->Metas->passwordvisit_password) {
return;
} else {
echo '<script type="text/javascript">alert("密码错误,请重新输入!");window.location="' . $article->Url . '";</script>';
Expand Down

0 comments on commit a67607f

Please sign in to comment.