Menyembunyikan Kata Sandi dalam Skrip Shell

23

Bagaimana saya bisa menyembunyikan kata sandi dalam skrip shell? Ada sejumlah skrip yang mengakses basis data. Jika kita membuka skrip, orang lain juga akan mengetahui nama pengguna dan kata sandi. Jadi, jika ada yang tahu cara menyembunyikan, beri tahu saya.

Saya punya satu cara: letakkan kata sandi dalam file dan jadikan file sebagai tersembunyi dan tidak ada yang akan mengakses file (ubah izin dan gunakan file dalam skrip saat akan mengakses database).

arun
sumber

Jawaban:

35

Pertama , seperti yang telah dikatakan beberapa orang, menjaga kredensial terpisah dari naskah sangat penting. (Selain meningkatkan keamanan, ini juga berarti Anda dapat menggunakan kembali skrip yang sama untuk beberapa sistem dengan kredensial berbeda.)

Kedua , Anda harus mempertimbangkan tidak hanya keamanan kredensial, tetapi juga dampaknya jika / ketika kredensial tersebut dikompromikan. Anda seharusnya tidak hanya memiliki satu kata sandi untuk semua akses ke database, Anda harus memiliki kredensial berbeda dengan berbagai tingkat akses. Anda bisa, misalnya, memiliki satu pengguna DB yang memiliki kemampuan untuk melakukan pencarian dalam database - bahwa pengguna harus memiliki akses hanya baca. Pengguna lain mungkin memiliki izin untuk memasukkan catatan baru, tetapi tidak untuk menghapusnya. Yang ketiga mungkin memiliki izin untuk menghapus catatan.

Selain membatasi izin untuk setiap akun, Anda juga harus memiliki batasan tempat masing-masing akun dapat digunakan. Misalnya, akun yang digunakan oleh server web Anda tidak boleh terhubung dari alamat IP lain selain dari server web. Akun dengan izin root penuh ke basis data harus sangat terbatas dalam hal di mana ia dapat terhubung dan tidak boleh digunakan selain secara interaktif. Juga pertimbangkan untuk menggunakan prosedur tersimpan dalam database untuk membatasi dengan tepat apa yang dapat dilakukan oleh setiap akun.

Pembatasan ini perlu diterapkan pada sisi server DB sistem, sehingga bahkan jika sisi klien dikompromikan, pembatasan tidak dapat diubah darinya. (Dan, tentu saja, server DB perlu dilindungi dengan firewall dll selain konfigurasi DB ...)

Dalam kasus akun DB yang hanya diizinkan akses read-only terbatas, dan hanya dari alamat IP tertentu, Anda mungkin tidak memerlukan kredensial lebih lanjut dari itu, tergantung pada sensitivitas data dan keamanan host script. sedang dijalankan. Salah satu contoh dapat berupa formulir pencarian di situs web Anda, yang dapat dijalankan dengan pengguna yang hanya diizinkan untuk menggunakan prosedur tersimpan yang hanya mengekstraksi informasi yang akan disajikan pada halaman web. Dalam hal ini, menambahkan kata sandi tidak benar-benar memberikan keamanan tambahan, karena informasi itu sudah dimaksudkan untuk umum, dan pengguna tidak dapat mengakses data lain yang akan lebih sensitif.

Pastikan juga koneksi ke database dibuat menggunakan TLS, atau siapa pun yang mendengarkan di jaringan bisa mendapatkan kredensial Anda.

Ketiga , pertimbangkan kredensial apa yang digunakan. Kata sandi hanyalah satu bentuk, dan bukan yang paling aman. Anda bisa menggunakan beberapa bentuk pasangan kunci publik / pribadi, atau AD / PAM atau sejenisnya.

Keempat , pertimbangkan kondisi di mana skrip akan dijalankan:

Jika dijalankan secara interaktif, maka Anda harus memasukkan kata sandi, atau kata sandi ke kunci pribadi, atau kunci pribadi, atau masuk dengan tiket Kerberos yang valid, ketika Anda menjalankannya - dengan kata lain, skrip harus mendapatkan kredensial langsung dari Anda pada saat Anda menjalankannya, alih-alih membacanya dari beberapa file.

Jika dijalankan dari server web, pertimbangkan untuk menyiapkan kredensial pada saat Anda memulai server web. Contoh yang baik di sini adalah sertifikat SSL - sertifikat publik dan kunci privat, dan kunci privat memiliki kata sandi. Anda dapat menyimpan kunci privat di server web, tetapi Anda masih harus memasukkan kata sandi saat memulai Apache. Anda juga dapat memiliki kredensial pada beberapa jenis perangkat keras, seperti kartu fisik atau HSM, yang dapat dihapus atau dikunci setelah server dimulai. (Tentu saja, kelemahan dari metode ini adalah bahwa server tidak dapat memulai kembali sendiri jika terjadi sesuatu. Saya lebih suka ini dengan risiko sistem saya dikompromikan, tetapi jarak tempuh Anda mungkin bervariasi ...)

Jika skrip dijalankan dari cron, ini adalah bagian yang sulit. Anda tidak ingin memiliki kredensial tergeletak di mana saja pada sistem Anda di mana seseorang dapat mengaksesnya - tetapi Anda ingin memiliki kredibilitas itu di sekitar sehingga skrip Anda dapat mengaksesnya, bukan? Ya tidak benar. Pertimbangkan dengan tepat apa yang dilakukan skrip. Izin apa yang dibutuhkan pada database? Bisakah itu dibatasi sehingga tidak masalah jika orang yang salah terhubung dengan izin itu? Bisakah Anda menjalankan skrip secara langsung di server DB yang tidak dapat diakses orang lain, alih-alih dari server yang memang memiliki pengguna lain? Jika, untuk beberapa alasan yang tidak dapat saya pikirkan, Anda benar - benar harus menjalankan skrip pada server yang tidak aman dan harus dapat melakukan sesuatu yang berbahaya / destruktif ... sekarang adalah saat yang tepat untuk memikirkan kembali arsitektur Anda.

Kelima , jika Anda menghargai keamanan basis data Anda, Anda seharusnya tidak menjalankan skrip ini di server yang dapat diakses orang lain. Jika seseorang masuk pada sistem Anda, maka mereka akan memiliki kemungkinan untuk mendapatkan kredensial Anda. Misalnya, dalam hal server web dengan sertifikat SSL, setidaknya ada kemungkinan teoritis seseorang dapat memperoleh root dan mengakses area memori proses httpd dan mengekstrak kredensial. Paling tidak ada satu exploit dalam beberapa waktu terakhir di mana ini bisa dilakukan melalui SSL, bahkan tidak mengharuskan penyerang untuk login.

Juga pertimbangkan untuk menggunakan SELinux atau apparmor atau apa pun yang tersedia untuk sistem Anda untuk membatasi pengguna mana yang dapat melakukan apa. Mereka akan memungkinkan Anda untuk melarang pengguna bahkan mencoba untuk terhubung ke database, bahkan jika mereka berhasil mendapatkan akses ke kredensial.

Jika semua ini kedengarannya berlebihan bagi Anda , dan Anda tidak mampu atau tidak punya waktu untuk melakukannya - maka, menurut pendapat saya (arogan dan elitis), Anda tidak boleh menyimpan sesuatu yang penting atau sensitif dalam database Anda. Dan jika Anda tidak menyimpan sesuatu yang penting atau sensitif, maka tempat Anda menyimpan kredensial Anda juga tidak penting - dalam hal ini, mengapa menggunakan kata sandi sama sekali?

Terakhir , jika Anda benar-benar tidak dapat menghindari menyimpan semacam kredensial, Anda dapat membuat kredensial hanya-baca dan dimiliki oleh root dan root dapat memberikan kepemilikan secara sangat sementara ketika diminta untuk melakukannya dengan skrip (karena skrip Anda tidak boleh jalankan sebagai root kecuali benar-benar diperlukan, dan menghubungkan ke database tidak membuatnya perlu). Tapi itu masih bukan ide yang bagus.

Jenny D
sumber
9
Sama sekali tidak arogan dan elitis. Atau aku juga. "Bagaimana saya bisa melindungi perhiasan saya kalau-kalau pencuri masuk?" "Letakkan di dalam brankas yang dibaut / dilas pada tempatnya." "Itu terlalu banyak masalah, aku hanya akan mendapatkan brankas portabel dan menggantung kunci dari kail." "Kalau begitu jangan repot-repot menggunakan brankas." Nasihat yang sangat masuk akal.
Wildcard
12

Pertama-tama, jika ada cara apa pun Anda dapat mengubah hal-hal untuk menghindari harus menyimpan kata sandi di dalam atau di samping skrip di tempat pertama, Anda harus berusaha keras untuk melakukan itu. Jawaban Jenny D mengandung banyak saran bagus untuk efek itu.

Jika tidak, ide Anda untuk memasukkan kata sandi dalam file terpisah dengan izin terbatas cukup banyak. Misalnya Anda dapat sumber file itu dari skrip utama:

. /usr/local/etc/secret-password-here

Anda juga dapat membatasi izin skrip utama sehingga hanya orang yang berwenang yang dapat mengeksekusinya, tetapi mungkin lebih baik melakukannya seperti yang Anda sarankan dan hanya menyimpan kata sandi itu sendiri dalam file yang dibatasi. Dengan begitu Anda dapat mengizinkan pemeriksaan kode itu sendiri (tanpa rahasia sensitif), kontrol versi dan menyalin di sekitar skrip dengan lebih mudah, dll ...

Celada
sumber
@BasileStarynkevitch ah tapi saya melihat itu juga mengatakan " /usr/local/etcmungkin tautan simbolis ke /etc/local". Saya melewatkan itu. Jadi Anda juga benar, tetapi ini MUNGKIN jadi itu opsional. Tapi ya, tidak masalah, dan preferensi pribadi.
Celada
1
Kecuali bahwa saya membuat cadangan /etc/ tetapi tidak /usr/local/ (yang saya asumsikan dapat dibangun kembali setelah kerusakan disk)
Basile Starynkevitch
titik adil tentang backup
Celada
3

Jawaban lain telah membahas caranya , tetapi saya akan mempertimbangkan apakah . Bergantung pada jenis basis data yang terhubung dengan pengguna Anda, Anda mungkin sudah memiliki mekanisme yang cocok yang sudah digunakan oleh program klien tersebut, dalam hal ini pastikan untuk menggunakannya (saya sedang memikirkan ~/.mysqlrcatau ~/.pgpass).

Jika Anda memberi beberapa pengguna kemampuan untuk mengakses database untuk membuat pertanyaan spesifik menggunakan akun bersama, maka Anda mungkin tidak seharusnya. Alih-alih, pastikan mereka memiliki akun di basis data dan bahwa akun itu tidak memiliki izin lebih dari yang mereka butuhkan (mungkin banyak membaca tentang itu, dan sangat sedikit akses menulis). Jika mereka perlu membuat pertanyaan spesifik pada tabel tertentu yang tidak dapat mereka akses, sediakan prosedur tersimpan SECURTY DEFINERuntuk memungkinkan mereka melakukannya.

Jika tidak ada di atas yang menghindari Anda perlu menyimpan kredensial, maka baca jawaban lain di sini.

Toby Speight
sumber
1

Gagasan Anda untuk menyembunyikan kata sandi di tempat yang tidak dapat diakses mungkin baik-baik saja tergantung pada situasinya.

Jika informasi terpisah, itu berarti pengeditan file yang sederhana, misalnya selama peninjauan kode dengan kolega tidak akan memperlihatkannya. Tetapi sadari bahwa siapa pun yang memiliki akses ke akun Anda dapat dengan mudah menemukan file seperti itu. Saya telah menggunakan subdirektori ~/.sshuntuk tujuan tersebut, karena alasan sederhana yang sshmengeluh jika hak akses untuk ~/.sshtidak cukup dibatasi.

Namun ada hal lain yang dapat Anda lakukan untuk mencegah melirik nama pengguna dan / atau kata sandi.

Mengaburkan : Jika Anda tidak ingin orang membaca nama pengguna atau kata sandi saat Anda mengedit skrip, Anda dapat memasukkannya ke dalam teks tetapi tidak sebagai teks biasa, tetapi dikaburkan. Jika versi yang dikaburkan cukup lama mencegah menghafalnya oleh seseorang yang melihatnya, itu tidak dapat diketahui bahkan jika metode dan kunci dekripsi terlihat jelas. Ini tentu saja masih bisa dielakkan sepele oleh seseorang yang memiliki akses ke akun Anda.

Menggunakan GPG :

Sedikit lebih baik, tetapi masih belum bukti penuh terhadap serangan oleh pengguna root pada sistem Anda, adalah untuk mengenkripsi pasangan nama pengguna / kata sandi dalam file gpgpublik Anda dan membuat skrip mengambil konten pada file (mungkin meminta Anda untuk kata sandi, jika tidak meminta Anda untuk kata sandi, jika tidak di-cache / kedaluwarsa). Saya menggunakan kartu ggp sehingga ketika saya meninggalkan laptop saya tetapi menarik kartu, tidak ada akses yang mungkin bahkan jika pin masih di-cache. Setidaknya jika saya menjalankan sesuatu 20 kali dalam beberapa menit, saya harus memberikan pin hanya sekali.

Keamanan tampaknya selalu berhubungan terbalik dengan kenyamanan (pengaturan dan penggunaan).

Anthon
sumber
0

Ada cara untuk menyimpan kata sandi dalam skrip bash tetapi Anda harus mengenkripsi dan mengaburkan skrip tersebut sehingga tidak ada yang dapat membacanya atau menjalankan segala jenis debugger di atasnya untuk melihat apa yang dilakukannya. Untuk mengenkripsi dan mengaburkan skrip bash / shell dan membuatnya benar-benar dapat dieksekusi, coba salin dan tempel di sini:

http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm

Pada halaman di atas, yang harus Anda lakukan adalah mengirimkan skrip Anda (Anda dapat mengirimkan skrip sampel terlebih dahulu untuk ketenangan pikiran Anda). File zip akan dibuat untuk Anda. Klik kanan pada tautan unduhan dan salin URL yang Anda berikan. Lalu, buka kotak UNIX Anda dan lakukan langkah-langkah berikut.

Instalasi:

  1. wget tautan ke file zip

  2. unzip file zip yang baru diunduh

  3. cd / tmp / KingLazySHIELD

  4. ./install.sh / var / tmp / KINGLAZY / SHIELDX- (nama-skrip Anda) / home / (nama pengguna Anda) -maksa

Apa yang akan dilakukan perintah instalasi di atas untuk Anda adalah:

  1. Ini akan menginstal versi terenkripsi dari skrip Anda di direktori / var / tmp / KINGLAZY / SHIELDX- (nama-skrip-Anda).

  2. Ini akan menempatkan tautan ke skrip terenkripsi ini di direktori mana pun yang Anda tentukan sebagai pengganti / home / (nama pengguna Anda) - dengan cara itu, ia memungkinkan Anda untuk dengan mudah mengakses skrip tanpa harus mengetikkan path absolut.

  3. Pastikan TIDAK ADA yang dapat memodifikasi skrip - Upaya apa pun untuk memodifikasi skrip terenkripsi akan membuatnya tidak dapat dioperasikan ... hingga upaya tersebut dihentikan atau dihapus. Ia bahkan dapat dikonfigurasikan untuk memberi tahu Anda kapan pun seseorang mencoba melakukan apa saja dengan skrip selain menjalankannya ... mis. Peretasan atau upaya modifikasi.

  4. Memastikan benar-benar TIDAK ADA yang bisa menyalinnya. Tidak ada yang dapat menyalin skrip Anda ke lokasi terpencil dan mencoba untuk membukanya dengan itu untuk melihat cara kerjanya. Semua salinan skrip harus berupa tautan ke lokasi asli yang Anda tentukan saat menginstal (langkah 4).

CATATAN:

Saya tidak percaya ini berfungsi untuk skrip interaktif yang meminta pengguna untuk merespons. Nilai harus dikodekan ke dalam skrip. Enkripsi memastikan tidak ada yang benar-benar dapat melihat nilai-nilai itu sehingga Anda tidak perlu khawatir tentang itu.

AncientMinds
sumber
0

Solusi lain, tanpa memperhatikan keamanan (saya juga berpikir lebih baik menyimpan kredensial di file lain atau dalam database) adalah mengenkripsi kata sandi dengan gpg dan memasukkannya ke dalam skrip.

Saya menggunakan pasangan kunci gpg tanpa kata sandi yang saya simpan di usb. (Catatan: Saat Anda mengekspor pasangan kunci ini tidak menggunakan --armor, ekspor mereka dalam format biner).

Pertama mengenkripsi kata sandi Anda:

echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient someone@mail.com --encrypt

Itu akan mencetak kata sandi terenkripsi gpg di output standar. Salin seluruh pesan dan tambahkan ini ke skrip:

password=$(gpg --batch --quiet --no-default-keyring --secret-keyring /media/usb/key.priv --decrypt <<EOF 
-----BEGIN PGP MESSAGE-----

hQEMA0CjbyauRLJ8AQgAkZT5gK8TrdH6cZEy+Ufl0PObGZJ1YEbshacZb88RlRB9
h2z+s/Bso5HQxNd5tzkwulvhmoGu6K6hpMXM3mbYl07jHF4qr+oWijDkdjHBVcn5
0mkpYO1riUf0HXIYnvCZq/4k/ajGZRm8EdDy2JIWuwiidQ18irp07UUNO+AB9mq8
5VXUjUN3tLTexg4sLZDKFYGRi4fyVrYKGsi0i5AEHKwn5SmTb3f1pa5yXbv68eYE
lCVfy51rBbG87UTycZ3gFQjf1UkNVbp0WV+RPEM9JR7dgR+9I8bKCuKLFLnGaqvc
beA3A6eMpzXQqsAg6GGo3PW6fMHqe1ZCvidi6e4a/dJDAbHq0XWp93qcwygnWeQW
Ozr1hr5mCa+QkUSymxiUrRncRhyqSP0ok5j4rjwSJu9vmHTEUapiyQMQaEIF2e2S
/NIWGg==
=uriR
-----END PGP MESSAGE-----
EOF)

Dengan cara ini hanya jika usb dipasang di sistem, kata sandi dapat didekripsi. Tentu saja Anda juga dapat mengimpor kunci ke sistem (kurang aman, atau tidak ada keamanan sama sekali) atau Anda dapat melindungi kunci pribadi dengan kata sandi (sehingga tidak dapat otomatis).

Juanu
sumber
-2
#!/bin/bash
unset username
unset password
unset dbname
echo -n "username:"
read username
echo -n "dbname:"
read dbname
prompt="password:"

    while IFS= read -p "$prompt" -r -s -n 1 char
            do
                    if [[ $char == $'\0' ]]
                            then
                                    break
                    fi
                    prompt='*'
                    password+="$char"
            #       read -s -p "Enter Password: "  pswd
            #       echo -e "\nYour password is: " $pswd
            done
arun
sumber
3
Saya membuat indentasi kode Anda, mungkin Anda bisa menjelaskan apa yang Anda coba lakukan?
Archemar
-6

Saya tidak percaya Anda harus menyimpan kata sandi. Saya tidak bisa memikirkan satu pun alasan bagus untuk itu. Sebaliknya, Anda harus menyimpan hash asin dari kata sandi tersebut - beberapa string yang dihasilkan andal oleh beberapa fungsi ketika kata sandi asli dilewatkan sebagai input, tetapi tidak pernah kata sandi .

mikeserv
sumber
5
Saya tidak jelas tentang bagaimana ini akan menyelesaikan masalah a) dapat terhubung ke layanan yang membutuhkan kata sandi, dan b) pengguna dapat melihat skrip dan dengan demikian dapat mengetahui rincian otentikasi, apakah itu kata sandi atau tidak
Jenny D
1
Anda mengaku tahu jawaban saya sebelum saya menulisnya.
Jenny D
1
Saya sudah menulis jawaban saya sekarang. Apa yang saya coba dapatkan dari Anda adalah sebagian poin kelima saya - setelah kredensial disimpan dalam memori mereka tidak sepenuhnya aman dari penyerang dengan akses ke server. Juga jawaban singkat Anda itu tidak sangat membantu, meskipun tidak salah. Saya berpikir untuk menunjuk pada saat seseorang mengeluh bahwa kita di ServerFault tidak sebagus orang-orang di Unix / Linux :-)
Jenny D
2
@ JennyD - begitu kredibilitasnya ada di memori - itu tentu tidak perlu tinggal di sana - dan itu alasan yang sangat baik untuk menangani w / hash saja. Namun, saya akan dengan senang hati mewakili standar kesopanan komunitas sebagai contoh pada umumnya - saya sangat terkenal dengan sifat itu, pada kenyataannya.
mikeserv
4
Setelah diskusi besar Anda, saya hanya ingin menyebutkan kalau-kalau ada kesalahpahaman bahwa akulah yang kalah, bukan Jenny. Dan alasannya bukan pendapat tentang apakah itu ide yang baik untuk menggunakan sertifikat & privkey atau kata sandi yang dimasukkan secara interaktif atau melakukan apa yang diinginkan OP atau apa pun. Itu karena jawaban yang ada salah: menyimpan hash kata sandi asin sebagai kredensial klien bukanlah sesuatu: hash asin adalah hal yang Anda simpan di ujung koneksi yang memverifikasi auth, bukan di sisi yang mengirimkannya.
Celada