Javascript tạo nonce ngẫu nhiên

Có nhiều cách không an toàn để liệt kê danh sách trắng các thẻ tập lệnh nội tuyến, trình xử lý sự kiện nội tuyến, thẻ kiểu nội tuyến và kiểu nội tuyến, nhưng tôi sẽ không nói về chúng vì chúng không an toàn và phá vỡ toàn bộ quan điểm của CSP

Đặt CSP trong Nút. js

Để xác định tài nguyên được phép trong CSP thông qua Nút. js, chúng ta phải khai báo chúng dưới dạng tiêu đề phản hồi

  1. Người dùng đưa ra yêu cầu
  2. Máy chủ gửi phản hồi
  3. Trình duyệt tải trang cùng với các tài nguyên được phép

CSP nằm trong tiêu đề phản hồi và nơi trình duyệt sẽ xem để biết anh ta có thể hiển thị những gì

Sử dụng Express, chúng ta chỉ cần làm như sau

// /index.js

const express = require("express")
const app = express()

// Set CSP as a middleware function
app.use(function (req, res, next) {
    res.setHeader(
        "Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
    )

    next()
})

app.get("/", (req, res) => {
    res.send("Hello World!")
})

app.listen(3000, () => {
    console.log(`App 🚀 @ http://localhost:3000`)
})

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Như bạn có thể thấy, chúng tôi đã xác định các lệnh được sử dụng nhiều nhất cho

// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
4, nghĩa là chúng tôi chỉ cho phép các tài nguyên từ máy chủ hiện tại (bao gồm lược đồ URL và số cổng) mà thôi.

Nếu bạn chạy ứng dụng này (
// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
5) và theo liên kết, bạn sẽ nhận được một Hello World đẹp mắt

Nếu bạn mở Bảng điều khiển (F12), bạn sẽ không thấy gì vì hiện tại chúng tôi chưa làm gì nhiều

EJS

Để hiển thị trang

// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
6, hãy tải các tập lệnh và kiểu bên ngoài để kiểm tra CSP của chúng tôi, tôi sẽ sử dụng EJS

Vui lòng sử dụng bất kỳ công cụ mẫu nào khác phù hợp với nhu cầu của bạn

Tôi đánh giá cao EJS vì lý do sau

EJS là một ngôn ngữ tạo khuôn mẫu đơn giản cho phép bạn tạo đánh dấu HTML bằng JavaScript đơn giản

Sau khi cài đặt EJS (

// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
7), chúng ta sẽ phải tạo một thư mục
// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
8, ở thư mục gốc của ứng dụng, để lưu trữ các tệp
// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
9

EJS sẽ xem bên trong thư mục này để
document.getElementById("my-div").setAttribute("style", "background-color:red;")
0 (các) trang của bạn theo cách bạn hướng dẫn anh ấy thực hiện
Trong thư mục này, tạo một tệp tên là
document.getElementById("my-div").setAttribute("style", "background-color:red;")
1 với nội dung sau




 lang="en">
    
         charset="UTF-8" />
         http-equiv="X-UA-Compatible" content="IE=edge" />
         name="viewport" content="width=device-width, initial-scale=1.0" />
        </span>Document<span>
    
    
        

Hello from EJS !

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Có, tệp

// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
9 là tệp
// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
6 trong đó chúng tôi có thể sử dụng
document.getElementById("my-div").setAttribute("style", "background-color:red;")
4 đơn giản, chúng tôi sẽ thấy điều đó trong giây lát

Cập nhật tệp máy chủ chính của chúng tôi để trông như thế này

// /index.js

const express = require("express")
const app = express()

// Set CSP as a middleware function
app.use(function (req, res, next) {
    res.setHeader(
        "Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
    )

    next()
})

// Set EJS as a template engine
app.set("view engine", "ejs")

// Use EJS to render our page(s)
app.get("/", (req, res) => {
    res.render("index") // renders index.ejs
})

app.listen(3000, () => {
    console.log(`App 🚀 @ http://localhost:3000`)
})

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

nguồn lực bên ngoài

Bây giờ, để kiểm tra CSP của chúng tôi, chúng tôi chỉ cần tải một số tài nguyên bên ngoài

Hãy mang về Pure. css và Lodash
Cập nhật

document.getElementById("my-div").setAttribute("style", "background-color:red;")
1 để trông như thế này




 lang="en">
    
         charset="UTF-8" />
         http-equiv="X-UA-Compatible" content="IE=edge" />
         name="viewport" content="width=device-width, initial-scale=1.0" />
        </span>Document<span>
        
        
            rel="stylesheet"
            href="https://unpkg.com/[email protected]/build/pure-min.css"
            integrity="sha384-yHIFVG6ClnONEA5yB5DJXfW2/KC173DIQrYoZMEtBvGzmf0PKiGyNEqe9N6BNDBH"
            crossorigin="anonymous"
        />
    
    
        

Hello from EJS !

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Lưu

document.getElementById("my-div").setAttribute("style", "background-color:red;")
1, tải lại ứng dụng trong trình duyệt và mở Bảng điều khiển

// Firefox Console
⚠️ Loading failed for the <script> with source https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js”.
🛑 Content Security Policy: The pages settings blocked the loading of a resource at https://unpkg.com/[email protected]/build/pure-min.css (“style-src”).
🛑 Content Security Policy: The pages settings blocked the loading of a resource at https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js (“script-src”).

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

 id="btn" onclick="doSomething()">
0

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Bây giờ, bạn có thể thấy rằng CSP của chúng tôi đã chặn Pure. css và Lodash, vì vậy mọi thứ đang hoạt động như mong đợi vì chúng không được định nghĩa trong CSP của chúng tôi là tài nguyên được phép tải trong trình duyệt

Mũ bảo hiểm

Hãy tưởng tượng, không nhất thiết là vì nó xảy ra khi bạn đang tạo một ứng dụng, có một số lượng tập lệnh và kiểu hợp lý để đưa vào danh sách trắng

Chức năng phần mềm trung gian CSP trong tệp máy chủ chính sẽ phát triển và trở nên xấu xí và khó bảo trì

Một giải pháp thay thế tuyệt vời là sử dụng Mũ bảo hiểm nếu bạn đang sử dụng Express

Mũ bảo hiểm giúp bạn bảo mật các ứng dụng Express của mình bằng cách đặt các tiêu đề HTTP khác nhau

Hãy thêm Mũ bảo hiểm vào ứng dụng Express của chúng tôi bằng lệnh sau

document.getElementById("my-div").setAttribute("style", "background-color:red;")
7

Để dễ dàng duy trì CSP của chúng ta, hãy di chuyển nó vào trong thư mục
document.getElementById("my-div").setAttribute("style", "background-color:red;")
8, thư mục gốc của ứng dụng, trong một tệp có tên
document.getElementById("my-div").setAttribute("style", "background-color:red;")
9

Cấu trúc ứng dụng trông giống như cây sau

 id="btn" onclick="doSomething()">
1

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Hãy thêm một CSP với Mũ bảo hiểm

 id="btn" onclick="doSomething()">
2

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

và cập nhật

document.getElementById("my-div").style.backgroundColor = "red"
0 để gọi phần mềm trung gian này

 id="btn" onclick="doSomething()">
3

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Lưu cả hai tệp, làm mới trình duyệt của bạn và mở Bảng điều khiển

 id="btn" onclick="doSomething()">
4

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

 id="btn" onclick="doSomething()">
5

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Như bạn có thể thấy, hiện chỉ có Lodash bị chặn 🤔
Và Firefox đang đưa ra cảnh báo cho một chỉ thị không xác định

Về cơ bản, có rất nhiều điều đang xảy ra và sẽ có một loạt bài đăng để giải thích chi tiết từng tiêu đề và cách định cấu hình chúng

Nhưng bạn biết đấy, Mũ bảo hiểm đặt một loạt các giá trị mặc định để bảo vệ điểm cuối của bạn
một trong số đó là

document.getElementById("my-div").style.backgroundColor = "red"
1
Đây là chỉ thị cho phép Pure. css
Nó có nghĩa là. "cho phép bất kỳ nguồn kiểu nào từ miền của tôi hoặc nguồn kiểu được cung cấp qua https hoặc kiểu nội tuyến"
Nhưng như tôi đã nói trước đây, bất kỳ biểu thức
document.getElementById("my-div").style.backgroundColor = "red"
2 nào đều không an toàn và không nên được sử dụng trừ khi chúng thực sự không còn lựa chọn nào khác

Tôi đã liên kết ở phần đầu của phần này với tài liệu của Mũ bảo hiểm
Chúng tôi sẽ giải quyết tất cả các vấn đề một cách chính xác trong phần tiếp theo và phần cuối cùng

Hash và Nonce

Để cho phép thực thi tập lệnh nội tuyến, trình xử lý sự kiện nội tuyến và kiểu nội tuyến, có thể chỉ định một hàm băm hoặc nonce khớp với mã nội tuyến, để tránh sử dụng biểu thức

document.getElementById("my-div").style.backgroundColor = "red"
3

Băm


Băm là một chuỗi bao gồm hai phần được kết nối bằng dấu gạch ngang với nhau

  1. Thuật toán mật mã được sử dụng để tạo giá trị băm
  2. Hàm băm được mã hóa base64 của tập lệnh hoặc kiểu

CSP hỗ trợ sha256, sha384 và sha512

Nhưng khi bạn băm một tập lệnh hoặc một kiểu, chuỗi được tạo chỉ khớp với mã được băm, nghĩa là nếu mã thay đổi theo bất kỳ cách nào (dấu chấm, dấu cách, dòng mới, nhận xét, mã được thêm/xóa/định dạng) thì hàm băm sẽ không

Trong trường hợp này, bạn sẽ phải tạo lại một hàm băm phù hợp với mã đã sửa đổi

Đó là một quá trình tốn thời gian nếu mã của bạn thay đổi nhiều, nhưng thường được sử dụng và khuyên dùng hơn một lần, đặc biệt đối với các tập lệnh tĩnh

từ MDN

Ghi chú. Chỉ sử dụng nonce cho các trường hợp bạn không có cách nào khác bằng cách sử dụng nội dung kiểu hoặc tập lệnh nội tuyến không an toàn. Nếu bạn không cần nonce, đừng sử dụng nó. Nếu tập lệnh của bạn là tĩnh, bạn cũng có thể sử dụng hàm băm CSP để thay thế. (Xem ghi chú sử dụng trên. ) Luôn cố gắng tận dụng tối đa các biện pháp bảo vệ CSP và tránh các nonce hoặc tập lệnh nội tuyến không an toàn bất cứ khi nào có thể

nonce


Mặt khác, nonce là số mật mã được sử dụng một lần, được tạo bằng trình tạo số ngẫu nhiên bảo mật bằng mật mã, phải là duy nhất cho mỗi phản hồi HTTP dưới dạng chuỗi mã hóa base64 ngẫu nhiên gồm ít nhất 128 bit dữ liệu

Vì vậy, trong trường hợp kết xuất phía máy chủ, một nonce thường được sử dụng hơn và có thể được sử dụng cho các tập lệnh và kiểu nội tuyến và bên ngoài

Lưu ý rằng một

document.getElementById("my-div").style.backgroundColor = "red"
4 sẽ không cho phép các yêu cầu biểu định kiểu bắt nguồn từ quy tắc
document.getElementById("my-div").style.backgroundColor = "red"
5

Để sử dụng một nonce, cho một tập lệnh, chúng ta phải khai báo ở đầu chỉ thị

// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
1 biểu thức
document.getElementById("my-div").style.backgroundColor = "red"
7 để cho phép thực thi tập lệnh đó cũng như bất kỳ tập lệnh nào được tải bởi tập lệnh gốc này

Khi sử dụng biểu thức
document.getElementById("my-div").style.backgroundColor = "red"
7, các biểu thức khác như
// Inline style tag gets ignored


// Inline style attribute gets also ignored
 id="my-div" style="background-color:red">I will not have a red background !
4 hoặc
document.getElementById("my-div").style.backgroundColor = "red"
3 sẽ bị bỏ qua

Tôi muốn giữ cho mã của mình sạch sẽ và có thể bảo trì được vì lúc này hay lúc khác tôi sẽ muốn cập nhật mã, đây là lý do tại sao tôi chia (như hầu hết các nhà phát triển) mã của mình thành các phần để mỗi phần có thể dễ dàng theo dõi trong tương lai gần hoặc xa.
Hãy thêm một tệp có tên là

// /index.js

const express = require("express")
const app = express()

// Set CSP as a middleware function
app.use(function (req, res, next) {
    res.setHeader(
        "Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
    )

    next()
})

app.get("/", (req, res) => {
    res.send("Hello World!")
})

app.listen(3000, () => {
    console.log(`App 🚀 @ http://localhost:3000`)
})
1 vào thư mục
document.getElementById("my-div").setAttribute("style", "background-color:red;")
8, cấu trúc ứng dụng bây giờ trông giống như cái cây sau

 id="btn" onclick="doSomething()">
6

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Mở

// /index.js

const express = require("express")
const app = express()

// Set CSP as a middleware function
app.use(function (req, res, next) {
    res.setHeader(
        "Content-Security-Policy",
        "default-src 'self'; script-src 'self'; style-src 'self'; font-src 'self'; img-src 'self'; frame-src 'self'"
    )

    next()
})

app.get("/", (req, res) => {
    res.send("Hello World!")
})

app.listen(3000, () => {
    console.log(`App 🚀 @ http://localhost:3000`)
})
1 và thêm nội dung sau

 id="btn" onclick="doSomething()">
7

Vào chế độ toàn màn hình Thoát chế độ toàn màn hình

Mô-đun tiền điện tử là chức năng tích hợp sẵn của Node. js nhưng tốt hơn hết là kiểm tra xem nó có được bao gồm hay không, trong bản cài đặt của chúng tôi, giống như tài liệu

Làm cách nào để tạo nonce ngẫu nhiên trong JavaScript?

Trước tiên, chúng tôi xác định một chuỗi gồm tất cả các ký tự được phép trong chuỗi ngẫu nhiên cuối cùng của chúng tôi. Sau đó, chúng tôi lặp lại cho đến khi có độ dài nhất định sẽ đại diện cho kích thước chuỗi. Trong vòng lặp này, chúng ta sẽ xem xét chuỗi ký tự được phép dưới dạng một loại mảng (từng ký tự một) và chọn ngẫu nhiên một chỉ mục của mảng

Nonce trong Javascript là gì?

Thuộc tính toàn cục nonce là một thuộc tính nội dung xác định một nonce mật mã ("số được sử dụng một lần") có thể được Chính sách bảo mật nội dung sử dụng để xác định xem một lần tìm nạp nhất định có được phép tiến hành cho một phần tử nhất định hay không

Làm cách nào để tạo tên ngẫu nhiên trong JavaScript?

Mảng. áp dụng (null, Mảng (N)). bản đồ (hàm () { return s. charAt(Toán. tầng (Toán. ngẫu nhiên() * s. chiều dài)); . tham gia(''); .
Toán học. ngẫu nhiên(). toString(36). lát(-5); . ngẫu nhiên() trả về 0. 0?.
@ x-ray, bạn sẽ nhận được "0";).
Chính xác. ;)

Làm cách nào để lấy chuỗi ngẫu nhiên từ mảng trong JavaScript?

Ví dụ. Lấy mục ngẫu nhiên từ một mảng .
Một số ngẫu nhiên từ 0 đến mảng. chiều dài được tạo bằng Math. phương pháp ngẫu nhiên ()
Toán học. floor() trả về giá trị số nguyên gần nhất được tạo bởi Math. ngẫu nhiên()
Chỉ mục ngẫu nhiên này sau đó được sử dụng để truy cập một phần tử mảng ngẫu nhiên