如何防止 PHP echo 结束 JS 字符串?
How to prevent PHP echo from ending a JS string?
我有这个代码:
<!DOCTYPE html>
<html>
<head>
<title>Sign up page</title>
<meta charset="UTF-8"/>
</head>
<body>
<h1>Sign up page</h1>
<form action="test.php" method="post">
<input placeholder="Enter your username" name="username"/><br/>
<input type="password" placeholder="Enter your password" style="margin-bottom:5px" name="password"/><br/>
<button type="submit" name="submit">Sign up</button>
</form>
<?php
if(isset($_POST["username"],$_POST["password"],$_POST["submit"])){
if(mb_strlen($_POST["username"])<8){
?>
<script>
alert("Your username must be at least 8 characters long.");
var i=document.getElementsByTagName("input")[0];
i.value="<?php echo $_POST['username']; ?>";
i.focus();
</script>
<?php
}else if(mb_strlen($_POST["password"])<8){
?>
<script>
alert("Your password must be at least 8 characters long.");
var i=document.getElementsByTagName("input")[1];
i.value="<?php echo $_POST['password']; ?>";
i.focus();
</script>
<?php
}else{
echo "Successfully signed up!";
}
}
?>
</body>
</html>
大多数情况下它工作正常,但如果您尝试在用户名字段中输入 ";f();
,您会在控制台中收到错误并且没有警报。
很明显,这种情况正在发生,因为当 PHP 收到输入时,它会在 JS 字符串中回显它。 ";
结束字符串和语句,而 f();
导致阻止输入聚焦的错误。这发生在 8 个字符以下,因此导致它属于 mb_strlen($_POST["username"])<8
.
通常我只会使用 htmlspecialchars
,但如果你尝试添加它,然后如果你输入 ";<!--
,它会出现 <
而不是 <
。有些用户可能希望在他们的用户名中包含 <
(或其他 &*;
个字符),并且(如果他们不是开发人员)会对 <
的含义感到惊讶。
那么如何在保持用户友好性的同时防止 JavaScript 注入?
您应该使用 json_encode
来输出您的值(请注意您不再需要封闭的 "
s):
i.value=<?php echo json_encode($_POST['username']); ?>;
这将确保字符串中的引号被转义并且整个值被 JavaScript 视为字符串。对于您的示例数据,这将产生
"\";f();"
问题是这个例子中的双引号。试试 addslashes
:
i.value="<?php echo addslashes($_POST['username']); ?>";
尽管 Nick's 答案可能对 JS 更好。我比 JSPHP
你永远不应该将未经处理的代码注入任何东西。这至少会引起XSS攻击。
我认为清理代码同时保持用户友好性的最简单方法是使用 json_encode()
<?php
}else if(mb_strlen($_POST["password"])<8){
$data = json_encode(['password' => $_POST['password']]);
?>
<script>
alert("Your password must be at least 8 characters long.");
var user_data = <?php echo $data; ?>;
var i=document.getElementsByTagName("input")[1];
i.value=user_data.password;
i.focus();
</script>
但是!
你真的应该把它放在输入元素中:
<input type="password" value="<?=htmlspecialchars($_POST['password'] ?? '',ENT_QUOTES); ?>" placeholder="Enter your password" style="margin-bottom:5px" name="password"/>
我有这个代码:
<!DOCTYPE html>
<html>
<head>
<title>Sign up page</title>
<meta charset="UTF-8"/>
</head>
<body>
<h1>Sign up page</h1>
<form action="test.php" method="post">
<input placeholder="Enter your username" name="username"/><br/>
<input type="password" placeholder="Enter your password" style="margin-bottom:5px" name="password"/><br/>
<button type="submit" name="submit">Sign up</button>
</form>
<?php
if(isset($_POST["username"],$_POST["password"],$_POST["submit"])){
if(mb_strlen($_POST["username"])<8){
?>
<script>
alert("Your username must be at least 8 characters long.");
var i=document.getElementsByTagName("input")[0];
i.value="<?php echo $_POST['username']; ?>";
i.focus();
</script>
<?php
}else if(mb_strlen($_POST["password"])<8){
?>
<script>
alert("Your password must be at least 8 characters long.");
var i=document.getElementsByTagName("input")[1];
i.value="<?php echo $_POST['password']; ?>";
i.focus();
</script>
<?php
}else{
echo "Successfully signed up!";
}
}
?>
</body>
</html>
大多数情况下它工作正常,但如果您尝试在用户名字段中输入 ";f();
,您会在控制台中收到错误并且没有警报。
很明显,这种情况正在发生,因为当 PHP 收到输入时,它会在 JS 字符串中回显它。 ";
结束字符串和语句,而 f();
导致阻止输入聚焦的错误。这发生在 8 个字符以下,因此导致它属于 mb_strlen($_POST["username"])<8
.
通常我只会使用 htmlspecialchars
,但如果你尝试添加它,然后如果你输入 ";<!--
,它会出现 <
而不是 <
。有些用户可能希望在他们的用户名中包含 <
(或其他 &*;
个字符),并且(如果他们不是开发人员)会对 <
的含义感到惊讶。
那么如何在保持用户友好性的同时防止 JavaScript 注入?
您应该使用 json_encode
来输出您的值(请注意您不再需要封闭的 "
s):
i.value=<?php echo json_encode($_POST['username']); ?>;
这将确保字符串中的引号被转义并且整个值被 JavaScript 视为字符串。对于您的示例数据,这将产生
"\";f();"
问题是这个例子中的双引号。试试 addslashes
:
i.value="<?php echo addslashes($_POST['username']); ?>";
尽管 Nick's 答案可能对 JS 更好。我比 JSPHP
你永远不应该将未经处理的代码注入任何东西。这至少会引起XSS攻击。
我认为清理代码同时保持用户友好性的最简单方法是使用 json_encode()
<?php
}else if(mb_strlen($_POST["password"])<8){
$data = json_encode(['password' => $_POST['password']]);
?>
<script>
alert("Your password must be at least 8 characters long.");
var user_data = <?php echo $data; ?>;
var i=document.getElementsByTagName("input")[1];
i.value=user_data.password;
i.focus();
</script>
但是!
你真的应该把它放在输入元素中:
<input type="password" value="<?=htmlspecialchars($_POST['password'] ?? '',ENT_QUOTES); ?>" placeholder="Enter your password" style="margin-bottom:5px" name="password"/>