Bởi Alex Nadalin
Giới thiệu về bảo mật ứng dụng web
_Ảnh của [Unsplash](https://unsplash.com/photos/cVMaxt672ss?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText" rel="noopener" target="_blank" title="">Liam Tucker trên
Bạn có thể quen làm việc với một trong những trình duyệt phổ biến nhất như Chrome, Firefox, Edge hoặc Safari, nhưng điều đó không có nghĩa là không có các trình duyệt khác nhau.
Ví dụ:lynx là một trình duyệt dựa trên văn bản nhẹ, hoạt động từ dòng lệnh của bạn. Trọng tâm của lynx nằm ở những nguyên tắc chính xác giống như bạn tìm thấy trong bất kỳ trình duyệt “chính thống” nào khác. Người dùng nhập địa chỉ web (URL), trình duyệt sẽ tìm nạp tài liệu và hiển thị nó — điểm khác biệt duy nhất là lynx không sử dụng công cụ hiển thị trực quan mà sử dụng giao diện dựa trên văn bản, khiến các trang web như Google trông như thế này:

Chúng tôi hiểu rộng rãi chức năng của trình duyệt nhưng hãy cùng xem xét kỹ hơn các bước mà ứng dụng khéo léo này thực hiện cho chúng ta.
Trình duyệt có chức năng gì?
Tóm lại, công việc của trình duyệt chủ yếu bao gồm:
- Độ phân giải DNS
- Trao đổi HTTP
- Kết xuất
- Rửa sạch và lặp lại
Độ phân giải DNS
Quá trình này đảm bảo rằng khi người dùng nhập URL, trình duyệt sẽ biết nó phải kết nối với máy chủ nào. Trình duyệt liên hệ với máy chủ DNS để tìm google.com đó dịch sang 216.58.207.110 , một địa chỉ IP mà trình duyệt có thể kết nối tới.
Trao đổi HTTP
Sau khi trình duyệt đã xác định được máy chủ nào sẽ phân phát yêu cầu của chúng ta, trình duyệt sẽ bắt đầu kết nối TCP với máy chủ đó và bắt đầu trao đổi HTTP . Đây không gì khác hơn là một cách để trình duyệt liên lạc với máy chủ những gì nó cần và để máy chủ phản hồi lại.
HTTP đơn giản là tên của giao thức phổ biến nhất để giao tiếp trên web và các trình duyệt chủ yếu giao tiếp qua HTTP khi giao tiếp với máy chủ. Trao đổi HTTP liên quan đến việc khách hàng (trình duyệt của chúng tôi) gửi yêu cầu và máy chủ phản hồi lại bằng phản hồi .
Ví dụ:sau khi trình duyệt kết nối thành công với máy chủ phía sau google.com , nó sẽ gửi một yêu cầu có dạng như sau:
GET / HTTP/1.1Host: google.comAccept: */*
Hãy chia nhỏ yêu cầu ra từng dòng một:
GET / HTTP/1.1:với dòng đầu tiên này, trình duyệt sẽ yêu cầu máy chủ lấy tài liệu tại vị trí/, thêm rằng phần còn lại của yêu cầu sẽ tuân theo giao thức HTTP/1.1 (nó cũng có thể sử dụng1.0hoặc2)Host: google.com:đây là tiêu đề HTTP duy nhất bắt buộc trong HTTP/1.1 . Vì máy chủ có thể phục vụ nhiều miền (google.com,google.co.uk, v.v.) khách hàng ở đây đề cập rằng yêu cầu dành cho máy chủ cụ thể đóAccept: */*:một tiêu đề tùy chọn, trong đó trình duyệt thông báo cho máy chủ rằng nó sẽ chấp nhận bất kỳ loại phản hồi nào. Máy chủ có thể có sẵn tài nguyên ở định dạng JSON, XML hoặc HTML, do đó, máy chủ có thể chọn bất kỳ định dạng nào nó thích
Sau trình duyệt, hoạt động như một ứng dụng khách , được thực hiện với yêu cầu của nó, đến lượt máy chủ trả lời lại. Phản hồi trông như thế này:
HTTP/1.1 200 OKCache-Control: private, max-age=0Content-Type: text/html; charset=ISO-8859-1Server: gwsX-XSS-Protection: 1; mode=blockX-Frame-Options: SAMEORIGINSet-Cookie: NID=1234; expires=Fri, 18-Jan-2019 18:25:04 GMT; path=/; domain=.google.com; HttpOnly
<!doctype html><html">......</html>
Wow, có rất nhiều thông tin cần tiêu hóa. Máy chủ cho chúng tôi biết rằng yêu cầu đã thành công (200 OK ) và thêm một vài tiêu đề vào phản hồi , ví dụ:nó quảng cáo máy chủ nào đã xử lý yêu cầu của chúng tôi (Server: gws ), X-XSS-Protection là gì chính sách của phản hồi này, v.v.
Hiện tại, bạn không cần phải hiểu từng dòng trong câu trả lời. Chúng tôi sẽ đề cập đến giao thức HTTP, các tiêu đề của nó, v.v. ở phần sau của loạt bài này.
Hiện tại, tất cả những gì bạn cần hiểu là máy khách và máy chủ đang trao đổi thông tin và họ thực hiện việc đó thông qua HTTP.
Kết xuất
Cuối cùng nhưng không kém phần quan trọng là kết xuất quá trình. Một trình duyệt sẽ tốt đến mức nào nếu thứ duy nhất nó hiển thị cho người dùng là danh sách các nhân vật hài hước?
<!doctype html><html">......</html>
Trong cơ thể của phản hồi, máy chủ bao gồm việc thể hiện phản hồi theo Content-Type tiêu đề. Trong trường hợp của chúng tôi, loại nội dung được đặt thành text/html , vì vậy chúng tôi mong đợi đánh dấu HTML trong phản hồi — đó chính xác là những gì chúng tôi tìm thấy trong nội dung.
Đây là nơi trình duyệt thực sự tỏa sáng. Nó phân tích cú pháp HTML, tải các tài nguyên bổ sung có trong đánh dấu (ví dụ:có thể có tệp JavaScript hoặc tài liệu CSS để tìm nạp) và hiển thị chúng cho người dùng càng sớm càng tốt.
Một lần nữa, kết quả cuối cùng là điều mà một Joe bình thường có thể hiểu được.

Để có phiên bản chi tiết hơn về những gì thực sự xảy ra khi chúng ta nhấn enter vào thanh địa chỉ của trình duyệt, tôi khuyên bạn nên đọc “Điều gì xảy ra khi…”, một nỗ lực rất công phu nhằm giải thích cơ chế đằng sau quá trình này.
Vì đây là loạt bài tập trung vào bảo mật nên tôi sẽ đưa ra gợi ý về những gì chúng ta vừa tìm hiểu:những kẻ tấn công dễ dàng kiếm sống nhờ các lỗ hổng trong phần trao đổi và kết xuất HTTP . Các lỗ hổng bảo mật và người dùng độc hại cũng ẩn nấp ở những nơi khác, nhưng phương pháp bảo mật tốt hơn ở các cấp độ đó đã cho phép bạn đạt được những bước tiến trong việc cải thiện tình trạng bảo mật của mình.
Nhà cung cấp
4 trình duyệt phổ biến nhất hiện nay thuộc về các nhà cung cấp khác nhau:
- Chrome của Google
- Firefox của Mozilla
- Safari của Apple
- Edge của Microsoft
Bên cạnh việc cạnh tranh với nhau để tăng khả năng thâm nhập thị trường, các nhà cung cấp còn hợp tác với nhau để cải thiện tiêu chuẩn web , là một loại “yêu cầu tối thiểu” đối với trình duyệt.
W3C là cơ quan đứng sau việc phát triển các tiêu chuẩn, nhưng không có gì lạ khi các trình duyệt phát triển các tính năng của riêng chúng và cuối cùng biến nó thành tiêu chuẩn web và bảo mật cũng không ngoại lệ.
Ví dụ:Chrome 51 đã giới thiệu cookie SameSite, một tính năng cho phép các ứng dụng web loại bỏ một loại lỗ hổng cụ thể được gọi là CSRF (sẽ nói thêm về điều này sau). Các nhà cung cấp khác cho rằng đây là một ý tưởng hay và làm theo, khiến SameSite trở thành một tiêu chuẩn web:tính đến thời điểm hiện tại, Safari là trình duyệt chính duy nhất không hỗ trợ cookie SameSite.

Điều này cho chúng ta biết 2 điều:
- Safari dường như không quan tâm đầy đủ đến vấn đề bảo mật của người dùng (đùa thôi:cookie SameSite sẽ có sẵn trong Safari 12, có thể đã được phát hành vào thời điểm bạn đang đọc bài viết này)
- vá lỗ hổng trên một trình duyệt không có nghĩa là tất cả người dùng của bạn đều an toàn
Điểm đầu tiên là về Safari (như tôi đã đề cập, chỉ đùa thôi!), trong khi điểm thứ hai thực sự quan trọng. Khi phát triển các ứng dụng web, chúng tôi không chỉ cần đảm bảo rằng chúng trông giống nhau trên nhiều trình duyệt khác nhau mà còn đảm bảo rằng người dùng của chúng tôi được bảo vệ theo cách giống nhau trên các nền tảng.
Chiến lược bảo mật web của bạn sẽ thay đổi tùy theo những gì nhà cung cấp trình duyệt cho phép chúng tôi thực hiện . Ngày nay, hầu hết các trình duyệt đều hỗ trợ cùng một bộ tính năng và hiếm khi đi chệch khỏi lộ trình chung, nhưng những trường hợp như trên vẫn xảy ra và đó là điều chúng ta cần tính đến khi xác định chiến lược bảo mật của mình.
Trong trường hợp của chúng tôi, nếu chúng tôi quyết định rằng chúng tôi sẽ giảm thiểu các cuộc tấn công CSRF chỉ thông qua cookie SameSite, chúng tôi nên lưu ý rằng chúng tôi đang khiến người dùng Safari gặp rủi ro. Và người dùng của chúng tôi cũng nên biết điều đó.
Cuối cùng nhưng không kém phần quan trọng, bạn nên nhớ rằng bạn có thể quyết định có hỗ trợ phiên bản trình duyệt hay không:việc hỗ trợ từng phiên bản trình duyệt sẽ không thực tế (hãy nghĩ đến Internet Explorer 6). Tuy nhiên, việc đảm bảo rằng một số phiên bản cuối cùng của các trình duyệt chính được hỗ trợ thường là một quyết định đúng đắn. Tuy nhiên, nếu bạn không có ý định cung cấp sự bảo vệ trên một nền tảng cụ thể thì bạn nên cho người dùng biết.
Mẹo chuyên nghiệp :Bạn không bao giờ nên khuyến khích người dùng của mình sử dụng các trình duyệt lỗi thời hoặc tích cực hỗ trợ họ. Mặc dù bạn có thể đã thực hiện tất cả các biện pháp phòng ngừa cần thiết nhưng các nhà phát triển web khác có thể chưa làm như vậy. Khuyến khích người dùng sử dụng phiên bản được hỗ trợ mới nhất của một trong những trình duyệt chính.
Nhà cung cấp hay lỗi tiêu chuẩn?
Việc người dùng bình thường truy cập ứng dụng của chúng tôi thông qua ứng dụng khách bên thứ 3 (trình duyệt) bổ sung thêm một mức độ gián tiếp khác hướng tới trải nghiệm duyệt web rõ ràng, an toàn:bản thân trình duyệt có thể gây ra lỗ hổng bảo mật.
Các nhà cung cấp thường cung cấp phần thưởng (còn gọi là tiền thưởng phát hiện lỗi ) cho các nhà nghiên cứu bảo mật, những người có thể tìm ra lỗ hổng trên chính trình duyệt. Những lỗi này không liên quan đến việc triển khai của bạn mà liên quan đến cách trình duyệt tự xử lý bảo mật.
Ví dụ:chương trình phần thưởng Chrome cho phép các kỹ sư bảo mật liên hệ với nhóm bảo mật Chrome để báo cáo các lỗ hổng mà họ đã tìm thấy. Nếu những lỗ hổng này được xác nhận, một bản vá sẽ được phát hành, thông báo tư vấn bảo mật thường được phát hành ra công chúng và nhà nghiên cứu sẽ nhận được phần thưởng (thường là tài chính) từ chương trình.
Các công ty như Google đầu tư một lượng vốn tương đối lớn vào các chương trình Bug Bounty của họ, vì nó cho phép họ thu hút các nhà nghiên cứu bằng cách hứa hẹn một lợi ích tài chính nếu họ gặp bất kỳ vấn đề nào với ứng dụng.
Trong chương trình Bug Bounty, mọi người đều thắng:nhà cung cấp quản lý để cải thiện tính bảo mật cho phần mềm của mình và các nhà nghiên cứu được trả tiền cho những phát hiện của họ. Chúng ta sẽ thảo luận về các chương trình này sau vì tôi tin rằng các sáng kiến Bug Bounty xứng đáng có một phần riêng trong bối cảnh bảo mật.
Jake Archibald là người ủng hộ nhà phát triển tại Google, người gần đây đã phát hiện ra một lỗ hổng ảnh hưởng đến nhiều trình duyệt. Anh ấy đã ghi lại những nỗ lực của mình, cách anh ấy tiếp cận các nhà cung cấp khác nhau và phản ứng của họ trong một bài đăng blog thú vị mà tôi khuyên bạn nên đọc.
Trình duyệt dành cho nhà phát triển
Đến bây giờ, lẽ ra chúng ta đã hiểu một khái niệm rất đơn giản nhưng khá quan trọng:trình duyệt chỉ đơn giản là ứng dụng khách HTTP được xây dựng cho người lướt Internet trung bình .
Chúng chắc chắn mạnh hơn ứng dụng khách HTTP đơn thuần của nền tảng (hãy nghĩ đến require('http') của NodeJS , chẳng hạn), nhưng xét cho cùng, chúng “chỉ” là sự phát triển tự nhiên của các ứng dụng khách HTTP đơn giản hơn.
Với tư cách là nhà phát triển, ứng dụng khách HTTP mà chúng tôi lựa chọn có lẽ là cURL của Daniel Stenberg, một trong những chương trình phần mềm phổ biến nhất mà các nhà phát triển web sử dụng hàng ngày. Nó cho phép chúng tôi thực hiện trao đổi HTTP một cách nhanh chóng bằng cách gửi yêu cầu HTTP từ dòng lệnh của chúng tôi:
$ curl -I localhost:8080
HTTP/1.1 200 OKserver: ecstatic-2.2.1Content-Type: text/htmletag: "23724049-4096-"2018-07-20T11:20:35.526Z""last-modified: Fri, 20 Jul 2018 11:20:35 GMTcache-control: max-age=3600Date: Fri, 20 Jul 2018 11:21:02 GMTConnection: keep-alive
Trong ví dụ trên, chúng tôi đã yêu cầu tài liệu tại localhost:8080/ và máy chủ cục bộ đã phản hồi thành công.
Thay vì chuyển nội dung phản hồi vào dòng lệnh, ở đây chúng tôi đã sử dụng -I cờ cho cURL biết chúng tôi chỉ quan tâm đến tiêu đề phản hồi. Tiến lên một bước, chúng tôi có thể hướng dẫn cURL cung cấp thêm một chút thông tin, bao gồm cả yêu cầu thực tế mà nó thực hiện, để chúng tôi có thể có cái nhìn rõ hơn về toàn bộ quá trình trao đổi HTTP này. Tùy chọn chúng ta cần sử dụng là -v (dài dòng):
$ curl -I -v localhost:8080* Rebuilt URL to: localhost:8080/* Trying 127.0.0.1...* Connected to localhost (127.0.0.1) port 8080 (#0)> HEAD / HTTP/1.1> Host: localhost:8080> User-Agent: curl/7.47.0> Accept: */*>< HTTP/1.1 200 OKHTTP/1.1 200 OK< server: ecstatic-2.2.1server: ecstatic-2.2.1< Content-Type: text/htmlContent-Type: text/html< etag: "23724049-4096-"2018-07-20T11:20:35.526Z""etag: "23724049-4096-"2018-07-20T11:20:35.526Z""< last-modified: Fri, 20 Jul 2018 11:20:35 GMTlast-modified: Fri, 20 Jul 2018 11:20:35 GMT< cache-control: max-age=3600cache-control: max-age=3600< Date: Fri, 20 Jul 2018 11:25:55 GMTDate: Fri, 20 Jul 2018 11:25:55 GMT< Connection: keep-aliveConnection: keep-alive
<* Connection #0 to host localhost left intact
Thông tin tương tự cũng có sẵn trong các trình duyệt phổ thông thông qua DevTools của họ.
Như chúng ta đã thấy, trình duyệt không gì khác hơn là các máy khách HTTP phức tạp. Chắc chắn, chúng bổ sung rất nhiều tính năng (như quản lý thông tin xác thực, đánh dấu trang, lịch sử, v.v.) nhưng sự thật là chúng được sinh ra dưới dạng ứng dụng khách HTTP cho con người. Điều này rất quan trọng vì trong hầu hết các trường hợp, bạn không cần trình duyệt để kiểm tra tính bảo mật của ứng dụng web vì bạn có thể chỉ cần “cuộn nó” và xem phản hồi.
Một điều cuối cùng mà tôi muốn chỉ ra là mọi thứ đều có thể là trình duyệt . Nếu bạn có một ứng dụng di động sử dụng API thông qua giao thức HTTP thì ứng dụng đó chính là trình duyệt của bạn — nó chỉ là một ứng dụng được tùy chỉnh cao do chính bạn xây dựng, một ứng dụng chỉ hiểu một loại phản hồi HTTP cụ thể (từ API của riêng bạn).
Vào giao thức HTTP
Như chúng tôi đã đề cập, trao đổi HTTP và kết xuất các giai đoạn là những giai đoạn chúng tôi chủ yếu đề cập đến vì chúng cung cấp số lượng vectơ tấn công lớn nhất dành cho người dùng độc hại.
Trong bài viết tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về giao thức HTTP và cố gắng hiểu những biện pháp chúng ta nên thực hiện để bảo mật các trao đổi HTTP.
Được xuất bản lần đầu tại odino.org (29 tháng 7 năm 2018).
_Bạn có thể theo dõi tôi trên Twitter - hoan nghênh những lời tán dương!_ ?
Học cách viết mã miễn phí. Chương trình giảng dạy mã nguồn mở của freeCodeCamp đã giúp hơn 40.000 người có được việc làm với tư cách là nhà phát triển. Bắt đầu