2010-03-29 31 views
6

Tôi đang viết bộ điều khiển phiên của riêng mình phát hành id duy nhất cho người dùng khi đã đăng nhập và sau đó xác minh và xác thực id duy nhất đó ở mọi lần tải trang. Cách an toàn nhất để tạo id như vậy là gì? ID duy nhất có nên hoàn toàn ngẫu nhiên không? Có bất kỳ nhược điểm nào để bao gồm id người dùng như là một phần của id duy nhất không?Cách an toàn nhất để tạo ID phiên ngẫu nhiên cho cookie?

+1

Sử dụng id người dùng như một phần của ID duy nhất sẽ loại bỏ toàn bộ điều 'ngẫu nhiên'. Ngay cả khi nó không được công khai, sẽ có nhiều số nhất quán nhất định cho cùng một người dùng, điều này kém an toàn hơn. –

Trả lời

4

Nếu thông tin duy nhất trong cookie là một định danh, về bản chất là một nhãn, đòn tấn công duy nhất bạn đang cố bảo vệ là kẻ tấn công đoán nó là gì. Vì vậy, sử dụng một số byte ngẫu nhiên. Đủ byte ngẫu nhiên mà nó "không thể chấp nhận được."

Sau đó, chuyển các byte ngẫu nhiên thành nội dung phù hợp với giới hạn ký tự bạn có thể sử dụng trong cookie HTTP. base64 hoạt động cho việc này. Nó không hoàn toàn tối ưu, bởi vì có hơn 64 ký tự an toàn cookie và nó có xu hướng để lại dấu vết == ký tự thêm byte vào tiêu đề nhưng không phải ngẫu nhiên, nhưng điều đó là tốt. Nó hoạt động và Python có thể làm mã hóa base64 nhanh hơn bất kỳ thứ gì khác mà chúng ta có thể đưa ra.

Nếu bạn cũng muốn thêm ID người dùng vào đó, điều đó sẽ giúp mọi thứ dễ dàng hơn trong việc theo dõi và gỡ lỗi, điều này có thể giúp cuộc sống của bạn dễ dàng hơn, vì vậy hãy tiếp tục. Nó không cung cấp cho kẻ tấn công bất kỳ lợi thế đáng kể nào. (trừ khi họ quản lý để ăn cắp một mà không thể nếu không có thể xác định những gì người dùng mà họ đang ăn cắp từ, mà dường như không.)

+3

Hãy chắc chắn 100% rằng cookie * không bao giờ * đi qua HTTP thuần; nếu nó có thể bị chặn, "không thể chấp nhận" không còn là một yếu tố nữa. Một lần nữa, tôi khuyên bạn nên thực hiện một số đọc thực tế về chủ đề này ... – retracile

+1

Rất đúng. Nhưng chỉ một phần nhỏ của thế giới là ở một vị trí để chặn các gói tin. Trong khi đó, bạn có thể sử dụng toàn bộ botnet ở bất cứ đâu trên thế giới để đoán. Nhưng, vâng, nếu bạn không muốn vặn vẹo bất cứ ai sử dụng điểm truy cập wifi bảo mật kém, hãy nhận HTTPS và chứng chỉ hợp lệ. Không ai trong số đó có bất kỳ vòng bi cụ thể nào về tạo cookie, tuy nhiên. – keturn

-1

Cách tốt nhất là nên generate a UUID, bằng cách sử dụng chức năng uuid.uuid1:

Tạo một UUID từ một host ID, số thứ tự, và thời gian hiện tại.

+0

Đây có phải là ID máy chủ của máy mà tập lệnh đang chạy không? Hoặc của người dùng kết nối? Id máy chủ lưu trữ được chỉ định như thế nào? Cảm ơn. – ensnare

+3

Có các yếu tố không đổi (như ID máy chủ) hoặc các yếu tố có thể dự đoán (như số thứ tự) không phải là những gì bạn muốn cho ứng dụng này. uuid.uuid4 có thể phù hợp hơn, tùy thuộc vào việc triển khai. Ngoài ra, UUID là một chuỗi được biểu thị bằng hệ thập lục phân và bạn có thể thêm entropy-per-byte nếu bạn sử dụng nhiều ký tự hơn. – keturn

4

Sử dụng mô-đun UUID trong phiên bản 2.5 trở lên. Bằng cách này, họ không thể đoán được vì họ không phải là tuần tự. Nếu bạn muốn chúng thực sự an toàn, bạn có thể muối chúng với id của người dùng và sau đó SHA1 băm chúng, Base64 mã hóa kết quả và sau đó sử dụng nó làm giá trị. Bằng cách đó bạn có thể xác minh ở phía máy chủ rằng chúng thực sự là cookie của bạn và không chỉ là thứ mà một số spammer đang tạo ra và ném vào máy chủ của bạn. Và để làm cho chúng an toàn hơn, hãy đảm bảo rằng chúng chỉ kéo dài trong một khoảng thời gian nhất định trên máy chủ cũng như máy khách. Python 2.6.5 có một triển khai thực hiện HMAC mà bạn có thể sử dụng trên UUID đã tạo.

+0

Làm cách nào để bạn thực hiện xác minh phía máy chủ này của hàm băm? Và điều gì sẽ khiến bạn mua lại? Điều này có vẻ là một cách phức tạp để đưa ra một số byte ngẫu nhiên. – keturn

+3

Sử dụng HMAC cho phép máy chủ xác minh rằng nó tạo ra giá trị ngẫu nhiên mà không phải lưu trữ giá trị ngẫu nhiên đó. Nó cũng có thể bao gồm dấu thời gian để cho phép hết hạn mã thông báo và máy khách không thể sửa đổi dấu thời gian đó mà không làm mất hiệu lực HMAC. Điều này * phức tạp hơn, nhưng cho phép bạn xác thực mã thông báo đó mà không cần nhấn vào một cơ sở dữ liệu. – retracile

+2

Tôi có lẽ cũng nên đề cập rằng trong trường hợp HMAC, giá trị ngẫu nhiên chỉ cần là một nonce. Nhưng đó là những gì các cuốn sách dành cho - chúng bao gồm điều này tốt hơn nhiều so với tôi có thể. :) – retracile

7

Hãy mua số Secrets and Lies và số Practical Cryptography của Bruce Schneier. Hãy tiếp tục và đặt hàng Security Engineering 2nd Ed. của Ross Anderson trong khi bạn đang ở đó. Bây giờ, hãy đọc Secrets and Lies - hãy tin tôi đi, đó là một điều thú vị. :) Sau đó đọc Mật mã thực hành. Tại thời điểm đó, bạn nên có nền tảng tốt hơn về những gì bạn cần làm khi triển khai phần mềm cần bảo mật. Tiếp tục và thực hiện dự thảo thô. Bây giờ bản sao Kỹ thuật bảo mật của bạn đã đến, đọc nó ... mặc dù bạn có thể muốn tiêu hóa chậm hơn một chút; đó là một tome khá nặng.

Ngoài ra còn có whitepaper on web authentication dos and don'ts đáng để đọc và áp dụng trực tiếp hơn một chút cho những gì bạn đang làm. Tôi vẫn đề nghị những cuốn sách ở trên.

another timely article from LWN.net liệt kê một số lượng lớn các cạm bẫy bạn cần phải làm việc để tránh. (BTW, LWN.net cũng đáng để đăng ký và tôi khuyên bạn nên đăng ký. Liên kết trên cho phép truy cập miễn phí vào bài viết đó nếu không sẽ không có sẵn cho người chưa đăng ký.)

4

Bạn có thể sử dụng os.urandom:

os.urandom (n)

Return một chuỗi các byte n ngẫu nhiên thích hợp cho việc sử dụng mật mã.

Hàm này trả về các byte ngẫu nhiên từ nguồn ngẫu nhiên dành riêng cho hệ điều hành. Dữ liệu trả về phải đủ khó đoán trước đối với các ứng dụng mã hóa, mặc dù chất lượng chính xác của nó phụ thuộc vào việc thực hiện OS . Trên một hệ thống giống UNIX, truy vấn/dev/urandom, và trên Windows, nó sẽ sử dụng CryptGenRandom. Nếu một nguồn ngẫu nhiên là không tìm thấy, NotImplementedError sẽ được nâng lên.

Tính năng mới trong phiên bản 2.4.

+1

Lưu ý rằng điều này trả về 'byte' ngẫu nhiên, không phải ký tự. Có thể bạn sẽ muốn chạy kết quả bằng [base64.b64encode] (https://docs.python.org/3/library/base64.html#base64.b64encode) và sử dụng nó làm id phiên. – WhyNotHugo

0

http://docs.python.org/2/library/random.html

"Cảnh báo: Các máy phát điện giả ngẫu nhiên này [ngẫu nhiên] mô-đun không nên được sử dụng cho các mục đích an ninh Sử dụng os.urandom() hoặc SystemRandom nếu bạn đòi hỏi phải có mã hóa bảo mật giả ngẫu nhiên. bộ tạo số. "

"Hàm os.urandom trả về các byte ngẫu nhiên từ nguồn ngẫu nhiên dành riêng cho hệ điều hành. Dữ liệu trả về sẽ không thể đoán trước đủ cho các ứng dụng mã hóa, mặc dù chất lượng chính xác của nó phụ thuộc vào việc triển khai hệ điều hành./dev/urandom, và trên Windows, nó sẽ sử dụng CryptGenRandom() Nếu không tìm thấy nguồn ngẫu nhiên, thì NotImplementedError sẽ được nâng lên. xin vui lòng xem ngẫu nhiên.SystemRandom. "

0

Tôi sẽ tránh hoàn toàn yếu tố ngẫu nhiên. Những gì tôi thường làm là:

  • Tạo tuần tự session_id (mà tôi lưu trữ cục bộ).
  • Khi người dùng đăng nhập, hãy ký session_id bằng khóa riêng (Tôi sử dụng itsdangerous cho việc này).
  • Khi tôi nhận được yêu cầu, nếu chữ ký của session_id còn nguyên vẹn, tôi tiếp tục, nếu không, 403 (400 cũng sẽ có ý nghĩa).

Lưu ý rằng tôi lưu trữ session_id cục bộ vì tôi muốn có thể hết hạn các phiên kết thúc sớm.

Nếu phiên của bạn luôn kéo dài một khoảng thời gian cố định và bạn không cần phải kết thúc sớm, bạn có thể chỉ cần ký user_id + datetime.now(). Điều này cho phép quản lý phiên hoàn toàn không trạng thái.

1

Nếu bạn đang sử dụng Python 3.6+, bạn có thể sử dụng thư viện mới secrets.

from secrets import token_urlsafe 

token = token_urlsafe(64) # something like Drmhze6EPcv0fN_81Bj-nA.... 
Các vấn đề liên quan