Как мне ограничить доступ к классической странице asp доменом, а не IP? - PullRequest
0 голосов
/ 16 апреля 2019

Я хочу написать некоторый код, который фиксирует доменное имя пользователя и использует его, чтобы разрешить ему доступ или не разрешить ему доступ к содержимому страницы.

1 Ответ

0 голосов
/ 17 апреля 2019

Я говорю о том же, что и ограничение доступа к странице через 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). Если форма не была отправлена ​​с вашего домена, то данные формы не будут обрабатываться.

Таким образом, теперь сторонний веб-сайт уже не может использовать код на стороне клиента для рассылки спама или манипулирования размещаемой вами формой. Это потому что мы:

  1. Требование, чтобы действительный токен возвращался при каждом почтовом запросе, и токен может быть выдан и доступен только на вашем веб-сайте.

  2. Проверка заголовка HTTP_REFERER, чтобы убедиться, что с вашего сайта был отправлен запрос на публикацию.

  3. Использование 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/

...