10 lỗ hổng bảo mật web phổ biến
Với hầu hết các doanh nghiệp, việc thực hiện bảo mật website luôn là vấn đề được ưu tiên hàng đầu và không cần đợi đến khi hậu quả xảy ra. Cách tiếp cận hiệu quả đối với các mối đe dọa về bảo mật web là chủ động và tự phòng ngừa. Bài viết này tập trung vào 10 lỗ hổng bảo mật web phổ biến và quan trọng cũng như đề xuất các cách để khắc phục chúng.
1. Injection flaws
Lỗ hổng Injection là kết quả của sự thiếu sót trong việc lọc các đầu vào không đáng tin cậy. Nó có thể xảy ra khi bạn truyền các dữ liệu chưa được lọc tới Database (SQL injection), tới trình duyệt (XSS), tới máy chủ LDAP (LDAP Injection) hoặc tới bất cứ vị trí nào khác. Vấn đề ở đây là kẻ tấn công có thể chèn các đoạn mã độc dẫn đến mất dữ liệu và chiếm quyền kiểm soát các trình duyệt của khách hàng.
Mọi thông tin mà ứng dụng của bạn nhận được khi truy cập vào các nguồn không đáng tin cậy đều phải được lọc theo Whitelist, bởi nếu bạn sử dụng Blacklist việc lọc thông tin sẽ rất dễ bị bỏ qua. Các phầm mềm chống virus thường đưa ra các ví dụ không thành công khi sử dụng Blacklist, dẫn đến tính năng Pattern matching không hoạt động.
Cách ngăn chặn lỗ hổng:
Thật may mắn là để chống lại lỗ hổng này chỉ “đơn giản” là vấn đề bạn đã lọc đầu vào đúng cách chưa hay việc bạn cân nhắc liệu một đầu vào có thể được tin cậy hay không. Tuy nhiên, tất cả các đầu vào đều cần được lọc trừ trường hợp đầu vào đó chắc chắn tin cậy. (Tuy nhiên việc cẩn thận kiểm tra tất cả các đầu vào là luôn luôn cần thiết).
Ví dụ, trong một hệ thống với 1000 đầu vào, lọc thành công 999 đầu vào là không đủ vì điều này vẫn để lại một phần giống như “gót chân Asin”, có thể phá hoại hệ thống của bạn bất cứ lúc nào. Bạn có thể cho rằng đặt kết quả truy vấn SQL vào truy vấn khác là một ý tưởng hay vì cơ sở dữ liệu này là đáng tin cậy nhưng thật không may nếu không có hệ thống mạng Perimeter các đầu vào sẽ gián tiếp đến từ những kẻ có malintent. Đây được gọi là lỗi Second Order SQL Injection.
Việc lọc dữ liệu khá khó (giống như crypto) vì thế các bạn nên sử dụng các chức năng lọc trong framework của mình – các tính năng này đã được chứng minh sẽ thực hiện việc kiểm tra một cách kỹ lưỡng. Bạn cần cân nhắc về tầm quan trọng của việc sử dụng các framework vì chúng thực sự hiệu quả với an ninh máy chủ của bạn.
2. Broken Authentication
Đây là một nhóm các vấn đề có thể xảy ra trong quá trình xác thực bị lỗi nhưng chúng không cùng xuất phát từ một nguyên nhân gốc.
Có một lời khuyên đó là không nên tự phát triển các giải pháp mã hóa vì rất khó có thể làm được chính xác do có rất nhiều rủi ro có thể gặp phải như:
- URL có thể chứa phiên ID và rò rỉ nó trong referer header của người khác.
- Mật khẩu có thể không được mã hóa trong lưu trữ.
- Có thể thực hiện các phiên cố định.
- Session hijacking có thể xảy ra, thời gian chờ không được triển khai đúng hoặc sử dụng HTTP (không bảo mật SSL)…
Cách ngăn chặn lỗ hổng:
Cách đơn giản nhất để tránh lỗ hổng bảo mật web này là sử dụng một framework. Bạn có thể thực hiện việc này một cách chính xác nhưng thời gian gần đây việc này đã tở nên khó khăn hơn. Trong trường hợp bạn muốn cuộn mã của mình hãy nghĩ đến những rủi ro mà bạn sẽ gặp phải và tự cân nhắc kĩ trước khi thực hiện
3. Cross Site Scripting (XSS)
Đây là một sự lọc đầu vào khá phổ biến (chủ yếu là các trường hợp đặc biệt của lỗ hổng đầu tiên). Kẻ tấn công đưa các thẻ JavaScript của ứng dụng web của bạn lên đầu vào. Khi đầu vào này trả e người dùng chưa được lọc, chúng sẽ được thực thi trên trình duyệt của người dùng. Nó tạo ra một liên kết và thuyết phục người dùng nhấp vào hoặc nó có thể là thứ gì đó nguy hiểm hơn. Trên trang tải tập lệnh chạy, ví dụ, kẻ tấn công có thể lấy được cookie của bạn.
Sơ đồ quá trình tấn công XSS
Cách ngăn chặn lỗ hổng:
Có một cách bảo mật web đơn giản đó là không trả lại thẻ HTML cho người dùng. Điều này còn giúp bảo vệ chống lại cả HTML Injection, một cuộc tấn công tương tự mà hacker tấn công vào nội dung HTML (chẳng hạn như hình ảnh hoặc splash player vô hình) – không gây ảnh hưởng nghiêm trọng nhưng khá rắc rối. Thông thường cách giải quyết đơn giản chỉ là chuyển đổi tất cả các thực thể HTML, do đó <script>được trả về dưới dạng <script>. Một phương pháp làm sạch khác để loại bỏ các thẻ HTML là sử dụng các biểu thức thông thường trên < và > nhưng điều này khá nguy hiểm vì các trình duyệt sẽ cho rằng một vài HTML hỏng . Cách tốt hơn là chuyển đổi tất cả các ký tự cho các đối tác đã thoát được.
4. Insecure Direct Object Referances
Đây là trường hợp điển hình của việc cho rằng đầu vào của người dùng là tin cậy từ đó dẫn đến hậu quả là một lỗ hổng trong bảo mật. Lỗ hổng này xảy ra khi chương trình cho phép người dùng truy cập các tài nguyên (dữ liệu, file, database). Vấn đề ở đây là kẻ tấn công có thể cung cấp các thông tin truy cập này, nếu ủy quyền không được thi hành (hoặc bị hỏng) kẻ tấn công có thể truy cập một cách bất hợp pháp.
Chúng ta có thể xem xét ví dụ sau để hiểu rõ hơn: Một đoạn mã có mô-đun download.php và cho phép người dùng tải tệp xuống, sử dụng tham số CGI để chỉ định tên tệp (ví dụ download.php?file=something.txt). Hoặc do sai sót của nhà phát triển, việc ủy quyền cho mã đã bị bỏ qua. Bây giờ kẻ tấn công có thể sử dụng nó để tải về bất kì tệp nào trên hệ thống mà người dùng đang chạy PHP có quyền truy cập, chắc hạn như code ứng dụng, hoặc các dữ liệu khác để lại trên máy chủ.
Một ví dụ phổ biến khác là chức năng đặt lại mật khẩu dựa vào đầu vài của người dùng để xác định mật khẩu đang đặt lại. Sauk hi nhấp vào URL hợp lệ, kẻ tấn công có thể sửa đổi trường tên người dùng trong URL để “đóng giả” admin.
Cách ngăn chặn lỗ hổng: Thực hiện ủy quyền người dùng đúng cách và nhất quán và Whitelist là sự lựa chọn. Thường xuyên lưu trữ dữ liệu nội bộ và không dựa vào nó thông qua từ khách hàng thông qua các thông số CGI. Các biến số trong hầu hết các framework rất phù hợp cho mục đích này.
5. Security Misconfiguration
Trong thực tế, máy chủ web và các ứng dụng đa số bị cấu hình sai, có lẽ do một vài sự sai sót như:
- Chạy ứng dụng với debug được bật
- Danh sách thư mục trên máy chủ được bật và làm rò rỉ các thông tin có giá trị
- Sử dụng phần mềm đã lỗi thời (WordPress plugin, PhpMyAdmin cũ)
- Có các dịch vụ không cần thiết đang chạy trên máy
- Không thay đổi default key và mật khẩu (xảy ra khá thường xuyên)
- Tiết lộ lỗi xử lý thông tin cho kẻ tấn công chẳng hạn như stack traces.
Cách ngăn chặn lỗ hổng:
Có một quá trình “xây dựng và triển khai” tốt (tốt nhất là tự động), có thể triển khai chạy thử nghiệm. Giải pháp để tạo cấu hình an toàn là các móc nối sau cam kết, để ngăn không cho mã đi ra với mật khẩu mặc định và/hoặc các công cụ phát triển được tích hợp sẵn.
6. Sensitive data exposure:
Lỗ hổng bảo mật web này là về bảo mật crypto và tài nguyên. Dữ liệu nhạy cảm phải được mã hóa mọi lúc, bao gồm cả khi chuyển đổi và nghỉ ngơi, không có ngoại lệ. Thông tin thẻ tín dụng và mật khẩu người dùng không bao giờ được di chuyển hoặc được lưu trữ không được mã hóa. Rõ ràng thuật toán crypto / hashing không phải là một cách bảo mật yếu – khi có sự nghi ngờ, các tiêu chuẩn an ninh web đề nghị sử dụng AES (256 bit trở lên) và RSA (2048 bit trở lên).
Cần phải nói rằng các phiên ID và dữ liệu nhạy cảm không nên đi chuyển trong các URL và các cookie nhạy cảm nên có cờ an toàn bởi điều này rất quan trọng.
Cách ngăn chặn lỗ hổng:
- Trong transit: Sử dụng HTTPS có chứng chỉ phù hợp và PFS (Perfect Forward Secrecy). Không chấp nhận bất cứ điều gì trên các kết nối không phải là HTTPS. Có cờ an toàn trên cookie.
- Trong lưu trữ: Việc ngăn chặn sẽ trở nên khó khăn hơn. Trước hết, bạn cần giảm các dữ liệu nhạy cảm có khả năng bị lộ của mình. Nếu bạn không cần dữ liệu nhạy cảm, hãy hủy nó. Dữ liệu bạn không có không thể bị đánh cắp. Không bao giờ lưu trữ thông tin thẻ tín dụng, vì bạn có thể không muốn phải đối phó với việc tuân thủ PCI. Đăng ký một bộ xử lý thanh toán như Stripe hoặc Braintree. Thứ hai, nếu bạn có dữ liệu nhạy cảm mà bạn thực sự cần, lưu trữ mã hóa nó và đảm bảo rằng tất cả các mật khẩu được sử dụng hàm Hash để bảo vệ. Đối với Hash, nên sử dụng bcrypt. Nếu bạn không sử dụng mã hoá bcrypt, hãy tìm hiểu về mã Salt để ngăn ngừa rainbow table attack.
Không lưu trữ các khóa mã hóa bên cạnh dữ liệu được bảo vệ, việc này giống như cất giữ chiếc xe đạp của bạn với khóa có chìa khoá trong đó. Bảo vệ sao lưu của bạn với mã hóa và giữ các khóa của bạn riêng tư.
7. Missing function level access control
Đây chỉ là sai sót trong vấn đề ủy quyền. Nó có nghĩa là khi một hàm được gọi trên máy chủ, sự ủy quyền thích hợp đã không được thực hiện. Các nhà phát triển dựa vào thực tế là phía máy chủ đã tạo giao diện người dùng và họ nghĩ rằng khách hàng không thể truy cập các chức năng không được cung cấp bởi máy chủ. Nó không đơn giản như vậy, vì kẻ tấn công luôn có thể yêu cầu các chức năng “ẩn” và sẽ không bị cản trở, bởi giao diện người dùng không làm cho chức năng nàytrở nên dễ truy cập. Hãy tưởng tượng trong giao diện người dùng chỉ có bảng điều khiển /admin và nút nếu người dùng thực sự là quản trị viên. Không có gì ngăn cản kẻ tấn công phát hiện tính năng này và lạm dụng nó nếu ủy quyền bị thiếu.
Cách ngăn chặn lỗ hổng: Ở phía máy chủ, phải luôn được phân quyền một cách triệt để từ khâu thiết kế. Không có ngoại lệ hoặc lỗ hổng sẽ dẫn đến các vấn đề nghiêm trọng.
8. Cross Site Request Forgery (CSRF)
Đây là một ví dụ của cuộc tấn công deputy attack theo đó trình duyệt bị lừa bởi một số bên khác lạm dụng quyền của nó. Ví dụ: trang web của bên thứ ba có thể làm cho trình duyệt của người dùng lạm dụng quyền đó để làm điều gì đó cho kẻ tấn công.
Trong trường hợp của CSRF, trang web của bên thứ ba gửi yêu cầu đến trang web đích (ví dụ: ngân hàng của bạn) sử dụng trình duyệt của bạn với cookie / phiên. Nếu bạn đăng nhập vào một trang trên trang chủ của ngân hàng và trang đó dễ bị tấn công, một tab khác có thể làm cho trình duyệt của bạn sử dụng sai thông tin của người quản trị “đóng giả” bởi kẻ tấn công, dẫn đến sự cố nhầm lẫn. Deputy là trình duyệt lạm dụng quyền hạn của mình (session cookies) để làm điều gì đó mà kẻ tấn công yêu cầu.
Chúng ta có thể xem xét ví dụ sau:
- Kẻ tấn công là Alice chọn mục tiêu là chiếc ví của Todd bằng cách chuyển một phần tiền của Todd cho cô ta. Ngân hàng của Todd đã gặp phải lỗ hổng CSRF. Để gửi tiền, Todd phải truy cập vào URL sau:
- Sau khi URL này được mở ra, một trang thành công được trình bày cho Todd, và việc chuyển đổi đã hoàn tất. Alice cũng biết rằng Todd thường ghé thăm một trang web dưới quyền kiểm soát của cô tại blog.aliceisawesome.com, nơi cô đặt đoạn mã sau đây:
- Khi truy cập trang web của Alice, trình duyệt của Todd nghĩ rằng Alice liên kết đến một hình ảnh và tự động đưa ra yêu cầu HTTP GET để lấy “hình ảnh”, nhưng điều này thực sự hướng dẫn ngân hàng của Todd chuyển $ 1500 đến Alice.
Ngoài việc chứng minh tính dễ bị tổn thương của CSRF, ví dụ này cũng cho thấy thay đổi trạng thái máy chủ bằng yêu cầu HTTP GET idempotent vốn là một lỗ hổng nghiêm trọng. Yêu cầu HTTP GET phải là idempotent (an toàn), có nghĩa là họ không thể thay đổi tài nguyên được truy cập. Không bao giờ nên sử dụng các phương pháp idempotent để thay đổi trạng thái máy chủ.
Cách ngăn chặn lỗ hổng:
Lưu trữ một mã thông báo bí mật trong một trường mẫu ẩn mà không thể truy cập được từ trang web của bên thứ ba. Tất nhiên bạn phải xác minh trường ẩn này. Một số trang web yêu cầu mật khẩu của bạn cũng như khi sửa đổi các cài đặt nhạy cảm (ví dụ như email nhắc nhở mật khẩu của bạn).
9. Using component with known vulnerabilities
Đây là vấn đề xảy ra khi sử dụng mà không kiểm duyệt các thành phần đã tồn tại lỗ hổng. Trước khi kết hợp mã mới, hãy thực hiện một số nghiên cứu, có thể kiểm tra. Sử dụng mã mà bạn nhận được từ một người ngẫu nhiên trên GitHub hoặc một số diễn đàn có thể rất thuận tiện, nhưng không phải là không có rủi ro từ lỗ hổng bảo mật web nghiêm trọng.
Ví dụ: Nhiều trường hợp, nơi các trang web sở hữu (tức là, ở đó người bên ngoài có quyền truy cập quản trị vào một hệ thống) không phải vì các lập trình viên sai sót, mà vì phần mềm của bên thứ ba vẫn chưa được sản xuất. Điều này đang xảy ra hầu hết với các plugin WordPress. Nếu bạn nghĩ rằng họ sẽ không tìm thấy cài đặt phpmyadmin ẩn của bạn, hãy tìm hiểu về dirbuster.
Bài học ở đây là sự phát triển phần mềm không kết thúc khi ứng dụng được triển khai. Cần phải có tài liệu, thử nghiệm, và kế hoạch về cách duy trì và cập nhật nó, đặc biệt nếu nó có chứa bên thứ ba hoặc các thành phần mã nguồn mở.
Cách ngăn chặn lỗ hổng:
Chú ý cẩn thận khi sử dụng các thành phần như vậy, không nên là một coder copy-paste. Kiểm tra cẩn thận phần mã mà bạn sắp đưa vào phần mềm của bạn vì nó có thể bị hỏng nếu không được sửa chữa (hoặc trong một số trường hợp, các cuộc tấn công an ninh web độc hại có chủ ý đôi khi được mời theo cách này).
Cập nhật mọi thứ: Đảm bảo bạn đang sử dụng phiên bản mới nhất của tất cả mọi thứ mà bạn tin tưởng và có kế hoạch cập nhật chúng thường xuyên. Ít nhất là đăng ký bản tin về các lỗ hổng bảo mật mới liên quan đến sản phẩm.
10. Unvalidated redirects and forwards
Đây lại là vấn đề về lọc đầu vào. Giả sử rằng trang đích có một mô-đun redirect.php lấy URL làm tham số GET. Thao tác với tham số này có thể tạo ra một URL trên targetite.com chuyển hướng trình duyệt đến phần mềm malwareinstall.com. Khi người dùng nhìn thấy liên kết, họ sẽ thấy targetite.com/blahblahblah mà người dùng cho là đáng tin cậy và an toàn khi nhấp chuột. Họ ít biết rằng điều này sẽ thực sự chuyển vào trang thả phần mềm độc hại (hoặc bất kỳ trang độc hại khác). Ngoài ra, kẻ tấn công có thể chuyển hướng trình duyệt sang targetite.com/deleteprofile?confirm=1.
Điều đáng nói đến là việc cài các đầu vào không xác định của người dùng xác định vào một tiêu đề HTTP có thể dẫn đến việc header injection khá xấu.
Cách ngăn chặn lỗ hổng: Các lựa chọn bao gồm
- Không làm chuyển hướng (chúng hiếm khi cần thiết).
- Có một danh sách tĩnh các vị trí hợp lệ để chuyển hướng đến.
- Có Whitelist tham số người dùng xác định.
Đọc thêm về