Tôi phải lưu trữ khóa riêng trong một tệp?


7

Tôi có một ứng dụng dựa trên db cần liên lạc với máy chủ khác thông qua ssh. Ứng dụng web có thể tạo ra một cặp khóa và cung cấp cho người dùng pubkey hoặc nó có thể chấp nhận khóa riêng không được mã hóa trong một trường trên một biểu mẫu web. Sau đó, nó mã hóa khóa bằng mã hóa đảo ngược và lưu trữ nó trong cơ sở dữ liệu của nó.

Khi ứng dụng web liên lạc với máy chủ ssh, tôi cần giải mã khóa riêng và cung cấp cho ssh bằng cách này hay cách khác. Tôi có thể tạo một tệp tạm thời an toàn với mktemp, trỏ ssh vào nó và sau đó hủy tệp, nhưng đó là công việc bổ sung để lộ khóa theo cách mới mà dường như không cần thiết. Tôi đã xem man ssh, man ssh-agentman ssh-add, nhưng dường như không có cách nào để sử dụng khóa mà không thêm nó vào tệp trước. Tôi đang thiếu gì?


Nếu bạn muốn sử dụng các công cụ tiêu chuẩn, bạn phải cung cấp khóa thông qua một tệp. Tất nhiên, bạn cũng có thể triển khai ứng dụng khách ssh / đại lý SSH của riêng mình và trực tiếp giải mã khóa từ cơ sở dữ liệu
Ulrich Dangel

@UlrichDangel bạn sẽ thật tử tế khi chỉ cho tôi tài liệu về cách triển khai một tác nhân SSH?
kojiro

Không, vì tôi không có nhưng nên có một mô tả về giao thức đại lý SSH svnweb.freebsd.org/base/vendor-crypto/openssh/dist/ trộm
Ulrich Dangel 14/213

Tốt hơn là thực hiện lại mọi thứ một bản vá đơn giản cho một triển khai hiện có nên thực hiện thủ thuật.
peterph

@peterph Đó là một ý tưởng tốt, nhưng tôi vẫn muốn có một thông số để làm việc.
kojiro

Câu trả lời:


4

Nếu bạn muốn sử dụng các công cụ hiện có như ssh/ ssh-agentbạn phải cung cấp khóa dưới dạng tệp.

Một giải pháp khác, có thể khả thi hơn là trực tiếp triển khai sshứng dụng khách trong ứng dụng của bạn và phụ thuộc vào các thư viện bên thứ ba như JSch hoặc mở rộng ssh/ ssh-agentđể trực tiếp nhận và giải mã khóa từ cơ sở dữ liệu của bạn.


4

Tập tin là cách chính để trao đổi dữ liệu giữa các ứng dụng. Nó không phải là một tập tin đĩa. Nó có thể là một tập tin lưu trữ tạm thời hoặc một đường ống. Bạn có thể cung cấp một tệp chính cho ssh-addđầu vào tiêu chuẩn của nó, miễn là tệp chính không được bảo vệ bằng mật khẩu¹ (và vì tệp chính được lưu trữ được mã hóa, không có lý do gì để bảo vệ mật khẩu trên đầu trang).

Ngoài ra, không làm bất cứ điều gì ưa thích và ghi tệp vào hệ thống tệp được hỗ trợ bộ nhớ, chẳng hạn như /run( /dev/shmhoặc /tmphoặc bất cứ điều gì phân phối của bạn cung cấp).

Ngoài ra, giữ tệp khóa riêng xung quanh không có mã hóa bên ngoài, nhưng đặt mật khẩu vào đó. Sử dụng một mật khẩu dài, được tạo ngẫu nhiên và lưu mật khẩu đó trong cơ sở dữ liệu.

Về mặt thực nghiệm, ssh-addcuộn cảm trên các tệp khóa được bảo vệ bằng mật khẩu mà không thể tìm kiếm được, chẳng hạn như các đường ống có tên.


3

Xin lỗi, không phải là một câu trả lời nhưng quá dài cho một bình luận, mà tôi nghĩ là đúng chỗ.

Điều quan trọng là những gì bạn đang cố gắng đạt được bằng cách lưu trữ khóa trong cơ sở dữ liệu được mã hóa.

Kẻ tấn công có thể truy cập tệp khóa riêng tạm thời cũng có thể đọc bộ nhớ của quy trình khách ssh (và do đó nhận được dữ liệu chính), vì cả hai dữ liệu này đều phải có cùng quyền truy cập - thử để ẩn tập tin dường như không làm cho nó an toàn hơn.

Nếu bạn đang sử dụng các người dùng khác nhau cho kết nối db, webapp và ssh, bằng cách lưu trữ khóa trong db, giải mã nó trong ứng dụng web và đưa nó vào ssh, bạn chỉ cần mở các vectơ tấn công tiềm năng bằng cách trải đều khóa trong suốt quá trình. Nếu bạn đang sử dụng chỉ một người dùng cho tất cả những người này (db, ứng dụng, ssh), bạn sẽ không thu được gì ngoại trừ độ phức tạp của mã.

Ưu điểm duy nhất có vẻ là việc chuyển hệ thống dễ dàng hơn đến một máy chủ khác và mức tăng tiềm năng trong trường hợp dữ liệu db bị đánh cắp nhưng ứng dụng web (mà AFAIU chứa thuật toán giải mã và mật khẩu) thì không. Nhưng điều đó có khả năng không?

Điều đó nói rằng, nếu bạn muốn bảo vệ khóa, bạn cũng có thể sử dụng mã hóa nội bộ của các khóa và tải chúng vào một tác nhân ssh khi bắt đầu dịch vụ của bạn (hãy nhớ xóa nó khi dừng!). Nhưng một lần nữa hãy nhớ rằng ssh-agent giữ các khóa trong bộ nhớ không được mã hóa, vì vậy nó có khả năng có thể được đọc. Một lần nữa: đây có phải là vấn đề bạn đang cố gắng giải quyết?

Nếu bạn chỉ cần bảo vệ liên lạc giữa hai máy, stunnelcó thể dịch vụ tốt hơn ssh.

Và cuối cùng cho câu hỏi: liên quan đến OpenSSH ( di động ), việc viết một bản vá đơn giản cho phép sshđọc khóa từ một quy trình khác cũng như sshdvới AuthorizedKeysCommandtùy chọn nên đơn giản một cách hợp lý.


Tôi đánh giá cao những gì bạn đang nói và bạn có quyền thách thức các giả định của mình và hỏi tôi đang giải quyết vấn đề gì ; tuy nhiên, câu trả lời của bạn quá cụ thể đối với môi trường xung quanh câu hỏi của tôi (webapp và db) và (như bạn nói) không thực sự trả lời chính câu hỏi đó.
kojiro

Chắc chắn, tôi chỉ muốn viết này để tham khảo trong tương lai. Thay vào đó, tôi thường thấy mọi người (mis) sử dụng ssh trong các tình huống trong đó một cái gì đó khác sẽ là lựa chọn tốt hơn (tôi không nói đây là trường hợp của bạn). Và người khôn ngoan về bảo mật thường quên đi những gì nên là mối quan tâm chính của anh ấy / cô ấy.
peterph

2

Tôi đã cố gắng giải quyết vấn đề này khi tôi đang tạo ra các bàn phím và lưu trữ chúng trong cơ sở dữ liệu bằng Python. Dưới đây là một số bước mà tôi đã sử dụng, cụ thể là bắt đầu ssh-agentvà tương tác với nó. Nó bằng Python, nhưng có lẽ bạn có thể dịch nó sang bất cứ thứ gì khác. Một tính năng khác là không ai trong số này sử dụng shell=True, vì vậy chúng an toàn hơn trước các cuộc tấn công tiêm chích.

import subprocess
import os
sockfile = '/some/place.sock'

agent = subprocess.Popen(['ssh-agent',
          '-D', # foreground mode
          '-a', sockfile, # bind address (socket file)
     ])
subprocess.check_call(['ssh-add', 
           '-D', # delete all identities from the agent
      ], 
      env={'SSH_AUTH_SOCK': sockfile},
)

Điều đó kích hoạt một ssh-agentchương trình chỉ dành cho chương trình của chúng tôi và xóa nó đi (tôi tin rằng nó đang tải khóa người dùng của tôi vào đó, không chắc chắn.) Biến môi trường SSH_AUTH_SOCKthường được đặt bởi ssh-agent(nhưng chúng tôi đã làm thủ công), chúng tôi đang cung cấp cho người khác các chương trình.

Tiếp theo chúng ta sử dụng ssh-addđể cung cấp cho nó khóa riêng (ở đây nó được lưu trữ dr.private_keydưới dạng một chuỗi, nhưng tôi cần tuần tự hóa nó, vì vậy tôi mã hóa nó thành ASCII).

adder = subprocess.Popen(['ssh-add', 
        '-', # read key from stdin
     ], 
     env={'SSH_AUTH_SOCK': sockfile}, 
     stdin=subprocess.PIPE,
)
adder.communicate(dr.private_key.encode('ascii'))
retval = adder.wait()
assert retval == 0 # added successfully

Bây giờ bất cứ khi nào tôi sử dụng một số ứng dụng sử dụng SSH, ví dụ Git, tôi đều giới thiệu nó để sử dụng cùng một ổ cắm tác nhân SSH:

gitp = subprocess.Popen(
        ['git', '-C', os.path.abspath('../some-repo') ,'fetch'], 
        env={'SSH_AUTH_SOCK': sockfile}, 
        stdout=subprocess.PIPE, 
        stderr=subprocess.STDOUT,
    )
print(gitp.communicate()[0].decode('ascii'))

và nó hoạt động tốt "Tệp tạm thời" duy nhất là ổ cắm được sử dụng bởi ssh-agentnhưng nó được tạo để chỉ chủ sở hữu mới có quyền đối với nó và nó bị xóa khi bạn chấm dứt tác nhân.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.