Khi các nhà phát triển cần xử lý URL ở các dạng khác nhau cho các mục đích khác nhau — chẳng hạn như điều hướng lịch sử trình duyệt, mục tiêu được neo, tham số truy vấn, v.v. — chúng tôi thường chuyển sang JavaScript. Tuy nhiên, việc sử dụng thường xuyên của nó thúc đẩy những kẻ tấn công khai thác các lỗ hổng của nó. Nguy cơ khai thác này là lý do tại sao chúng tôi phải triển khai xác thực URL trong các ứng dụng JavaScript của mình
Xác thực URL kiểm tra xem các URL có tuân theo đúng cú pháp URL hay không — cấu trúc mà mọi URL phải có. Xác thực URL có thể lưu các ứng dụng của chúng tôi khỏi các lỗ hổng dựa trên URL như chèn tập lệnh độc hại và giả mạo yêu cầu phía máy chủ [SSRF]. Các tác nhân độc hại có thể sử dụng các cuộc tấn công SSRF khi chúng tôi không áp dụng các quy ước mã hóa an toàn để xác thực các URL do người dùng cung cấp khi tìm nạp tài nguyên từ xa. SSRF vẫn là một mối đe dọa nghiêm trọng đối với các ứng dụng dựa trên JavaScript, cho cả giao diện người dùng và Node. js và là một danh mục nổi bật trong danh sách Top 10 của OWASP vào năm 2021
xác thực URL
Xác thực URL tồn tại để tăng cường bảo mật chống lại các khai thác có thể xảy ra và loại bỏ khả năng xảy ra bất kỳ lỗi nào phát sinh trong khi chạy mã. Nhưng khi nào chúng ta nên sử dụng xác thực URL và chúng ta xác thực điều gì trong quá trình này? .
Một URL điển hình bao gồm nhiều đoạn, chẳng hạn như giao thức, tên miền, tên máy chủ, tên tài nguyên, nguồn gốc, cổng, v.v. Chúng cho trình duyệt biết cách truy xuất tài nguyên cụ thể. Chúng tôi có thể sử dụng chúng để xác thực URL theo nhiều cách
- Sử dụng chữ và hàm tạo Regex
- trình tạo URL
- phương pháp
0function checkUrl [string] { let givenURL ; try { givenURL = new URL [string]; } catch [error] { console.log ["error is", error]; return false; } return true; }
- yếu tố đầu vào
- Phương pháp thẻ neo
Lược đồ xác thực URL điển hình nhận đầu vào từ người dùng và sau đó phân tích cú pháp để xác định các thành phần khác nhau của nó. Lược đồ xác thực có thể đảm bảo rằng tất cả các thành phần URL đều tuân thủ các tiêu chuẩn internet. Ví dụ: nếu được yêu cầu, nó có thể kiểm tra xem URL có sử dụng giao thức bảo mật hay không.
Xác thực tên máy chủ bắt đầu bằng cách chia tên máy chủ thành các nhãn riêng biệt để đảm bảo chúng tuân thủ. Tên máy chủ điển hình bao gồm tối thiểu hai nhãn được phân tách bằng dấu chấm. Ví dụ:www. lén lút. com có nhãn “www,” “snyk,” và “com”. Mỗi nhãn chỉ có thể bao gồm một ký tự chữ và số hoặc dấu gạch nối, bất kể trường hợp của chúng. Sau đó, lược đồ xác thực có thể đảm bảo tên máy chủ khớp với danh sách các URL được phép để đảm bảo chỉ các URL được chỉ định mới được phép và các URL được phép không bị loại do nhầm lẫn
Theo mặc định, hầu hết các đường dẫn đến tài nguyên được sử dụng trong URL đều được phép. Tuy nhiên, các cổng chỉ có thể nằm trong khoảng từ 1 đến 65536. Bất cứ điều gì bên ngoài phạm vi đó sẽ gây ra lỗi. Chúng tôi cũng có thể kiểm tra địa chỉ IP bằng số để đánh giá xem đó là địa chỉ IPV4 hay địa chỉ IPV6
Cuối cùng, mặc dù ban đầu không rõ ràng, nhưng chúng tôi cũng có thể kiểm tra URL để biết tên người dùng và mật khẩu. Tính năng này giúp tuân thủ các chính sách của công ty và bảo vệ thông tin xác thực.
Bây giờ bạn đã có kiến thức cơ bản, hãy xem qua xác thực URL bằng javascript
Cách thực hiện xác thực URL trong JavaScript
Cách dễ nhất để thực hiện xác thực URL trong JavaScript là sử dụng hàm tạo
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
1. Ngoài sự đơn giản của nó, nó được hỗ trợ bởi Node. thời gian chạy js vàCú pháp cơ bản như sau
new URL [url]
new URL [url , base]
JavaScript chỉ yêu cầu phần tử
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2 nếu chúng tôi cung cấp một URL tương đối. Nếu chúng tôi không cung cấp, nó sẽ mặc định là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
3. Ngoài ra, nếu chúng tôi cung cấp một phần tử function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2 với một URL tuyệt đối, thì JavaScript sẽ bỏ qua phần tử function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2Để xác thực URL, có thể sử dụng chức năng sau
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
Hàm này kiểm tra tính hợp lệ của một URL — nó trả về true khi URL hợp lệ và sai khi không. Nếu bạn chuyển
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
6 cho chức năng này, nó sẽ trả về false vì nó không chứa lược đồ URL hợp lệ. Phiên bản chính xác của URL này là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
7. Một ví dụ khác là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
8. Đây là một URL hợp lệ, nhưng nếu bạn xóa dấu hai chấm, JavaScript sẽ không nhận ra đó là một URL nữa. Ví dụ thứ ba là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
9. Điều này không hợp lệ vì nó không chứa tên máy chủ. Nếu bạn thêm hai dấu chấm [function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
20], nó sẽ trở thành hợp lệ vì các dấu chấm sẽ được coi là tên máy chủ, theo cách này, function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
21 trở thành một URL hợp lệ. Điều quan trọng cần lưu ý là tồn tại các URL độc đáo nhưng hoàn toàn hợp lệ. Chúng có thể gây bất ngờ cho các nhà phát triển đang làm việc trên chúng, nhưng nếu không thì hoàn toàn phù hợp. Ví dụ: cả hai URL sau sẽ trả về TRUE
- URL mới [“youtube. //một. b. c. d”];
- URL mới [“a. //1. 2. 3. 4@1. 2. 3. 4"];
Những ví dụ này là một lời nhắc nhở rằng các nhà phát triển nên dựa vào các nguyên tắc xác thực URL, thay vì tập trung vào các quy ước
Nếu bạn muốn đảm bảo rằng URL hợp lệ có chứa lược đồ URL cụ thể, bạn có thể sử dụng chức năng sau
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2Hàm này xác thực URL, sau đó kiểm tra xem URL đó có đang sử dụng lược đồ HTTP hoặc HTTPS hay không. Ở đây,
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
21 sẽ không hợp lệ vì nó không chứa HTTP hoặc HTTPS, trong khi function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
23 vẫn hợp lệ. Một số cách khác để sử dụng hàm xây dựng
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
24 bao gồm. function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
8Ví dụ trên sử dụng phần tử
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2. Ghi nhật ký giá trị mang lại cho chúng tôi function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
26Để trả về một đối tượng URL mà không chỉ định tham số
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
2, cú pháp là new URL [url]
new URL [url , base]
2Để thêm tên đường dẫn vào host ta cấu trúc như sau
new URL [url]
new URL [url , base]
3URL được lưu trữ trong
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
28 là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
29Một chức năng khác của mô-đun URL là nó triển khai API URL WHATWG, tuân thủ tiêu chuẩn URL WHATWG mà các trình duyệt sử dụng
new URL [url]
new URL [url , base]
6Trong ví dụ trên, chúng tôi đã tạo một đối tượng URL có tên là
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
80. Sau đó, mã tìm nạp máy chủ lưu trữ và tên đường dẫn của URL — lần lượt là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
81 và function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
82. Cuối cùng, chúng tôi có thể so sánh URL với danh sách cho phép hoặc danh sách chặn để đảm bảo chỉ những URL được chỉ định mới được phép và các URL được phép không bị loại do nhầm lẫnCách xác thực URL bằng regex — mặc dù bạn không nên
Một cách khác để xác thực URL là sử dụng biểu thức chính quy [regex] — hoặc chuỗi tạo thành mẫu tìm kiếm. Chúng tôi có thể sử dụng Regex để kiểm tra xem URL có hợp lệ không
Cú pháp JavaScript để xác thực URL bằng regex là
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
0Để kiểm tra một số URL
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
1Cú pháp URL do regex xác định kiểm tra xem URL có bắt đầu bằng lược đồ
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
83 hoặc function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
84 hoặc tên miền phụ hay không và liệu URL đó có chứa tên miền hay không. Câu lệnh trên bảng điều khiển là function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
85 vì nó tuân theo cú pháp URL được xác định bởi biểu thức chính quy. Ngược lại, câu lệnh sau sẽ trả về giá trị function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
86 vì nó không bắt đầu với bất kỳ lược đồ được phép nào hoặc tên miền phụ, cũng như không chứa tên miền. function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
6Regex ở trên tương đối đơn giản nhưng vẫn khó điều hướng. Đây cũng là một cách tiếp cận dễ xảy ra lỗi vì biểu thức chính quy không thể xử lý đầy đủ các quy tắc để xác thực URL. Điều tốt nhất nó có thể làm là khớp với các URL hợp lệ. Hơn nữa, việc thực hiện kiểm tra xác thực trở nên tốn thời gian khi một biểu thức chính quy chứa logic xác thực phức tạp hoặc nhận một chuỗi đầu vào dài.
Để đáp ứng các kiểm tra xác thực regex đã xác định, trình duyệt phải quay lại theo thứ tự hàng triệu thông qua chuỗi đầu vào. Việc kiểm tra lại quá nhiều này có thể dẫn đến "việc kiểm tra ngược thảm khốc", một hiện tượng trong đó các biểu thức chính quy phức tạp có thể đóng băng trình duyệt hoặc làm quá tải các quy trình lõi của CPU
Các lỗ hổng và giải pháp trong thế giới thực
Nút. js là môi trường thời gian chạy JavaScript đa nền tảng, mã nguồn mở, miễn phí sử dụng trình quản lý gói có tên là Trình quản lý gói Node [npm].
Một sự kiện tương tự đã xảy ra vào năm 2019 khi một kẻ tấn công đã tự mình có được quyền truy cập trái phép vào dữ liệu từ Capital One, một trong những ngân hàng lớn nhất ở Hoa Kỳ. Vi phạm dữ liệu đó vẫn là một trong những vi phạm quan trọng nhất của thế kỷ. Theo The New York Times, kẻ tấn công đã có quyền truy cập vào 100 triệu hồ sơ khách hàng, 140.000 số An sinh xã hội và 80.000 chi tiết ngân hàng được liên kết của khách hàng Capital One.
Kẻ tấn công đã truy cập máy chủ Capital One do Amazon Web Services [AWS] lưu trữ. Việc phát hiện chậm trễ cho thấy rằng kẻ tấn công đã có kiến thức sâu rộng về cơ sở hạ tầng AWS và nhìn thấy lỗ hổng có thể khai thác trong Tường lửa ứng dụng web [WAF] của Nhà cung cấp dịch vụ bảo mật được quản lý [MODSEC]. Được trang bị kiến thức này, thủ phạm đã thực hiện cuộc tấn công SSRF và thực hiện các yêu cầu HTTP mới bằng cách thao túng máy chủ web dễ bị tổn thương — nhờ đó giành được quyền truy cập thành công vào dịch vụ siêu dữ liệu AWS.
Tùy thuộc vào yêu cầu của công ty, chúng tôi có thể tránh các cuộc tấn công SSRF bằng cách hạn chế hệ thống chỉ ở một vài giao thức, chẳng hạn như HTTP hoặc HTTPS. Để tăng cường bảo mật hơn, chúng ta phải thiết lập ứng dụng để nó không vượt qua tham số URL mà không có sự giám sát. Danh sách cho phép và từ chối thường được sử dụng để lọc và kiểm soát cơ chế, giúp giảm đáng kể xác suất SSRF. Cho phép danh sách cho phép ứng dụng sử dụng một loại đối tượng và máy chủ được xác định trước. Trong khi đó, danh sách từ chối hạn chế ứng dụng truy xuất tên máy chủ phổ biến
Sử dụng JavaScript một cách an toàn
Bằng chứng là việc bổ sung SSRF vào Top 10 OWASP mới, xác thực URL ngày càng trở nên quan trọng đối với bảo mật ứng dụng JavaScript. May mắn thay, chúng tôi có thể giúp giảm thiểu các cuộc tấn công như vậy bằng cách xác thực URL ở phía máy chủ. Ngoài ra, việc sử dụng hàm
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
24 mới theo các cách ưa thích để xác thực và làm việc với các URL có thể mang lại nhiều lợi ích. Sau khi xem một số trường hợp sử dụng chức năng mới của hàm
function checkUrl [string] {
let givenURL ;
try {
givenURL = new URL [string];
} catch [error] {
console.log ["error is", error];
return false;
}
return true;
}
24, chúng tôi đã học cách xác thực URL bằng biểu thức chính quy — và hiểu tại sao cách tiếp cận này cồng kềnh và dễ bị lỗi. Sau đó, chúng tôi đã kết thúc bằng một nghiên cứu điển hình về lỗ hổng SSRF JavaScript. Rủi ro bảo mật với các URL ít hơn về tính hợp lệ của chúng và nhiều hơn về các sơ đồ URL nguy hiểm. Như vậy, chúng ta cần đảm bảo rằng ứng dụng phía máy chủ thực hiện xác thực. Kẻ tấn công có thể bỏ qua cơ chế xác thực phía máy khách, vì vậy chỉ dựa vào đó không phải là cách tốt
Để tìm hiểu thêm về cách quản lý bảo mật ứng dụng của bạn, hãy truy cập Snyk ngay hôm nay.
Tìm và sửa các lỗ hổng JavaScript miễn phí
Tạo tài khoản Snyk ngay hôm nay để có các ứng dụng JavaScript an toàn và bảo mật
Đăng kí miễn phí
Thảo luận về blog này trên Discord
Tham gia Cộng đồng DevSecOps trên Discord để thảo luận về chủ đề này và hơn thế nữa với các học viên tập trung vào bảo mật khác