我说的是与通过以下方式限制对页面的访问相同的事情
IP 地址,但使用域。 IE。 yoursite.com ...我是
试图阻止 yoursite.com 访问我的表单。这是个
努力限制来自使用一个域但俄罗斯域的访问
多个不断变化的 IP 地址。
这取决于您所说的“有权访问”是什么意思。如果您想阻止网站使用/发送垃圾邮件您托管的表单,那么您可以做一些事情。首先在 web.config 文件中实现 CORS 限制:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
<add name="Access-Control-Allow-Origin" value="https://yourdomain.com" />
</customHeaders>
</httpProtocol>
</system.webServer>
</configuration>
将Access-Control-Allow-Origin 设置为您自己的域。这将阻止其他网站上的 JavaScript 向您的表单发出 POST 或 GET 请求。
将X-Frame-Options 设置为SAMEORIGIN
这将阻止其他网站在 iFrame 中显示您的网站。
您还应该使用 CSRF 令牌。第三方网站访问您托管的表单并不是严格意义上的 CSRF 问题(实际的 CSRF 漏洞利用往往会在攻击者站点上使用隐藏的 iFrame,这些 iFrame 用于劫持访问者可能与另一个网站进行的活动会话。这是可以防止的由另一个网站要求在每个表单提交中包含一个令牌)。但是,在尝试阻止其他网站访问您托管的公共表单时,使用 CSRF 令牌仍然是一种很好的做法和很好的威慑。
有很多方法可以实现 CSRF 令牌(并且有很多教程)但这是我使用 CSRF cookie 的首选方法,如下面的简单 Web 表单所示:
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%
response.Charset = "utf-8"
Const CSRF_token_max = 9999999999999
Const CSRF_token_min = 1000000000000
sub create_CSRF_cookie(ignoreFormPost)
' Response.Cookies and Request.Cookies don't behave as you'd expect in Classic ASP.
' Response.Cookies is used to create a new cookie which is return in the HTTP
' response headers, so the client can store it locally.
' Request.Cookies is used to retrieve a cookie from the HTTP request headers, which
' are included in every HTTP request the client makes to the server.
' But here's the catch:
' If you use Response.Cookies to create a new cookie, but during the same page load
' you also use Request.Cookies to retrieve the cookie you have just set, ASP will
' return the value of the cookie waiting to be sent back to the client in the response
' headers, despite the cookie having never left the server.
' This has it's uses, but if we issue a new CSRF cookie before processing a form post,
' Request.Cookies("CSRF") will return the value of the new CSRF cookie rather than the
' value of the cookie contained in the request headers, and thus a CSRF token mismatch
' will occur.
if request.form = "" OR ignoreFormPost then
Dim CSRF_token
Randomize()
CSRF_token = Int((CSRF_token_max-CSRF_token_min+1)*Rnd+CSRF_token_min)
' Save the CSRF token as a cookie.
' HttpOnly must be false, which is it by default in classic asp.
Response.Cookies("CSRF") = CSRF_token
end if
end sub
' Create a new CSRF cookie on each page load
' Set "ignoreFormPost" to false. We don't want to create a new cookie if a form has been posted.
' We will do that once the form has been validated and processed.
call create_CSRF_cookie(false)
'---------------------------------------------------------------
' Process a form POST
'---------------------------------------------------------------
if request.form("formName") = "CSRFform" then
Dim hostName, responseStatus, responseColor, expectedCSRF, postedCSRF, postedText
' Is your domain using http or https?
if Request.ServerVariables("HTTPS") = "on" then _
hostName = "https://" else hostName = "http://"
' Build your hostname, e.g: http://yourdomain.com
hostName = hostName & Request.ServerVariables("HTTP_HOST")
expectedCSRF = request.cookies("CSRF")
postedCSRF = request.Form("CSRF")
postedText = request.Form("text")
' Was the form submitted from your domain?
' Is the CSRF token in the form data the correct length?
' Does the CSRF token in the form data match the CSRF token in the cookie?
if inStr(1,Request.ServerVariables("HTTP_REFERER"),hostName,1) = 1 _
AND len(request.form("CSRF")) = len(CSRF_token_max) _
AND request.Form("CSRF") = request.cookies("CSRF") then
' Everything checks out. Do whatever it is you need to do
responseColor = "#00CD42"
responseStatus = "Form submitted successfully"
else
' verification failed
responseColor = "#E00025"
responseStatus = "Form validation failed"
end if
' Create a new CSRF cookie and tell the sub to ignore the fact that a form was posted.
' We've processed the form now so a new CSRF cookie can be issued.
call create_CSRF_cookie(true)
end if
%><!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<%
' We could populate the hidden CSRF field with the "CSRF_token" variable.
' But instead, we're going to retrieve the token from the CSRF cookie
' as the form is submitted and insert it into the CSRF hidden field.
' Why get the CSRF token from the cookie? Well, let's assume you have
' many forms that require a CSRF token. If the user loads a form and
' we populate the CSRF field with the "CSRF_token" variable, great...
' but what if they open another form before submitting this one. A new
' CSRF cookie will be generated. The form will be validated just fine,
' but if they go back to the previous form and submit it, the CSRF cookie
' will have changed and the form will fail to validate.
' This method allows us to generate a new CSRF cookie each time one is
' required, and forms that have already been generated but forgotten
' about will still be verified once the user gets round to submitting it.
' It's quite a common CSRF technique and one I borrowed/stole from Pythons
' Django framework. Ideally, forms should be posted and handled using ajax,
' this would avoid validation fails when resubmitting a form on a page reload
%>
<form method="post" name="CSRFform" onsubmit="getCSRF()">
<table width="<% if request.form("formName") = "CSRFform" then response.write "5" %>0%" border="1" cellspacing="2" cellpadding="6">
<tbody>
<tr>
<td>
<input type="text" name="text" value="<%=Server.HTMLEncode(request.form("text"))%>" placeholder="Enter some text">
<input type="hidden" id="CSRF" name="CSRF" value="">
<input type="hidden" name="formName" value="CSRFform">
<input type="submit" value="Submit">
</td>
</tr>
<% if request.form("formName") = "CSRFform" then %>
<tr>
<td bgcolor="<%=responseColor%>" style="color:#ffffff; font-size:18px; font-weight:bold;"><%=responseStatus%></td>
</tr>
<tr>
<td>
<%
if postedCSRF = "undefined" then postedCSRF = "NA"
if expectedCSRF = "" then expectedCSRF = "NA"
if postedText = "" then postedText = "NA"
response.write "<p><b>Referer</b>: " & Request.ServerVariables("HTTP_REFERER") & "</p>"
response.write "<p><b>Expected Referer</b>: " & hostName & "/*</p><hr>"
response.write "<p><b>CSRF Token</b>: " & postedCSRF & "</p>"
response.write "<p><b>Expected CSRF Token</b>: " & expectedCSRF & "</p><hr>"
response.write "<p><b>CSRF Length</b>: " & len(replace(postedCSRF,"NA","")) & "</p>"
response.write "<p><b>Expected CSRF Length</b>: " & len(CSRF_token_max) & "</p><hr>"
response.write "<p><b>Posted Text</b>: " & Server.HTMLEncode(postedText) & "</p>"
%>
</td>
</tr>
<% end if %>
</tbody>
</table>
</form>
<script>
// Get the most recent CSRF token from the cookies
function getCSRF() {
document.getElementById("CSRF").value = getCookie("CSRF");
}
function getCookie(name) {
var value = "; " + document.cookie;
var parts = value.split("; " + name + "=");
if (parts.length == 2) return parts.pop().split(";").shift();
}
</script>
<body>
</body>
</html>
您会注意到,除了验证 CSRF 令牌外,我还对照服务器域名检查 HTTP_REFERER。每当提交表单时,HTTP_REFERER 标头包含提交帖子的网站的 URL(这是由浏览器发出的,不能使用标准的 HTTP POST 请求进行欺骗)。如果表单不是从您的域提交的,则不会处理表单数据。
因此,目前,第三方网站不可能使用客户端代码发送垃圾邮件或操纵您托管的表单。这是因为我们是:
要求每个发布请求都返回一个有效的令牌,并且该令牌只能在您的网站上发布和访问。
检查HTTP_REFERER 标头以确保发布请求来自您的网站。
使用 Access-Control-Allow-Origin 防止 javascript/ajax 从第三方网站发布到您的表单(javascript/ajax 可能被用于欺骗伪造的 HTTP_REFERER 标头)
但是...如果攻击者选择使用服务器端代码访问您的表单,那么这会打开一个完整的罐头或蠕虫。浏览器需要遵守非常严格的规则,但是当您将浏览器排除在外并使用服务器端代码访问和操作另一个网站上的 Web 表单时,这些规则可以被绕过。攻击者可能会使用 cURL(或类似协议)来请求您的 Web 表单,读取您的服务器在响应标头中发出的 CSRF cookie,使用该 CSRF 令牌来验证表单,将表单发送回您的服务器连同您发布的 CSRF cookie 并欺骗 HTTP_REFERER 标头,使其显示为从您的网站提交的表单。攻击者本质上会创建一个机器人,而这些很难检测和预防,尤其是因为它们也可以欺骗其他标头,例如HTTP_USER_AGENT。
有一些解决方案可以使用算法来检测可疑活动。 CloudFlare 提供了非常好的机器人管理服务,非常适合检测和阻止机器人以及一般数据抓取/挖掘:https://www.cloudflare.com/lp/bot-management/