Cho phép người dùng thông thường SSH sử dụng khóa riêng mà họ không thể đọc


8

Giả sử tôi có một bộ máy (được gọi ở đây là máy của khách hàng) chỉ một danh sách nhỏ người (được gọi là nhân viên hỗ trợ) mới được phép SSH vào, chỉ sử dụng một tài khoản bằng máy (tài khoản truy cập hỗ trợ).

Nhân viên hỗ trợ chỉ có nghĩa vụ đăng nhập vào máy của khách hàng bằng các phím. Hơn nữa, nhân viên hỗ trợ có thể phát triển, vì vậy ai đó rời khỏi nhân viên hỗ trợ không được phép đăng nhập vào bất kỳ máy khách hàng nào. Do đó, nhân viên bị cấm đọc các khóa riêng được sử dụng để đăng nhập vào máy của khách hàng. Ngoài ra, không được phép sửa đổi authorized_keystệp trên máy của khách hàng.

Để nhận ra cấu hình đó, tôi đã có ý tưởng sử dụng proxy SSH mà nhân viên hỗ trợ sẽ đăng nhập (với xác thực LDAP, nhưng đó là một vấn đề khác) và có chứa các khóa riêng.

Câu hỏi là: Làm cách nào để tôi cho phép nhân viên hỗ trợ sử dụng khóa riêng SSH mà không thể đọc được?

Tôi tin rằng tôi phải tạo một daemon chạy bằng root trên máy proxy sẽ chấp nhận yêu cầu của người dùng và mở phiên SSH cho họ, nhưng tôi không biết làm thế nào để làm điều đó. Có ý kiến ​​gì không?


Đã chỉnh sửa câu hỏi vì "máy khách" có thể khó hiểu (không có nghĩa là ngược lại với máy chủ).
Raspbeguy

Đó là rất nhiều táo bạo, và hầu hết có vẻ không liên quan. Nó gây mất tập trung. Bạn có nghĩ rằng trong tương lai bạn có thể sử dụng toàn bộ ít táo bạo hơn không? Cảm ơn bạn.
DW

Tôi giả sử rằng hạn chế ủy quyền chỉ đề cập đến các thay đổi động (ví dụ: khi một thành viên hỗ trợ mới tham gia / rời khỏi), vì bạn cần một cấu hình ban đầu trong máy khách hàng.
Ángel

Câu trả lời:


6

Tôi sẽ đề nghị một vài lựa chọn.

  1. Bảo vệ khóa ssh và yêu cầu sử dụng sudovề phía nhóm hỗ trợ của bạn. Bạn có thể làm điều này trong suốt với một trình bao bọc. Gọi trình bao bọc, nói /usr/local/bin/ssh-supportvà có chứa một cái gì đó như thế này (chưa được kiểm tra):

    #!/bin/bash
    export PATH=/usr/local/bin:/usr/bin:/bin
    export IFS=$' \t\n'
    export SUSER=ssupport
    
    # Restart if not running under sudo
    test "X$1" != 'X-S' && exec sudo -u "$SUSER" /usr/local/bin/ssh-support -S "$@"
    shift
    export SHOME="$(getent passwd "$SUSER" | cut -d: -f6)"
    
    # Extract single argument as hostname LABEL and validate that we have
    # an RSA private key for it. The target username, real hostname, port,
    # etc. can be defined in ~/.ssh/config for the user $SUSER (ssupport)
    label="$1"
    idfile="$SUSER/.ssh/id_rsa_for_$label"
    cgfile="$SUSER/.ssh/config"
    
    ok=true
    [[ "$label" =~ '/' ]] && { echo "Invalid label: $label" >&2; ok=; }
    [[ ! -s "$idfile" ]] && { echo "Missing identity file: $idfile" >&2; ok=; }
    [[ ! -s "$cgfile" ]] && { echo "Missing configuration file: $cgfile" >&2; ok=; }
    
    if test -n "$ok"
    then
        logger -t ssh-support "$SUDO_USER requested ssh to $label"
        exec ssh -i "$idfile" -F "$cgfile" "$label"
    fi
    exit 1

    Điều này sẽ yêu cầu một mục trong sudoerstệp cho phép người dùng trong supportnhóm sử dụng công cụ. Lệnh này cho phép họ chạy ssh-supportcông cụ với tư cách là ssupportngười dùng - mà bạn phải tạo. Nó không trao bất kỳ đặc quyền gốc.

    %support ALL = (ssupport) /usr/local/bin/ssh-support

    Nếu bạn hài lòng rằng người dùng hỗ trợ không cần cung cấp mật khẩu của riêng họ để chạy công cụ (theo yêu cầu của lệnh sudogọi trong chính tập lệnh), bạn có thể sửa đổi sudoersđịnh nghĩa như vậy:

    %support ALL = (ssupport) NOPASSWD: /usr/local/bin/ssh-support

    Giả sử PATHcó chứa /usr/local/bin/sau đó bạn sẽ gọi nó với ssh-support clientname. Cũng giả sử rằng bạn đã tạo ssupportngười dùng như /home/ssupportbạn sẽ tạo /home/ssupport/.ssh/id_rsa_clientname/home/ssupport/.ssh/id_rsa_clientname.publà cặp chứng chỉ và có một mục nhập máy chủ lưu trữ /home/ssupport/.ssh/configcho clientnamengười dùng, máy chủ, cổng, v.v. đã xác định cho máy đích. Bạn có thể sẽ vô hiệu hóa chuyển tiếp X11, chuyển tiếp cổng, vv một cách rõ ràng. Như thường lệ, /home/ssupport/.sshthư mục sẽ cần được bảo vệ với quyền 0700.

  2. Cung cấp cho mỗi thành viên hỗ trợ tài khoản người dùng cục bộ của riêng họ và yêu cầu mỗi người sử dụng khóa ssh riêng của họ để truy cập vào máy chủ của khách hàng. Khi một người rời khỏi nhóm hỗ trợ, bạn xóa khóa ssh của họ khỏi máy chủ của khách hàng. Điều này có nghĩa là bạn không còn phải lo lắng về việc ngăn nhân viên của mình biết khóa ssh riêng.


Tùy chọn thứ hai không hợp lệ. Như tôi đã nói, chỉ có một tài khoản hỗ trợ trên các máy khách và bạn không thể thêm khóa chung vào cấu hình ssh, đó là quy tắc. Trong thực tế, bạn không thể sửa đổi bất cứ điều gì về cấu hình ssh trên các máy khách.
Raspbeguy

4
Nhân tiện, câu trả lời này là một ví dụ điển hình của (ab) sử dụng sudo. Tôi đã viết một bài viết về chủ đề này ( dmitry.khlebnikov.net/2015/07/ trên ), dường như có một xu hướng để cố gắng giải quyết bất cứ điều gì bằng sudo. Tuy nhiên, điều này chỉ làm suy yếu tính bảo mật của hệ thống của bạn và không cải thiện nó.
thiên hà

1
@Raspbeguy tất nhiên họ sẽ không. Các sudoersgiới hạn dòng truy cập vào các lệnh đơn
roaima

1
Bạn chuyển các tùy chọn không được kiểm tra sang ssh với "$ @" chạy bằng root! Tôi có thể nghĩ ra các cách khác nhau để ether các tệp hệ thống bị hỏng (sử dụng -Eđể nối thêm), chuyển tiếp các cổng đặc quyền ( -L,-R,-D) hoặc đơn giản là lấy root ( -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'. Nhận xét từ thiên hà về việc lạm dụng sudo là đúng tại chỗ!
nkms

1
@roaima: Vì vậy, dù sao đi nữa, ý tưởng sudo to root của bạn có vấn đề, nhưng chúng là những vấn đề khác với những bài đăng trên blog của thiên hà. Anh ấy đang nói về ssh root@somewherechìa khóa, so với ssh user@somewheresudo. Đó thực sự là một điểm tốt. Tuy nhiên, cách duy nhất nó áp dụng cho trường hợp này ssh keyowner@localhost ssh_to_client client.example.org là cách thay thế sudo -u keyowner ssh_to_client client.example.org. Tương tự như sudo, SSH có thể giới hạn các lệnh mà người dùng được phép chạy. Chúng ta đang nói về sudo không mật khẩu để không root, không phải trường hợp sử dụng của Galaxy.
Peter Cordes

11

Những gì bạn thực sự muốn làm là sử dụng SSH CA và ký các khóa được sử dụng bởi mỗi người hỗ trợ (họ nên có khóa ssh riêng, như hộ chiếu) và định cấu hình máy chủ của khách hàng của bạn để sử dụng TrustedUserCAKeys /etc/ssh/users_ca.pubtrong / etc / ssh / sshd_config. Bằng cách này, máy chủ sẽ chấp nhận bất kỳ khóa nào được ký bởi khóa CA (mà bạn có quyền truy cập) và bạn sẽ có thể thu hồi khóa của những người không còn hỗ trợ mà thậm chí không chạm vào ủy quyền.

Một tìm kiếm nhanh cho "ssh ca" đã chỉ ra hướng dẫn này: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clents-with -ubfox (cuộn xuống "Cách cấu hình khóa người dùng") - mặc dù hướng dẫn đề cập đến Ubuntu là phân phối độc lập, nhưng bạn cần một phiên bản OpenSSH mới hỗ trợ SSH CA

Một mục blog hay khác về chủ đề này là https://ef.gy/hardening-ssh (cuộn xuống "Chứng chỉ SSH").

Đặc biệt chú ý rằng bạn có thể ký khóa để có hiệu lực trong một thời gian giới hạn, vì vậy chúng sẽ tự động hết hạn!


Sẽ là một ý tưởng tốt nếu máy của khách hàng có quyền truy cập internet (để cập nhật tính hợp lệ của chữ ký), điều này không phải luôn luôn như vậy. Chúng tôi kết nối với các máy này thông qua VPN do khách hàng cung cấp.
Raspbeguy

Chà, điều này gần đến mức bạn có thể nhận được mà không bị rò rỉ chìa khóa với một người rời công ty của bạn. Tôi đã cung cấp cho bạn cơ chế, bạn có thể tự động hóa nó, ví dụ bạn có thể có một nhân viên nghĩa vụ hỗ trợ nhân sự của bạn khi mọi người rời khỏi công ty và bạn có thể xác định một quy trình về cách thu hồi khóa.
thiên hà

1
Hơn nữa, bạn có thể ký một khóa (một người hỗ trợ) trong một thời gian giới hạn - ví dụ: bạn có thể ký nó chỉ trong 8 giờ (đối với ca làm việc của họ), sau 8 giờ nó sẽ hết hạn và máy chủ sẽ không cho phép họ vào.
galaxy

3
Về phần LDAP của bạn - Tôi hiện đang làm việc tại một công ty quản lý hàng trăm trường hợp và chúng tôi đang nghiên cứu một giải pháp nguồn mở để tích hợp SAML 2.0 và SSH CA. Ý tưởng là một người xác thực bằng SSO và nếu được ủy quyền sẽ nhận được các khóa của họ được ký trong một khoảng thời gian xác định (ví dụ 5 phút). Tất cả điều này khá minh bạch đối với người dùng và được triển khai bằng ProxyCommand của ~ / .ssh / config.
thiên hà

2

Có một vài câu trả lời khác nhau liên quan đến tập lệnh bao bọc cho ssh được gọi thông qua sudo hoặc setuid-execable (với một số tài khoản không phải mục đích đặc biệt ). Như nkms nói , việc chuyển qua tất cả các đối số sang ssh cho phép người dùng thực hiện những việc tùy ý bằng các phím ssh mà chúng tôi đang cố gắng bảo vệ. Một số cực đoan khác đã đưa ra là chỉ cho phép một tên máy chủ.

OP cho biết các quản trị viên cần có khả năng tải lên mọi thứ.

Bạn có thể có hai hàm bao cố định-ss-to-ssh khác nhau. Một cho shell đăng nhập, một cho scp. Không có đối số do người dùng cung cấp ngoài tên máy chủ (và tên tệp để tải lên).

Hoặc một tập lệnh bao bọc sử dụng getoptchính nó để phân tích các tùy chọn rất hạn chế và cắm mọi thứ vào một lệnh ssh được cố định nhiều nhất. Bỏ qua (hoặc lỗi) trên các tùy chọn không được công nhận sẽ là cách để đi.

Đừng cố lọc các tùy chọn ssh "nguy hiểm", chỉ cần viết một trình bao bọc có thể thực hiện hai việc: đăng nhập tương tác hoặc tải lên một tệp (tên tệp cục bộ và từ xa). Bạn vẫn cần phải làm một số vệ sinh ở đó, tôi đoán.

Trên thực tế, điều này vẫn dễ dàng để có được sai. Bạn phải tìm cách ngăn người dùng đưa tệp giữ các khóa ssh làm tệp cục bộ. Vì vậy, bạn vẫn đang cố gắng nghĩ về mọi thứ cần phải không được phép, thay vì bắt đầu từ việc không cho phép bất cứ điều gì. Sẽ là một sự khởi đầu để đảm bảo tên tệp không chứa bất kỳ @hoặc :.


Ý tưởng bao bọc thực sự là giải pháp, nhưng điều đó hàm ý một vi phạm bảo mật cần được lấp đầy.
Raspbeguy

Tôi ngạc nhiên về cách mọi người đang phát minh lại bánh xe khi không có nhu cầu. Chức năng SSH CA được giới thiệu chính xác cho OpenSSH vì những lý do và tình huống như câu hỏi ban đầu. Giải pháp của tôi đã không sử dụng bất kỳ trình bao bọc nào và đạt được chính xác những gì được hỏi, tuy nhiên, vì một số lý do, @Raspbeguy đã quyết định đi theo cách DIY với ý nghĩa bảo mật đáng ngờ. :)
thiên hà

@gal Wax: yeah, chắc chắn giải pháp SSH CA của bạn là giải pháp tốt nhất, trừ khi bạn có yêu cầu tuyệt đối rằng bạn không thể thay đổi một lần đối với các hệ thống từ xa để định cấu hình sshd của chúng để sử dụng. Nghe có vẻ hoàn hảo, và dễ dàng để có được đúng.
Peter Cordes

@gal Wax: giải pháp của bạn thực sự thanh lịch, nhưng không áp dụng trong trường hợp của tôi như tôi đã nói với bạn trước đó. Tôi thực sự thích ý tưởng này, tôi đã nói về nó với sếp của tôi nhưng nó vẫn không thể. Không cần phải khó chịu.
Raspbeguy

1
@Raspbeguy, tôi không buồn, tôi chỉ không hiểu tại sao công ty của bạn muốn hy sinh bảo mật của họ và thực hiện một cái gì đó bằng cách sử dụng "băng keo" khi có một cách thích hợp để làm điều đó. Và nhận xét của bạn là nó sẽ là một giải pháp tốt, nhưng bạn không thích rằng bạn không thể tự động hóa việc thu hồi - và tôi cũng cung cấp cho bạn giải pháp cho vấn đề này (chỉ bằng cách ký khóa cho ca làm việc). Dù sao, bạn đã chọn câu trả lời của mình, hãy tiếp tục :)
galaxy

1

Nếu bạn thiết lập máy chủ proxy SSH, bạn có thể sắp xếp rằng shell (in /etc/passwd) của nhân viên của bạn không được đặt thành shell như bash, mà thay vào đó là một tập lệnh đơn giản không cho phép truy cập shell. Thay vào đó, nó sẽ yêu cầu một tên máy chủ đích ( read target) exec ssh "support@$target".

Lưu ý rằng việc sử dụng proxy như thế này có thể gây khó khăn khi sử dụng các công cụ như scpchuyển tệp đến / từ máy của khách hàng. Đây có thể là một vấn đề hoặc một lợi thế!


Đây là ý tưởng của trình bao bọc tương tự như ý tưởng của @ roaima. Bạn đang cấp quyền truy cập cho nó bằng ssh, nhưng sudocũng hoạt động. Câu trả lời của anh ấy là đề xuất sử dụng người dùng root cục bộ, nhưng người dùng không root cũng sẽ làm việc. Xem ý kiến ​​của tôi về câu trả lời của anh ấy để thảo luận về điều đó. ( ssh keyowner@localhostÝ tưởng của tôi giống như ý tưởng của bạn.)
Peter Cordes

@Peter - hoàn toàn đúng: root hoàn toàn là người dùng sai cho việc này!
Toby Speight

Hỗ trợ kẻ phải tải lên mọi thứ, vì vậy giải pháp này có thể không hoạt động.
Raspbeguy

@Raspbeguy: đã đăng một câu trả lời giải quyết vấn đề này. Sử dụng kết hợp với sudothiết lập không root của roaima .
Peter Cordes

0

Những người hỗ trợ của bạn luôn kết nối thông qua máy proxy đó và chỉ từ nó, vì vậy khách hàng có thể chỉ cần xác thực máy proxy bằng HostbasingAuthentication .

Giả sử máy proxy là supporters.pcvà bạn cung cấp hỗ trợ chocustomer.pc

customer.pc sẽ có HostbasingAuthentication có trong /etc/ssh/ssd_config, supporters.pc được liệt kê trong /etc/ssh/shosts.equivvà khóa công khai của nó trong /etc/ssh/ssh_known_hosts.

Khi nhân viên hỗ trợ của bạn đăng nhập vào support@supporters.pc và thực hiện ssh customer.pc, nó sẽ sinh ra ssh-Keysign (8) (cần được setuid), sẽ xử lý việc ký khóa với tệp bạn không thể đọc và cung cấp bằng chứng để supporters.pc rằng kết nối được thực sự đến từ supporters.pc . Vì customer.pc tin tưởng những người ủng hộ.pc , nhân viên của bạn được đăng nhập với tư cách là hỗ trợ .


Đây là một giải pháp khủng khiếp theo quan điểm bảo mật vì nếu bạn cấp toàn quyền truy cập vào một máy và bạn sẽ mất trách nhiệm về việc ai đã làm gì. Niềm tin từ máy đến máy nên bị cấm trong thế giới hiện đại, nơi bảo mật CNTT bắt đầu nổi lên như một chủ đề khá nóng.
thiên hà

@gal Wax, từ OP tôi hiểu là về cơ bản họ đã làm điều đó. Sự tin tưởng vào máy đó là trong đặc điểm kỹ thuật . Đặc biệt lưu ý rằng họ "chỉ sử dụng một tài khoản bằng máy (tài khoản truy cập hỗ trợ)" có thể họ đang sử dụng tài khoản dùng chung trong customer.pc, nhưng kết nối với máy chủ với tư cách là người dùng của họ. Thay đổi quyền của ssh và ssh-keygen để buộc ssh -u hỗ trợ ssh sẽ giải quyết điều đó và cũng thêm một mục nhật ký.
Ángel

0

Sử dụng nhị phân bao bọc

Đối với trường hợp sử dụng cụ thể này (xem ghi chú quan trọng bên dưới), một khả năng là tạo một người dùng (giả sử support-ssh) cụ thể cho các kết nối SSH gửi đi này, sau đó cài đặt một nhị phân bao bọc nhỏ thực thi /usr/bin/ssh.

  • Đừng sao chép + chmod sshchính nhị phân, vì bạn sẽ không nhớ sao chép lại mỗi khi bạn áp dụng các cập nhật bảo mật.
  • Và đừng sử dụng rootnhư người dùng đặc quyền hơn, vì những lý do tôi tin tưởng là hiển nhiên.

Đây là một giải pháp thay thế tương đương về chức năng để sử dụng sudođể nâng cao các đặc quyền của support-sshtài khoản với sự đánh đổi sau:

  • Điều này nhỏ hơn và gọn hơn sudo, do đó, ít có nguy cơ lỗi cấu hình mở ra nhiều hơn bạn dự định.
  • Bạn có trách nhiệm mã hóa nó một cách chính xác - chỉ làm điều này nếu bạn cực kỳ cẩn thận và (lý tưởng) có kinh nghiệm về mã hóa bảo mật quan trọng.
  • Nó có thể được điều chỉnh để cụ thể hơn sudo(nhưng bạn viết càng nhiều mã, bạn càng cần phải kiểm toán để bảo mật).

Nhị phân của trình bao bọc nên được đặt HOMEvào thư mục chính của support-sshngười dùng, do đó sshsẽ chọn ssh_configkhóa riêng và khóa thích hợp . Nhưng người dùng yêu cầu không được phép đọc ~support-ssh/.ssh/hoặc nội dung của nó.

Trình bao bọc có thể đơn giản như:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    setenv("HOME", "/home/support-ssh", 1);
    /* allow only a single, non-option argument */
    if (argc!=2 || *argv[1]=='-') {
        fprintf(stderr, "Usage: %s <hostname>", argv[0]);
        exit(EXIT_FAILURE);
    }
    execv("/usr/bin/ssh", argv);
    return EXIT_FAILURE;
}

Bạn có thể muốn hạn chế hơn và kiểm tra xem đối số argv[1]có nằm trong một tập hợp các tên máy chủ được phép không. Hoặc ít hạn chế hơn và cho phép (một tập hợp con) đối số tùy chọn. Bạn có thể muốn thay thế hoàn toàn các biến môi trường (nhưng giữ những người quan trọng như TERM, LC_*, vv); lưu ý rằng LD_LIBRARY_PATHLD_PRELOADđặc biệt nguy hiểm.

Một chương trình bao bọc tương tự có thể được cung cấp scpnếu cần.

Một lưu ý về khả năng ứng dụng

Câu trả lời này giải quyết các trường hợp cụ thể của câu hỏi, trong đó người dùng có nghĩa vụ theo hợp đồng phải tuân theo các thủ tục và có các biện pháp trừng phạt (ví dụ như sa thải) vì vi phạm chúng. Nó cho rằng bạn muốn ngăn chặn các nhân viên tình cờ sao chép các khóa riêng tư xung quanh, thay vì ngăn chặn một kẻ tấn công xác định có được quyền truy cập trái phép.

Tôi cho rằng an ninh đạt được thông qua cả phòng thủ kỹ thuật và phi kỹ thuật, và sự cân bằng đạt được ở đây hoặc bằng cách sử dụng sudolà phù hợp với tình huống được đưa ra.


Bạn chuyển các đối số không được kiểm tra để ssh chạy như một người dùng khác, hãy xem nhận xét của tôi về câu trả lời ở trên. Tôi vẫn có thể đọc khóa ... và tôi sẽ không dựa vào kiểm tra đối số chặt chẽ, ssh không có nghĩa là được chạy theo cách đó.
nkms

@nkms - Tôi đã làm cho trình bao bọc hạn chế hơn. Nó có thể được mở rộng hơn nếu được yêu cầu, nhưng bạn có quyền khóa mọi thứ trừ khi có yêu cầu khác, thay vì ngược lại.
Toby Speight

@TobySpeight: yup, có vẻ tốt. Tôi đặt hầu hết những gì tôi nói trong các bình luận vào câu trả lời của riêng tôi.
Peter Cordes

1
Nó sẽ tốt hơn để sử dụng sudo hơn là một trình bao bọc nhị phân. Trái ngược với những gì bạn tuyên bố, sử dụng sudo ít rủi ro hơn nhiều so với việc tự lăn. Sudo có mặc định an toàn. Làm thế nào chắc chắn rằng bạn đã không quên để loại bỏ một biến môi trường sẽ ảnh hưởng đến ssh?
Gilles 'SO- ngừng trở nên xấu xa'
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.