Я говорю о том же, что и ограничение доступа к странице через
IP-адрес, но вместо этого используется домен. И.Е. yoursite.com ... Я
пытаясь удержать yoursite.com от доступа к моей форме. Это
усилия по ограничению доступа из России домена, который использует один домен, но
несколько постоянно меняющихся IP-адресов.
Это зависит от того, что вы подразумеваете под «доступом». Если вы хотите запретить веб-сайту использовать / спамить форму, которую вы размещаете, то есть несколько вещей, которые вы можете сделать. Начните с реализации ограничений CORS в вашем файле web.config:
<?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, как правило, используют скрытые iFrames на сайте злоумышленников, которые используются для перехвата активного сеанса, который может иметь посетитель с другим сайтом. Это запрещено другим веб-сайтом, требующим, чтобы токен был включен в каждую отправку формы). Но использование токенов CSRF все еще является хорошей практикой и хорошим сдерживающим фактором при попытке запретить другим веб-сайтам доступ к общедоступной форме, которую вы размещаете.
Есть много способов реализовать токены CSRF (и есть много обучающих программ). Но это мой предпочтительный метод, который использует куки CSRF, как показано в этой простой веб-форме:
<%@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
)
Однако ... если злоумышленник решит получить доступ к вашей форме с помощью серверного кода, то это откроет целую банку или червей. Браузеры обязаны соблюдать очень строгие правила, но когда вы убираете браузеры из уравнения и используете серверный код для доступа к веб-форме на другом веб-сайте и манипулирования ею, эти правила можно обойти. Злоумышленник может использовать cURL (или аналогичный протокол) для запроса вашей веб-формы, прочитать файл cookie CSRF, выданный вашим сервером, в заголовках ответа, использовать этот токен CSRF для проверки формы, отправить форму обратно на ваш сервер вместе с выданным вами файлом cookie CSRF и подделывает заголовок HTTP_REFERER
, чтобы он отображался при отправке формы с вашего веб-сайта. Злоумышленник, по сути, создал бы бота, и его очень трудно обнаружить и предотвратить, тем более что он может подделать и другие заголовки, такие как HTTP_USER_AGENT
.
Однако есть решения, которые используют алгоритмы для обнаружения подозрительной активности. CloudFlare предлагает действительно хорошие услуги по управлению ботами, которые отлично подходят для обнаружения и блокировки ботов, а также для общего сбора и анализа данных: https://www.cloudflare.com/lp/bot-management/