programing

ASP에 대한 각도Net WebApi, 서버에 CSRF 구현

linuxpc 2023. 2. 25. 19:50
반응형

ASP에 대한 각도Net WebApi, 서버에 CSRF 구현

나는 Angular.js에 웹사이트를 구현하고 있는데, 그것은 ASP에 접속하고 있다.NET WebAPI 백엔드

Angular.js에는 안티 csrf 보호를 지원하는 몇 가지 기능이 내장되어 있습니다.각 http 요청에서 "XSRF-TOKEN"이라는 이름의 쿠키를 검색하여 "X-XSRF-TOKEN"이라는 이름의 헤더로 전송합니다.

이것은, Web 서버가 유저 인증 후에 XSRF-TOKEN cookie 를 설정할 수 있는 것과 동시에, X-XSRF-TOKEN 헤더의 착신 요구를 체크할 수 있는 것에 의존합니다.

Angular 문서에는 다음과 같이 기술되어 있습니다.

이를 이용하려면 서버는 첫 번째 HTTP GET 요청 시 XSRF-TOKEN이라고 하는 JavaScript 판독 가능한 세션쿠키에 토큰을 설정해야 합니다.이후 비 GET 요구에서는 서버는 쿠키가 X-XSRF-TOKEN HTTP 헤더와 일치하는지 확인할 수 있습니다.따라서 도메인에서 실행되고 있는 JavaScript만이 토큰을 읽을 수 있는지 확인할 수 있습니다.토큰은 사용자별로 고유해야 하며 서버에서 확인할 수 있어야 합니다(JavaScript가 자체 토큰을 구성하지 않도록 하려면).토큰은 보안을 강화하기 위해 salt를 사용하여 사이트 인증 쿠키를 요약하는 것이 좋습니다.

ASP에 대한 좋은 예를 찾을 수 없었습니다.NET WebAPI에 의해서, 다양한 소스의 도움을 받아 독자적인 WebAPI를 전개하고 있습니다.제 질문은, 코드에 문제가 있는 것을 알 수 있는 사람이 있나요?

처음에 간단한 도우미 클래스를 정의했습니다.

public class CsrfTokenHelper
{
    const string ConstantSalt = "<ARandomString>";

    public string GenerateCsrfTokenFromAuthToken(string authToken)
    {
        return GenerateCookieFriendlyHash(authToken);
    }

    public bool DoesCsrfTokenMatchAuthToken(string csrfToken, string authToken) 
    {
        return csrfToken == GenerateCookieFriendlyHash(authToken);
    }

    private static string GenerateCookieFriendlyHash(string authToken)
    {
        using (var sha = SHA256.Create())
        {
            var computedHash = sha.ComputeHash(Encoding.Unicode.GetBytes(authToken + ConstantSalt));
            var cookieFriendlyHash = HttpServerUtility.UrlTokenEncode(computedHash);
            return cookieFriendlyHash;
        }
    }
}

그 후 승인 컨트롤러에 다음과 같은 메서드가 있으며 Forms를 호출한 후 호출합니다.인증.SetAuthCookie():

    // http://www.asp.net/web-api/overview/security/preventing-cross-site-request-forgery-(csrf)-attacks
    // http://docs.angularjs.org/api/ng.$http
    private void SetCsrfCookie()
    {
        var authCookie = HttpContext.Current.Response.Cookies.Get(".ASPXAUTH");
        Debug.Assert(authCookie != null, "authCookie != null");
        var csrfToken = new CsrfTokenHelper().GenerateCsrfTokenFromAuthToken(authCookie.Value);
        var csrfCookie = new HttpCookie("XSRF-TOKEN", csrfToken) {HttpOnly = false};
        HttpContext.Current.Response.Cookies.Add(csrfCookie);
    }

다음으로 csrf 헤더를 체크하기 위해 컨트롤러에 추가할 수 있는 커스텀애트리뷰트가 있습니다

public class CheckCsrfHeaderAttribute : AuthorizeAttribute
{
    //  http://stackoverflow.com/questions/11725988/problems-implementing-validatingantiforgerytoken-attribute-for-web-api-with-mvc
    protected override bool IsAuthorized(HttpActionContext context)
    {
        // get auth token from cookie
        var authCookie = HttpContext.Current.Request.Cookies[".ASPXAUTH"];
        if (authCookie == null) return false;
        var authToken = authCookie.Value;

        // get csrf token from header
        var csrfToken = context.Request.Headers.GetValues("X-XSRF-TOKEN").FirstOrDefault();
        if (String.IsNullOrEmpty(csrfToken)) return false;

        // Verify that csrf token was generated from auth token
        // Since the csrf token should have gone out as a cookie, only our site should have been able to get it (via javascript) and return it in a header. 
        // This proves that our site made the request.
        return new CsrfTokenHelper().DoesCsrfTokenMatchAuthToken(csrfToken, authToken);
    }
}

마지막으로 사용자가 로그아웃하면 Csrf 토큰을 클리어합니다.

HttpContext.Current.Response.Cookies.Remove("XSRF-TOKEN");

이 접근법에 대해 누구나 명백한(또는 그다지 명확하지 않은) 문제를 발견할 수 있습니까?

당신의 코드는 정상인 것 같습니다.단, web.api는 asp.net MVC의 "위"에서 실행되며, 후자는 안티바이러스 토큰을 지원하므로 가지고 있는 대부분의 코드가 필요하지 않습니다.

코멘트에서 dbrunning 및 ccorrin은 MVC html 도우미를 사용하는 경우에만 AntiForgy 토큰을 사용할 수 있다는 우려를 나타냅니다.그것은 사실이 아니다.도우미는 서로 검증할 수 있는 세션 기반 토큰 쌍만 표시할 수 있습니다.상세한 것에 대하여는, 이하를 참조해 주세요.

갱신:

AntiForgy에서 사용할 수 있는 두 가지 방법이 있습니다.

  • AntiForgery.GetTokens을 형성합니다.2개의 out cookie를 사용합니다.

  • AntiForgery.Validate(cookieToken, formToken)한지 여부를 합니다.

당신은 그 두 가지 방법을 완전히 바꿔서 양식을 사용할 수 있다.헤더로서의 토큰토큰 및 쿠키실제 쿠키로서의 토큰토큰입니다. 그럼 속성 내에서 둘 다 검증에 호출하세요.

또 다른 솔루션은 JWT를 사용하는 것입니다(MembershipReboot 구현 확인).

다음 링크에서는 Ajax와 함께 내장된 위조 방지 토큰을 사용하는 방법을 보여 줍니다.

<script>
    @functions{
        public string TokenHeaderValue()
        {
            string cookieToken, formToken;
            AntiForgery.GetTokens(null, out cookieToken, out formToken);
            return cookieToken + ":" + formToken;                
        }
    }

    $.ajax("api/values", {
        type: "post",
        contentType: "application/json",
        data: {  }, // JSON data goes here
        dataType: "json",
        headers: {
            'RequestVerificationToken': '@TokenHeaderValue()'
        }
    });
</script>


void ValidateRequestHeader(HttpRequestMessage request)
{
    string cookieToken = "";
    string formToken = "";

    IEnumerable<string> tokenHeaders;
    if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
    {
        string[] tokens = tokenHeaders.First().Split(':');
        if (tokens.Length == 2)
        {
            cookieToken = tokens[0].Trim();
            formToken = tokens[1].Trim();
        }
    }
    AntiForgery.Validate(cookieToken, formToken);
}

그리고 이 질문을 보세요 앵귤러JS가 XSRF-TOKEN 쿠키를 찾을 수 없습니다.

이 솔루션은 Auth cookie가 유효한 한 CSRF 공격이 발생할 수 있기 때문에 안전하지 않습니다.공격자가 다른 사이트를 통해 요청을 수행하도록 요청하면 인증 쿠키와 xsrf 쿠키가 모두 서버로 전송되므로 사용자가 "하드" 로그아웃을 수행할 때까지 사용자는 여전히 취약합니다.

CRSF 공격을 진정으로 방지하려면 각 요구 또는 세션에 고유한 토큰을 설정해야 합니다.그러나 가장 좋은 해결책은 쿠키 기반 인증이 아니라 OAuth 등의 토큰 기반 인증을 사용하는 것입니다.그러면 토큰이 쿠키 대신 http 헤더에 사용되므로 다른 웹 사이트가 사용자의 쿠키를 사용하여 원하지 않는 요청을 수행하는 것을 방지할 수 있습니다.또한 http 헤더는 자동으로 전송되지 않습니다.

  1. ASP를 사용한 토큰 기반 인증.NET Web API 2, Owin 및 ID
  2. ASP를 사용한 AngularJS 토큰 인증NET Web API 2, Owin 및 ID

이러한 훌륭한 블로그 투고에는 WebAPI용 OAuth 구현 방법에 대한 정보가 포함되어 있습니다.블로그 투고에는 Angular와의 통합 방법에 대한 훌륭한 정보도 포함되어 있습니다.JS.

또 다른 해결책은 CORS를 사용하지 않도록 설정하고 화이트리스트 도메인으로부터의 수신 요구만 받아들이는 것입니다.단, 모바일 클라이언트나 데스크톱 클라이언트와 같은 웹 사이트 이외의 애플리케이션에서는 사용할 수 없습니다.그 다음 웹 사이트가 XSS 공격에 취약해지면 공격자는 사용자의 권한에 따라 요청을 위조할 수 있습니다.

네 코드에는 결함이 있는 것 같아.예방 CSRF에 관한 전체적인 생각은 세션이 아닌 각 REQUEST에서 하나의 토큰을 방지하는 것입니다.위조 방지 토큰이 세션 지속 값인 경우 CSRF를 실행하는 기능은 그대로 유지됩니다.각 요청에 고유한 토큰을 제공해야 합니다.

코드에 문제가 지적된 적이 없기 때문에 질문에 대답했다고 생각합니다.

언급URL : https://stackoverflow.com/questions/15574486/angular-against-asp-net-webapi-implement-csrf-on-the-server

반응형