Izinkan pengguna biasa ke SSH menggunakan kunci pribadi yang tidak dapat mereka baca

8

Katakanlah saya memiliki satu set mesin (disebut mesin pelanggan) yang hanya daftar kecil orang (disebut staf pendukung) yang diizinkan masuk ke SSH, menggunakan hanya satu akun dengan mesin (akun akses dukungan).

Staf pendukung hanya seharusnya login ke mesin pelanggan menggunakan kunci. Selain itu, staf pendukung dapat berevolusi, sehingga seseorang yang meninggalkan staf pendukung tidak diizinkan masuk ke mesin pelanggan mana pun. Oleh karena itu, staf orang dilarang membaca kunci pribadi yang digunakan untuk masuk ke mesin pelanggan. Juga, dilarang untuk memodifikasi authorized_keysfile di mesin pelanggan.

Untuk mewujudkan konfigurasi itu, saya punya ide untuk menggunakan SSH proxy yang akan didukung oleh staf pendukung (dengan otentikasi LDAP, tapi itu masalah lain) dan yang berisi kunci pribadi.

Pertanyaannya adalah: Bagaimana cara saya mengizinkan staf pendukung untuk menggunakan kunci pribadi SSH tanpa bisa membacanya?

Saya percaya bahwa saya harus membuat daemon yang berjalan sebagai root pada mesin proxy yang akan menerima permintaan pengguna dan membuka sesi SSH untuk mereka, tetapi saya tidak tahu bagaimana melakukannya. Ada ide?

Raspbeguy
sumber
Mengedit pertanyaan karena "mesin klien" mungkin sulit dipahami (tidak berarti kebalikan dari server).
Raspbeguy
Itu sangat banyak yang berani, dan sebagian besar tampaknya tidak ada. Itu mengganggu. Apakah Anda berpikir di masa depan Anda bisa menggunakan jauh lebih sedikit berani? Terima kasih.
DW
Saya berasumsi bahwa pembatasan otorisasi hanya merujuk pada perubahan dinamis (mis. Ketika anggota dukungan baru bergabung / keluar), karena Anda memerlukan konfigurasi awal di mesin pelanggan.
Ángel

Jawaban:

6

Saya akan menyarankan beberapa opsi.

  1. Lindungi kunci ssh dan minta penggunaan sudodi sisi tim pendukung Anda. Anda bisa melakukan ini secara transparan dengan pembungkus. Panggil pembungkus, katakan, /usr/local/bin/ssh-supportdan minta agar berisi sesuatu seperti ini (belum diuji):

    #!/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

    Ini akan membutuhkan entri dalam sudoersfile yang memungkinkan pengguna dalam supportgrup untuk menggunakan alat ini. Perintah ini memungkinkan mereka untuk menjalankan ssh-supportalat sebagai ssupportpengguna - yang harus Anda buat. Itu tidak memberi hak root.

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

    Jika Anda senang bahwa pengguna dukungan tidak perlu memberikan kata sandi mereka sendiri untuk menjalankan alat (seperti yang diminta oleh sudodoa dalam skrip itu sendiri) Anda dapat mengubah sudoersdefinisi sebagai berikut:

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

    Dengan asumsi PATHada /usr/local/bin/Anda akan menyebutnya dengan ssh-support clientname. Juga dengan asumsi Anda telah membuat ssupportpengguna seperti yang /home/ssupportAnda buat /home/ssupport/.ssh/id_rsa_clientnamedan /home/ssupport/.ssh/id_rsa_clientname.pubsebagai pasangan sertifikat, dan memiliki entri host /home/ssupport/.ssh/configuntuk clientnameyang menentukan pengguna, host, port, dll untuk mesin target. Anda mungkin akan menonaktifkan penerusan X11, penerusan porta, dll. Secara eksplisit. Seperti biasa, /home/ssupport/.sshdirektori perlu dilindungi dengan izin 0700.

  2. Berikan masing-masing anggota dukungan akun pengguna lokal mereka sendiri, dan mintalah setiap orang menggunakan kunci ssh pribadi mereka sendiri untuk mengakses server klien. Ketika seseorang meninggalkan grup dukungan, Anda menghapus kunci ssh mereka dari server klien. Ini berarti bahwa Anda tidak perlu lagi khawatir tentang mencegah staf Anda mengetahui kunci ssh pribadi.

roaima
sumber
Opsi kedua tidak valid. Seperti yang saya katakan hanya ada satu akun dukungan di server klien dan Anda tidak dapat menambahkan kunci publik ke konfigurasi ssh, itulah aturannya. Bahkan, Anda tidak dapat mengubah apa pun tentang konfigurasi ssh di mesin klien.
Raspbeguy
4
Omong-omong, jawaban ini adalah contoh khas (ab) menggunakan sudo. Saya menulis artikel tentang topik ini ( dmitry.khlebnikov.net/2015/07/… ), sepertinya ada kecenderungan untuk mencoba menyelesaikan sesuatu menggunakan sudo. Namun, ini hanya melemahkan keamanan sistem Anda dan tidak memperbaikinya.
galaksi
1
@ Raspbeguy tentu saja mereka tidak mau. The sudoersbatas garis akses ke satu perintah
roaima
1
Anda memberikan opsi yang tidak dicentang ke ssh dengan "$ @" yang berjalan sebagai root! Saya dapat memikirkan berbagai cara untuk eter file sistem yang korup (digunakan -Euntuk menambahkan), meneruskan port istimewa ( -L,-R,-D) atau hanya mendapatkan root ( -o PermitLocalCommand=yes -o 'LocalCommand=/bin/bash'. Komentar dari galaksi tentang penyalahgunaan sudo ada di tempat yang benar!
nkms
1
@roaima: Jadi, sudo Anda untuk root ide memiliki masalah, tapi itu masalah yang berbeda dari yang dibicarakan oleh posting blog galaksi. Dia berbicara tentang ssh root@somewherekunci, vs. ssh user@somewherekemudian sudo. Ini sebenarnya poin yang sangat bagus. Namun, satu-satunya cara itu berlaku untuk kasus ini adalah itu ssh keyowner@localhost ssh_to_client client.example.org adalah alternatif sudo -u keyowner ssh_to_client client.example.org. Mirip dengan sudo, SSH dapat membatasi perintah yang diizinkan dijalankan oleh pengguna. Kita berbicara tentang sudo tanpa kata sandi ke non-root, bukan kasus penggunaan Galaxy.
Peter Cordes
11

Apa yang benar-benar ingin Anda lakukan adalah menggunakan SSH CA dan menandatangani kunci yang digunakan oleh masing-masing orang yang mendukung (mereka harus memiliki kunci ssh sendiri, seperti paspor) dan mengonfigurasi server klien Anda untuk menggunakan TrustedUserCAKeys /etc/ssh/users_ca.pubdi / etc / ssh / sshd_config. Dengan cara ini server akan menerima kunci apa pun yang ditandatangani oleh kunci CA (yang dapat Anda akses) dan Anda akan dapat mencabut kunci orang yang tidak lagi mendukung tanpa menyentuh tombol_wenang resmi.

Pencarian cepat untuk "ssh ca" menunjuk ke tutorial ini: https://www.digitalocean.com/community/tutorials/how-to-create-an-ssh-ca-to-validate-hosts-and-clients-with -ubuntu (gulir ke bawah ke "Cara Mengonfigurasikan Kunci Pengguna") - walaupun tutorial menyebutkan Ubuntu distribusinya independen, tetapi Anda memerlukan versi baru OpenSSH yang mendukung SSH CA

Entri blog lain yang bagus tentang topik ini adalah https://ef.gy/hardening-ssh (gulir ke bawah ke "sertifikat SSH").

Perhatikan bahwa Anda dapat menandatangani kunci agar valid untuk waktu yang terbatas, sehingga secara otomatis kedaluwarsa!

galaksi
sumber
Ini akan menjadi ide yang baik jika mesin pelanggan memiliki akses ke internet (untuk memperbarui validitas tanda tangan), yang tidak selalu terjadi. Kami terhubung ke mesin-mesin ini melalui VPN yang disediakan oleh pelanggan.
Raspbeguy
Yah, ini sedekat yang Anda bisa dapatkan tanpa membocorkan kunci dengan seseorang yang meninggalkan perusahaan Anda. Saya memberi Anda mekanisme, Anda dapat mengotomatisasi, misalnya Anda dapat memiliki petugas jaga yang mendukung SDM Anda ketika orang-orang meninggalkan perusahaan dan Anda dapat menentukan prosedur tentang cara mencabut kunci.
galaksi
1
Selain itu, Anda dapat menandatangani kunci (dukungan satu orang) untuk waktu yang terbatas - misalnya Anda dapat menandatanganinya hanya selama 8 jam (untuk shift mereka), setelah 8 jam akan kedaluwarsa dan server tidak akan membiarkan mereka masuk.
galaxy
3
Mengenai bagian LDAP Anda - Saya saat ini bekerja di perusahaan yang mengelola ratusan instance dan kami sedang mengerjakan solusi open source untuk mengintegrasikan SAML 2.0 dan SSH CA. Idenya adalah bahwa seseorang mengotentikasi menggunakan SSO dan jika berwenang mendapatkan kunci mereka ditandatangani untuk jangka waktu tertentu (misalnya 5 menit). Semua ini cukup transparan bagi pengguna dan diimplementasikan menggunakan ~ / .ssh / config's ProxyCommand.
galaksi
2

Ada beberapa jawaban berbeda yang melibatkan skrip wrapper untuk ssh yang dipanggil melalui sudo atau setuid-executable (ke beberapa akun non-root dengan tujuan khusus ). Seperti dikatakan nkms , melewati semua argumen ke ssh memungkinkan pengguna melakukan hal-hal yang sewenang-wenang dengan kunci ssh yang kami coba lindungi. Ekstrem lainnya yang muncul adalah membiarkan hanya nama host saja.

OP mengatakan admin harus dapat mengunggah sesuatu.

Anda dapat memiliki dua pembungkus fixed-args-to-ssh yang berbeda. Satu untuk shell login, satu lagi untuk scp. Tidak ada argumen yang disediakan pengguna selain nama host (dan nama file yang akan diunggah).

Atau skrip wrapper yang menggunakan getoptdirinya sendiri untuk mem-parsing opsi yang sangat terbatas, dan menyambungkannya dengan perintah ssh yang sebagian besar sudah diperbaiki. Mengabaikan (atau salah) pada opsi yang tidak dikenali akan menjadi cara untuk melakukannya.

Jangan mencoba memfilter opsi ssh "berbahaya", cukup tulis pembungkus yang dapat melakukan dua hal: login interaktif, atau unggah file (nama file lokal dan jarak jauh). Anda masih perlu melakukan sanitasi di sana, saya kira.

Sebenarnya, ini masih mudah salah. Anda harus menemukan cara untuk menghentikan pengguna memberikan file memegang kunci ssh sebagai file lokal. Jadi, Anda masih mencoba memikirkan segala hal yang perlu dianulir, alih-alih mulai dari tidak membiarkan apa pun. Ini akan menjadi awal untuk memastikan nama file tidak mengandung @atau :.

Peter Cordes
sumber
Ide pembungkus memang solusinya, tetapi itu menyiratkan pelanggaran keamanan yang perlu diisi.
Raspbeguy
Saya kagum bagaimana orang menemukan kembali roda ketika tidak perlu. Fungsionalitas SSH CA diperkenalkan ke OpenSSH tepat untuk alasan dan situasi seperti pertanyaan awal. Solusi saya tidak menggunakan pembungkus dan mencapai apa yang diminta, namun, untuk beberapa alasan @Raspbeguy memutuskan untuk menggunakan cara DIY dengan implikasi keamanan yang dipertanyakan. :)
galaxy
@galaxy: yeah, solusi SSH CA Anda adalah yang terbaik, kecuali jika Anda memiliki persyaratan mutlak bahwa Anda tidak dapat membuat perubahan satu kali ke sistem jarak jauh untuk mengonfigurasi sshd mereka untuk menggunakannya. Kedengarannya sempurna, dan mudah dilakukan.
Peter Cordes
@galaxy: solusi Anda sangat elegan, tetapi tidak berlaku dalam kasus saya seperti yang saya katakan sebelumnya. Saya sangat suka ide itu, saya membicarakannya dengan bos saya tetapi itu masih mustahil. Tidak perlu kesal.
Raspbeguy
1
@ Raspbeguy, saya tidak kecewa, saya hanya tidak mengerti mengapa perusahaan Anda ingin mengorbankan keamanan mereka dan mengimplementasikan sesuatu menggunakan "lakban" ketika ada cara yang tepat untuk melakukannya. Dan komentar Anda adalah bahwa itu akan menjadi solusi yang baik, tetapi Anda tidak suka bahwa Anda tidak dapat mengotomatiskan pencabutan - dan saya memberikan Anda solusi untuk ini juga (dengan menandatangani kunci untuk shift saja). Bagaimanapun, Anda memilih jawaban Anda, mari kita lanjutkan :)
galaksi
1

Jika Anda menyiapkan server proxy SSH, Anda dapat mengatur agar shell (in /etc/passwd) pengguna pengguna Anda tidak disetel ke shell seperti bash, melainkan ke skrip sederhana yang tidak memungkinkan akses shell. Sebagai gantinya, ia akan meminta nama host target ( read target), kemudian exec ssh "support@$target".

Perhatikan bahwa menggunakan proxy seperti ini mungkin menyulitkan untuk menggunakan alat seperti scpuntuk mentransfer file ke / dari mesin pelanggan. Ini mungkin masalah atau keuntungan!

Toby Speight
sumber
Ini adalah ide skrip wrapper mirip dengan ide @ roaima. Anda memberikan akses ke sana dengan ssh, tetapi sudojuga berfungsi. Jawabannya menyarankan menggunakan pengguna root lokal, tetapi pengguna non-root juga akan berfungsi. Lihat komentar saya pada jawabannya untuk diskusi tentang itu. ( ssh keyowner@localhostIde saya sama dengan ide Anda.)
Peter Cordes
@ Peter - cukup benar: root benar -benar pengguna yang salah untuk ini!
Toby Speight
Orang-orang pendukung harus mengunggah sesuatu, jadi solusi ini mungkin tidak berfungsi.
Raspbeguy
@ Raspbeguy: memposting jawaban yang membahas hal ini. Gunakan dalam kombinasi dengan pengaturan non-root roaima sudo.
Peter Cordes
0

Orang-orang dukungan Anda selalu terhubung melalui mesin proxy itu, dan hanya dari itu, sehingga klien dapat dengan mudah mengotentikasi mesin proxy menggunakan HostbasedAuthentication .

Katakanlah mesin proxy itu supporters.pcdan Anda memberikan dukungancustomer.pc

customer.pc akan memiliki HostbasedAuthentication ya di /etc/ssh/ssd_config, pendukung.pc terdaftar /etc/ssh/shosts.equivdan kunci publiknya /etc/ssh/ssh_known_hosts.

Ketika staf dukungan Anda masuk ke [email protected], dan melakukan ssh customer.pc, itu akan menelurkan ssh-keysign (8) (yang perlu diatur secara tepat), yang akan menangani penandatanganan kunci dengan file-Anda-tidak bisa membaca dan berikan bukti kepada suporter.pc bahwa koneksi memang berasal dari suporter.pc . Sebagai customer.pc mempercayai pendukung.pc , anggota staf Anda akan masuk sebagai dukungan .

Malaikat
sumber
Ini adalah solusi yang mengerikan dari sudut pandang keamanan karena jika Anda memberikan akses ke mesin secara keseluruhan dan Anda kehilangan akuntabilitas siapa yang melakukan apa. Kepercayaan mesin-ke-mesin harus dilarang dari dunia modern di mana keamanan TI mulai muncul sebagai topik yang cukup panas.
galaksi
@ Galaxy, dari OP pemahaman saya adalah bahwa mereka pada dasarnya sudah melakukan itu. Kepercayaan pada mesin itu adalah dalam spesifikasi . Perhatikan secara khusus bahwa mereka "hanya menggunakan satu akun oleh mesin (akun akses dukungan)" mungkin saja mereka menggunakan akun bersama di customer.pc, tetapi terhubung ke server sebagai pengguna mereka sendiri. Mengubah izin ssh dan ssh-keygen untuk memaksa dukungan sudo -u ssh ... akan menyelesaikannya dan juga menambahkan entri log.
Ángel
0

Gunakan biner pembungkus

Untuk kasus penggunaan khusus ini (lihat catatan penting di bawah), satu kemungkinan adalah membuat pengguna (katakanlah support-ssh) khusus untuk koneksi SSH keluar ini, kemudian instal biner pembungkus kecil yang dijalankan /usr/bin/ssh.

  • Jangan menyalin + chmod sshbiner itu sendiri, karena Anda tidak akan ingat untuk menyalinnya kembali setiap kali Anda menerapkan pembaruan keamanan.
  • Dan jangan gunakan rootsebagai pengguna yang lebih istimewa, karena alasan yang saya percayai sudah jelas.

Ini adalah alternatif yang setara secara fungsional untuk digunakan sudountuk meningkatkan hak istimewa dengan support-sshakun dengan trade-off berikut:

  • Ini lebih kecil dan lebih ramping daripada sudo, jadi ada sedikit risiko kesalahan konfigurasi yang membuka lebih dari yang Anda inginkan.
  • Merupakan tanggung jawab Anda untuk mengkodekannya dengan benar - hanya lakukan ini jika Anda sangat berhati - hati dan (idealnya) memiliki pengalaman pengkodean yang sangat penting untuk keamanan.
  • Itu dapat dirancang untuk menjadi lebih spesifik daripada sudo(tetapi semakin banyak kode yang Anda tulis, semakin Anda perlu mengaudit untuk keamanan).

Biner pembungkus harus diatur HOMEke support-sshdirektori home pengguna, sehingga sshakan mengambil ssh_configkunci pribadi yang sesuai . Tetapi pengguna yang memohon sebaiknya tidak diizinkan membaca ~support-ssh/.ssh/atau kontennya.

Pembungkus bisa sesederhana:

#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;
}

Anda mungkin ingin menjadi lebih ketat, dan memeriksa apakah argumennya argv[1]adalah sekumpulan nama host yang diizinkan. Atau kurang membatasi, dan memungkinkan (sebagian) argumen opsi. Anda mungkin ingin sepenuhnya menggantikan variabel lingkungan (tapi tetap yang penting seperti TERM, LC_*, dll); perhatikan itu LD_LIBRARY_PATHdan LD_PRELOADsangat berbahaya.

Program pembungkus serupa dapat disediakan scpjika diperlukan.

Catatan tentang penerapan

Jawaban ini membahas keadaan khusus dari pertanyaan, di mana pengguna secara kontraktual diwajibkan untuk mengikuti prosedur, dan ada sanksi (misalnya pemecatan) karena melanggar mereka. Itu mengandaikan bahwa Anda ingin mencegah karyawan dengan mudah menyalin kunci privat di sekitar, daripada mencegah penyerang yang tekun mendapatkan akses yang tidak sah.

Saya mengambil pandangan bahwa keamanan dicapai melalui pertahanan teknis dan non-teknis, dan bahwa keseimbangan yang dicapai di sini atau dengan menggunakan sudosesuai untuk situasi yang disajikan.

Toby Speight
sumber
Anda memberikan argumen yang tidak dicentang untuk menjalankan ssh sebagai pengguna lain, lihat komentar saya pada jawaban di atas. Saya masih bisa membaca kunci ... dan saya tidak akan mengandalkan pemeriksaan argumen yang ketat, ssh tidak dimaksudkan untuk dijalankan dengan cara itu.
nkms
@ nkms - Saya telah membuat bungkusnya lebih ketat. Itu dapat dibuat lebih terbuka jika diperlukan, tetapi Anda benar untuk mengunci semuanya kecuali sebagaimana diminta sebaliknya, bukan sebaliknya.
Toby Speight
@TobySpeight: yup, terlihat bagus. Saya memasukkan sebagian besar dari apa yang saya katakan di komentar ke dalam jawaban saya sendiri.
Peter Cordes
1
Akan lebih baik menggunakan sudo daripada pembungkus biner. Bertentangan dengan apa yang Anda klaim, menggunakan sudo jauh lebih berisiko daripada menggulung sendiri. Sudo memiliki standar keamanan. Seberapa yakin Anda bahwa Anda tidak lupa menghapus variabel lingkungan yang akan memengaruhi ssh?
Gilles 'SO- stop being evil'