iT邦幫忙

2022 iThome 鐵人賽

DAY 17
1
Software Development

ASP.NET Core 30 天旅程系列 第 17

[Day17]-防止跨網站腳本 (XSS) 攻擊

  • 分享至 

  • xImage
  •  

跨網站腳本 (XSS) 是安全性弱點,可讓攻擊者將用戶端腳本 (通常是 JavaScript) 放在網頁中。 當其他使用者載入受影響的頁面時,攻擊者的腳本將會執行、讓攻擊者竊取 cookie 和 session、透過 DOM 操作變更網頁的內容,或將瀏覽器重新導向至另一個頁面。 XSS 弱點容易發生在應用程式不驗證、編碼使用者的輸入並將它輸出到頁面時。

防止 XSS

  • 除非您遵循下列步驟的其餘部分,否則請勿將不受信任的資料放入您的 HTML 輸入中。 不受信任的資料是指HTML 表單輸入、查詢字串、HTTP 標頭,甚至是從資料庫取得的資料,攻擊者可能控制任何資料,即使它們無法入侵您的應用程式也一樣會受到攻擊。

  • 在 HTML 元素內放置不受信任的資料之前,請確定它是 HTML 編碼。 HTML 編碼會採用 < 之類的字元,並將其變更為安全形式,例如 &lt;

  • 將不受信任的資料放入 HTML 屬性之前,請確定它是 HTML 編碼。 HTML 屬性編碼是 HTML 編碼的超集合,並編碼其他字元,例如 "'

  • 將不受信任的資料放入 JavaScript 之前,請將資料放在您在執行時間擷取其內容的 HTML 元素中。 如果無法這樣做,請確定資料已編碼為 JavaScript。 JavaScript 編碼會採用 JavaScript 的危險字元,並以十六進位取代它們,例如 < 會編碼為 \u003C

  • 將不受信任的資料放入 URL 查詢字串之前,請確定其已編碼 URL。

使用 HTML 編碼

RazorMVC 中會自動編碼所有從變數來源的輸出。 每當您使用 @ 時, @ 它會使用 HTML 屬性編碼規則。

@{
    var untrustedInput = "<\"123\">";
}

@untrustedInput

此範例輸出 untrustedInput 變數的內容。 此變數包含 XSS 攻擊中使用的一些字元 <> 。會顯示編碼為:

&lt;&quot;123&quot;&gt;

注意
ASP.NET Core MVC 提供 HtmlString 不會在輸出時自動編碼的類別。 這不應該跟不受信任的輸入搭配使用,因為這樣會造成 XSS 弱點。

使用 JavaScript 編碼

有時候您可能會想要將值插入 JavaScript 中,在 Views 處理。 做法有二種,插入值的最安全方式是將值放在標記的資料屬性中,並將其擷取到您的 JavaScript 中。 例如:

@{
    var untrustedInput = "<script>alert(1)</script>";
}

<div id="injectedData" data-untrustedinput="@untrustedInput" /> 
//這邊產生html後 @untrustedInput 會變成 &lt;script&gt;alert(1)&lt;/script&gt;

<div id="scriptedWrite" />
<div id="scriptedWrite-html5" />

<script>
    var injectedData = document.getElementById("injectedData");

    // All clients
    var clientSideUntrustedInputOldStyle =
        injectedData.getAttribute("data-untrustedinput");

    // HTML 5 clients only
    var clientSideUntrustedInputHtml5 =
        injectedData.dataset.untrustedinput;

    // 將注入的、不受信任的數據放入 `scriptedWrite` `div` 標籤中。
    // 不要在動態生成的數據上使用 `document.write()`,因為它會導致 xss

    document.getElementById("scriptedWrite").innerText += clientSideUntrustedInputOldStyle;

    // 或者您可以使用 `createElement()` 動態創建 element
    // 這次我們使用 `textContent` 來確保數據被正確編碼。
    var x = document.createElement("div");
    x.textContent = clientSideUntrustedInputHtml5;
    document.body.appendChild(x);

    // 也可以在元素上使用 `createTextNode` 以確保正確編碼數據。
    var y = document.createElement("div");
    y.appendChild(document.createTextNode(clientSideUntrustedInputHtml5));
    document.body.appendChild(y);

</script>

注意
請勿在 JavaScript 中串連不受信任的輸入,以建立 DOM 元素,不要在動態生成的數據上使用 document.write(),因為會導致 XSS。

使用下列其中一種方法來防止程式碼公開至 DOM 型 XSS:
createElement() 並使用適當的方法或屬性指派屬性值,例如 node.textContent= 或 node.InnerText= 。
document.CreateTextNode() 並將它附加到適當的 DOM 位置。
element.SetAttribute()
element[attribute]=

程式碼中的編碼器

HTML、JavaScript 和 URL 編碼器有兩種方式可供您的程式碼使用,您可以透過 DI 或使用命名空間中using System.Text.Encodings.Web

public class HomeController : Controller
{
    HtmlEncoder _htmlEncoder;
    JavaScriptEncoder _javaScriptEncoder;
    UrlEncoder _urlEncoder;

    public HomeController(HtmlEncoder htmlEncoder,
                          JavaScriptEncoder javascriptEncoder,
                          UrlEncoder urlEncoder)
    {
        _htmlEncoder = htmlEncoder;
        _javaScriptEncoder = javascriptEncoder;
        _urlEncoder = urlEncoder;
    }
}

透過使用編碼器,可以將不信任的資料,轉換成安全的格式。

var html = _htmlEncoder.Encode(exampleString);
var js = _javaScriptEncoder.Encode(exampleString);
var url = _urlEncoder.Encode(exampleString);

編碼 URL 參數

使用 UrlEncoder 來編碼

var example = "\"Quoted Value with spaces and &\"";
var encodedValue = _urlEncoder.Encode(example);

編碼之後,encodedValue 會變成 %22Quoted%20Value%20with%20spaces%20and%20%26%22 。 空格、引號、標點符號和其他不安全字元將百分比編碼為其十六進位值,例如空白字元會變成 %20。


參考資料

Prevent Cross-Site Scripting (XSS) in ASP.NET Core


上一篇
[Day16]- .NET Core 授權
下一篇
[Day18]-防止跨網站偽造要求 (XSRF/CSRF) 攻擊
系列文
ASP.NET Core 30 天旅程30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言