Nếu bạn đang xây dựng một ứng dụng chấp nhận đầu vào của người dùng hoặc bên thứ ba, thì việc xem xét quan trọng đối với bảo mật là đảm bảo rằng bạn xác nhận đúng đầu vào đó. Bạn muốn đảm bảo rằng bất kỳ dữ liệu nào nhập ứng dụng của bạn là hợp lệ và an toàn. Dữ liệu này có thể là bất cứ điều gì ngoài tầm kiểm soát của bạn, chẳng hạn như nhận xét được gửi bởi người dùng trên trang web của bạn. Đầu vào cũng có thể đến từ các dịch vụ web của bên thứ ba mà ứng dụng của bạn yêu cầu [như tài liệu XML]. & NBSP;
Dữ liệu bị dị tật hoặc đầu vào được chế tạo cẩn thận có thể được sử dụng bởi các tác nhân độc hại để chuyển hướng ứng dụng của bạn để tiêm các lệnh không mong muốn [như tiêm vỏ hoặc tiêm SQL] hoặc chỉ để làm cho nó bị sập. Dữ liệu đầu vào là một vectơ tấn công lớn và hầu hết các lỗ hổng được liệt kê bởi Dự án bảo mật ứng dụng web mở [OWASP] trong danh sách 10 của họ có thể được ngăn chặn bằng cách xác thực dữ liệu đúng trước khi chúng được xử lý. & NBSP;
Thất bại hoặc thiếu sót trong xác thực dữ liệu có thể dẫn đến tham nhũng dữ liệu hoặc lỗ hổng bảo mật. Kiểm tra xác thực dữ liệu rằng dữ liệu là hợp lệ, hợp lý, hợp lý và an toàn trước khi chúng được xử lý. - OWASP
Xác thực dữ liệu đầu vào trong Python có thể đạt được theo nhiều cách. Bạn có thể thực hiện kiểm tra loại hoặc kiểm tra các giá trị hợp lệ/không hợp lệ. Hệ sinh thái Python cung cấp một số thư viện để giúp xác thực dữ liệu mà chúng tôi sẽ đề cập trong bài viết này. Nhưng trước tiên chúng ta sẽ bắt đầu với một ví dụ đơn giản.
Một ví dụ về xác thực không đúng
Khi chúng ta phát triển mã, chúng ta thường giới hạn quá trình suy nghĩ của mình để viết cho con đường hạnh phúc. Chúng tôi bắt đầu với việc làm rõ những đầu vào mong đợi và đầu ra mong đợi là gì, và phát triển cho những thứ đó. Chúng tôi kiểm tra chúng với unittest
và chuyển sang đoạn mã tiếp theo.
Thật không may, chúng tôi không phải lúc nào cũng nhận được các đầu vào mong đợi, cho dù là do tai nạn hay độc hại. Và ngay cả đoạn mã đơn giản nhất cũng có thể bị sập khi xử lý dữ liệu đầu vào bất ngờ. Vì lợi ích của ví dụ này, hãy để nói rằng bạn muốn cung cấp một dịch vụ web được viết bằng Python để tính toán phân chia thực sự của hai số.
Mã của bạn có thể trông giống như:
Dịch vụ này được thiết kế để xử lý các số, vì vậy nó hoạt động như mong đợi với các loại int
và float
:
Trong khi các loại int
và float
hoạt động như mong đợi, có những giá trị đã giành được công việc. Một giá trị nổi tiếng là bất hợp pháp trong toán hạng của chức năng của chúng tôi và sẽ làm hỏng ứng dụng của chúng tôi:
Chức năng của chúng tôi là tăng một ngoại lệ bất ngờ. Điều này rất dễ sửa bằng cách kiểm tra giá trị cụ thể này và nêu ra một ngoại lệ mà người gọi sẽ biết:
Tuy nhiên, đây không phải là đầu vào không hợp lệ duy nhất. Do tính chất của ngôn ngữ lập trình Python, các biến được gõ động, có nghĩa là hàm của chúng tôi có thể được gọi với bất kỳ kiểm tra loại đối số và loại đối số nào được thực hiện khi chạy. Vì đầu vào của chúng tôi đến từ phần thân JSON của một yêu cầu, một người dùng độc hại dễ dàng thay đổi loại number_1
và number_2
thành bất kỳ loại JSON hợp lệ nào họ chọn. Vì vậy, những gì về việc gọi chức năng của chúng tôi với những người không phải là người?
Dịch vụ thất bại bằng cách tăng một ngoại lệ bất ngờ khác vì loại float
không biết về None
. Chúng tôi có thể cố gắng sửa chữa chức năng của mình bằng cách kiểm tra các loại đầu vào:
Đây là một cải tiến, nhưng nó không đủ. Chúng ta vẫn có thể lừa ranh giới của các đối số để kích hoạt sự cố:
Để xác nhận đúng dịch vụ này, chúng tôi cũng nên giới hạn các giá trị mà chúng tôi chấp nhận.
So sánh phiên bản cuối cùng này với bản gốc chúng tôi bắt đầu. Chức năng của chúng tôi ở đây ở cuối hầu như không liên quan gì đến phiên bản đầu tiên và phức tạp hơn, nhưng cần phải phơi bày dịch vụ của chúng tôi với người dùng một cách an toàn. & NBSP;
Với các dịch vụ phức tạp hơn, nó khó khăn khi suy nghĩ qua mọi kịch bản đầu vào không phù hợp. Trong thực tế, có những giải pháp tốt hơn để xác thực dữ liệu đầu vào so với chúng tôi đã hiển thị ở đây. Ví dụ, bạn có thể sử dụng các chú thích loại Python và thư viện để kiểm tra các loại trước khi sử dụng dữ liệu.
Thực hiện xác nhận với các loại và pydantic
Hãy cùng lấy một ví dụ khác về một dịch vụ web Bình trả lại các bài viết được lưu trữ trong cơ sở dữ liệu MongoDB. Tất cả các bài viết được lưu trữ trong cùng một bộ sưu tập, nhưng một số bài viết là bản nháp và chúng tôi không muốn xuất bản chúng bây giờ.
Phiên bản ban đầu của dịch vụ web của chúng tôi trông giống như:
Điểm cuối này cấm truy cập vào danh mục drafts
nhưng quên xác thực yêu cầu JSON: nó không kiểm tra loại đầu vào mà chỉ vì giá trị của nó. Điều này có nghĩa là nó có thể bị lừa bởi một diễn viên độc hại với cơ thể JSON chứa tiêm NoQuery. Yêu cầu sau đây sẽ trả về tất cả các bài viết của chúng tôi bao gồm các bản nháp của chúng tôi.
Bắt đầu với Python 3.5, có thể chú thích mã của chúng tôi bằng các loại và sử dụng các thư viện bên ngoài để kiểm tra chúng. Đây là những gì Pydantic làm.
Đầu tiên, hãy để chỉ định một loại mới cho bộ lọc của chúng tôi bằng Pydantic:
Lớp này sẽ được Pydantic sử dụng để xác nhận đầu vào của chúng tôi và đảm bảo int
0 là một chuỗi, nhưng nó có thể được sử dụng để làm nhiều hơn nữa. Ví dụ, nó có thể được sử dụng để kiểm tra các giá trị không hợp lệ. Phiên bản cuối cùng của chúng tôi sau đó trông giống như:
Do những thay đổi này, chúng tôi hiện được bảo vệ chống lại việc tiêm NoQuery và chỉ các bài viết không phải là phác thảo được xuất bản nhờ xác thực dữ liệu đầu vào thích hợp.
Các giải pháp khác
Có một số thư viện Python khác có thể giúp bạn xác thực dữ liệu đầu vào của mình:
- Django cung cấp xác nhận thông qua các biểu mẫu và mô hình, hãy chắc chắn sử dụng chúng.
- Pydantic cũng hỗ trợ
int
1 bắt đầu từ Python 3.7. - Cerberus là một thư viện sạch sẽ và đẹp, định dạng bất khả tri định dạng và xác nhận. Cho nó hai dicts, nó sẽ tăng nếu nó thất bại.
Sự kết luận
Việc xác nhận đúng các đầu vào của bạn có thể đi một chặng đường dài để cải thiện tính bảo mật của mã của bạn và ngăn chặn các bên thứ ba vô tình hoặc cố ý làm mã của bạn làm điều gì đó mà nó không được cho là. Trong bài viết này, chúng tôi đã xem xét một số cách để xác nhận đầu vào trong Python. Nếu bạn muốn đọc thêm về các thực tiễn tốt nhất bảo mật nhà phát triển tốt, hãy xem bài đăng của chúng tôi về bảo vệ chống lại các cuộc tấn công thời gian.
Boris là một người nghiện Python thực sự. Boris thích làm việc về các vấn đề về khả năng mở rộng của cơ sở hạ tầng máy học trong quá khứ. Anh ấy cũng là một người yêu Saltstack, và bạn có thể sẽ gặp anh ấy trong nhiều cuộc gặp gỡ khác nhau!
Nhận liều bảo mật hai tuần một lần của bạn
Nội dung bảo mật được chọn bằng tay cho các nhà phát triển, DevOps và bảo mật. Không có thư rác. Chỉ là nội dung tuyệt vời.
- thực hành tốt nhất,
- Python