재우니의 블로그

 

 

 

더보기

 FATAL 2024-03-21 22:34:46,795 175921ms nErrorHandlerAttribute WriteLog - System.Web.HttpRequestValidationException (0x80004005): 클라이언트 (applySkill="...omment":"

 

textarea 에 xss 공격에 쉽게 가능한 html 및 script 언어가 들어가면 위와 같은 오류메시지가 나왔습니다. 이는 ASP.NET MVC에서 HTML 형태의 태그를 입력하고 저장할 때 발생하는 HttpRequestValidationException 오류는 기본적으로 ASP.NET MVC가 XSS(Cross-Site Scripting) 공격을 방지하기 위해 HTML 태그와 스크립트가 포함된 입력을 거부하기 때문입니다. 이 오류를 해결하려면, 서버 측에서 HTML 태그를 허용하도록 설정해야 합니다.

 

해결 방법은 여러가지가 존재합니다.

 

[AllowHtml] 속성 사용

 

특정 모델 속성에 대해서만 HTML 입력을 허용하고 싶다면, 해당 속성에 [AllowHtml] 어트리뷰트를 적용합니다.

 

public class YourViewModel
{
    public int Id { get; set; }

    [AllowHtml]
    public string YourHtmlContent { get; set; }
}

 

 

[ValidateInput(false)] 사용

 

특정 Action Method 전체에 대해 HTML 입력을 허용하려면, 해당 Action Method 에 [ValidateInput(false)] 어트리뷰트를 적용합니다. 이 방법은 보안상의 이유로 권장하지 않습니다. 

 

[HttpPost]
[ValidateInput(false)]
public ActionResult YourActionMethod(YourViewModel model)
{
    // 처리 로직
    return View();
}

 

 

Request.Unvalidated 사용

 

.NET 4.5 이상에서는 Request.Unvalidated 속성을 사용하여 검증되지 않은 원본 데이터에 접근할 수 있습니다. 이 방법 역시 보안 상의 이유로 주의하여 사용해야 합니다.

 

var unvalidatedData = Request.Unvalidated.Form["YourHtmlContent"];

 

 

개선된 접근 방법

 

HTML   형태의 데이터를 허용할 때는 XSS 공격에 더욱 주의해야 합니다. 사용자로부터 입력받은 HTML 데이터를 출력할 때는 항상 적절한 방법으로 콘텐츠를 escaping, sanitization 하여 안전하게 만들어야 합니다. 예를 들어, Microsoft AntiXSS 라이브러리나 HtmlSanitizer 같은 도구를 사용할 수 있습니다. 이러한 처리를 통해 위의 HttpRequestValidationException 오류를 해결하고, 보안상의 위험도 최소화할 수 있습니다.

 

 

보다 효과적인 접근법은 이미 잘 알려진 라이브러리를 사용하는 것입니다. Microsoft AntiXSS Library 또는 HtmlSanitizer 같은 라이브러리는 XSS 공격으로부터 보호하기 위해 특별히 설계되었습니다. 이러한 라이브러리들은 입력 데이터를 안전하게 처리하는 복잡한 로직을 이미 구현하고 있으며, 공격 패턴이 변화하고 새로운 취약점이 발견될 때마다 업데이트됩니다.

 

 

Microsoft AntiXSS Library 사용 예

 

Microsoft의 AntiXSS Library는 사용자 입력을 안전하게 처리하는 여러 메서드를 제공합니다. 예를 들어, Encoder.HtmlEncode 메서드를 사용하여 HTML 코드를 안전하게 인코딩할 수 있습니다.

 

using Microsoft.Security.Application;

string sanitizedInput = Encoder.HtmlEncode(inputParameter);

 

 

HtmlSanitizer 사용

 

HtmlSanitizer는 HTML 내용을 제거하는 데 사용할 수 있는 또 다른 강력한 라이브러리입니다. 이 라이브러리를 사용하면 특정 태그, 속성, CSS 클래스 등을 허용하거나 차단하는 세부적인 제어가 가능합니다.

 

아래 유틸리티 함수는 입력된 HTML 콘텐츠에서 XSS 공격에 사용될 수 있는 요소를 제거하고, 특정 태그(p), 속성(class), CSS 속성(color)만을 허용하여 정제된 보안에 안전한 HTML을 반환합니다.

using HtmlSanitizer;

public static class SanitizerUtility
{
    public static string SanitizeHtml(string htmlContent)
    {
        var sanitizer = new HtmlSanitizer();

        // 필요에 따라 허용할 태그, 속성, CSS 속성을 설정할 수 있습니다.
        sanitizer.AllowedTags.Add("p");
        sanitizer.AllowedAttributes.Add("class");
        sanitizer.AllowedCssProperties.Add("color");

        // XSS 공격에 취약한 태그나 속성, 스크립트 등이 제거된 안전한 HTML 콘텐츠 반환
        return sanitizer.Sanitize(htmlContent);
    }
}

 

사용자 입력에 대한 처리는 보안상 중요한 요소입니다. 자체적으로 문자열 치환 로직을 구현하는 대신, 검증된 라이브러리를 활용하는 것이 보다 안전하고 효과적인 접근 방법입니다. 이러한 라이브러리들은 공격 패턴을 지속적으로 모니터링하고 업데이트하여 보다 나은 보호를 제공합니다.

 

 

XSS 처리 샘플 예제

 

다음은 SanitizeHtml 함수를 사용하여 XSS 공격 시도를 포함한 HTML 콘텐츠를 정제하는 예제입니다. 아래 예제에서 unsafeHtml 문자열은 스크립트 태그를 포함하여 XSS 공격을 시도할 수 있는 요소를 포함하고 있습니다. SanitizeHtml 함수를 사용하여 이 입력 콘텐츠를 처리하면, XSS 공격에 사용될 수 있는 <script> 태그와 javascript: 프로토콜을 포함한 <img> 태그가 제거되고, 설정에 따라 허용된 요소만을 포함한 안전한 HTML 콘텐츠가 반환됩니다. 위의 유틸리티 함수와 샘플 예제를 통해, HtmlSanitizer 라이브러리를 사용하여 XSS 공격으로부터 보호하고 안전한 웹 애플리케이션을 구현하는 방법을 확인할 수 있습니다.

 

class Program
{
    static void Main(string[] args)
    {
        string unsafeHtml = @"
            <script>alert('XSS Attack!');</script>
            <p class='text'>안전한 <b>HTML</b> 콘텐츠입니다.</p>
            <img src='javascript:alert(\"XSS\");'>
            <p style='color: red;'>스타일 속성이 포함된 텍스트입니다.</p>";

        string safeHtml = SanitizerUtility.SanitizeHtml(unsafeHtml);

        Console.WriteLine(safeHtml);
    }
}

 

 

XSS 공격 테스트

 

XSS(Cross-Site Scripting) 공격은 다양한 방식으로 이루어질 수 있으며, 공격자들은 여러 창의적인 방법을 사용하여 보안 메커니즘을 우회하려고 시도합니다. 다음은 몇 가지 보다 다양한 XSS 공격 시도 예제를 포함한 unsafeHtml 샘플입니다. 이 예제들은 HtmlSanitizer를 사용하여 살균 처리할 수 있는 다양한 공격 시나리오를 보여줍니다.

 

 

string unsafeHtml = @"
    <script>alert('XSS');</script>
    <img src='javascript:alert(\"XSS\")'>
    <a href='javascript:alert(\"XSS\")'>클릭하세요!</a>
    <a href='#' onclick='alert(\"XSS\")'>링크</a>
    <iframe src='javascript:alert(\"XSS\");'></iframe>
    <form action='javascript:alert(\"XSS\")'><input type='submit'></form>
    <input type='text' value='' onfocus='alert(\"XSS\")'>
    <div style='background-color: red;' onmouseover='alert(\"XSS\")'>마우스를 올려보세요</div>
    <svg/onload=alert('XSS')>
    <object data='javascript:alert(\"XSS\")'></object>
    <!-- HTML5 새로운 태그들도 공격에 사용될 수 있습니다 -->
    <audio src='audio.ogg' onplay='alert(\"XSS\")'></audio>
    <video src='video.mp4' onplay='alert(\"XSS\")'></video>
    <body onload=alert('XSS')>
    <!-- 더욱 정교한 공격에서는 인코딩을 사용하여 감지를 회피할 수 있습니다 -->
    <script>eval(atob('YWxlcnQoIlhTUyIp'))</script>
    <!-- CSS를 이용한 공격 -->
    <style>@import 'javascript:alert(\"XSS\")';</style>
    <!-- 데이터 바인딩을 이용한 공격 -->
    <div data-bind='text: alert(\"XSS\")'></div>
".Trim();

 

 

위의 예제들은 HtmlSanitizer를 사용하여 정제 처리할 때 제거되어야 하는 다양한 XSS 공격 시도들을 보여줍니다. 이러한 공격 시도들은 <script> 태그의 직접적인 사용, 이벤트 핸들러(onclick, onmouseover 등)를 통한 자바스크립트 실행, javascript: 프로토콜의 사용, HTML5 태그의 속성을 이용한 공격, 인코딩을 사용한 우회 시도, CSS를 통한 공격 등 다양한 방법을 포함합니다. HtmlSanitizer와 같은 도구는 이러한 공격 시도 중 많은 부분을 자동으로 차단할 수 있도록 도와주지만, 완벽한 보안을 위해서는 항상 최신의 보안 패치와 업데이트를 적용하고, 사용자 입력에 대한 검증과 정제 처리를 철저히 하는 것이 중요합니다. 또한, 보안에 대한 지속적인 교육과 공격 패턴에 대한 이해를 바탕으로 시스템을 설계하고 개발해야 합니다.

 

 

 

 

사용자가 <> 을 사용하고자 할 경우, 다른 문자열로 치환해서 보관하는게 좋다. 

 

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue.js Example</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2"></script>
</head>
<body>
<div id="app">
    <textarea v-model="userInput" placeholder="여기에 입력하세요..."></textarea>
    <div>
        <h3>입력 내용:</h3>
        <p>{{ sanitizedInput }}</p>
    </div>
</div>

<script>
new Vue({
    el: '#app',
    data: {
        userInput: ''
    },
    computed: {
        sanitizedInput: function() {
            return this.userInput
                .replace(/</g, "〈")
                .replace(/>/g, "〉");
        }
    }
});
</script>
</body>
</html>