我希望编写一些代码来捕获用户的域名,并使用它来允许他们访问或不允许他们访问页面内容。
我说的是限制通过IP地址访问页面但使用域名的相同内容。 I.E. 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/