只要将针对您网站的恶意 HTML 或 JavaScript 嵌入到另一个已成功执行的 HTML 页面(或电子邮件)中,就有CSRF的手段。
下面是一个示例,它被放置在另一个网页中,该网页在继续之前会无辜地询问您的姓名和年龄:
<form action="http://yoursite.com/transferfunds" method="post">
Your name: <input type="text"><br>
Your age: <input type="text"><br>
<input type="submit">
<input type="hidden" name="amount" value="1000">
<input type="hidden" name="toaccount" value="12345678">
</form>
请注意,该操作指向您的网站,并且隐藏的输入包含所需的 POST 信息。此示例将尝试将 1000 的资金(以任何货币)转移到帐号 12345678。如果您需要在表单上登录并实际检查,那么上述内容当然只有在不知情的用户有最近登录您的网站,但尚未注销,或会话尚未过期。
为了防止这种情况发生,最好的办法是向表单添加一个基于请求的令牌并在服务器端对其进行验证。即生成一个长的、唯一的且无法猜测的随机字符串,您将其存储在会话中并作为<input type="hidden">表单元素嵌入。提交表单后,将提交的令牌值与会话中的值进行比较(并立即删除会话中的值)。要更进一步,请使用CAPTCHA。
在您的特定情况下,我认为您实际上更担心XSS,这与 CSRF 相反,但反过来也可以成为 CSRF 的来源。XSS 的一个示例是,当用户在输入字段中输入以下内容时,该输入字段迟早会在同一网站上重新显示:
<form name="delete" action="admin/deleteusers" method="post"></form>
<script>document.form.delete.submit();</script>
每当您(作为管理员)查看带有(不可见!)表单和脚本的评论的页面时,它将成功执行。
防止 XSS 实际上很容易。在网页上显示它们之前,只需对任何用户控制的输入(即请求 URL、请求标头、请求参数和请求正文)进行HTML 转义。在 PHP 中,您可以使用htmlspecialchars()它,在 Java/JSP 中,您可以使用 JSTL fn:escapeXml()。这种方式下,将<被转换为任何输入的 HTML/JS 将按原样显示,因此无法执行。<>>