Skenario:
Dalam skrip bash, saya harus memeriksa apakah kata sandi yang diberikan oleh pengguna adalah kata sandi pengguna yang valid.
Yaitu saya kira saya memiliki pengguna A dengan kata sandi PA .. Dalam skrip saya meminta pengguna A untuk memasukkan kata sandinya, Jadi bagaimana cara memeriksa apakah string yang dimasukkan benar-benar kata sandinya? ...
expect
di stackoverflow.com/a/1503831/320594 .Jawaban:
Karena Anda ingin melakukan ini dalam skrip shell, beberapa kontribusi dalam Cara memeriksa kata sandi dengan Linux? (pada Unix.SE , disarankan oleh AB ) sangat relevan:
/etc/shadow
memberikan bagian dari solusi.mkpasswd
sekarang perintah di Debian (dan Ubuntu).Untuk secara manual memeriksa apakah suatu string benar-benar beberapa kata sandi pengguna, Anda harus mengirisnya dengan algoritma hash yang sama seperti pada entri bayangan pengguna, dengan garam yang sama seperti pada entri bayangan pengguna. Kemudian bisa dibandingkan dengan kata sandi hash yang tersimpan di sana.
Saya telah menulis naskah yang lengkap dan berfungsi yang menunjukkan bagaimana melakukan ini.
chkpass
, Anda dapat menjalankan dan itu akan membaca baris dari input standar dan memeriksa apakah itu kata sandi.chkpass user
user
mkpasswd
utilitas yang menjadi dasar skrip ini.Catatan Keamanan
Mungkin itu bukan pendekatan yang tepat.
Apakah pendekatan seperti ini harus dianggap aman atau tidak, tergantung pada detail tentang kasus penggunaan yang belum Anda berikan (pada tulisan ini).
Belum diaudit.
Meskipun saya sudah berusaha berhati-hati saat menulis skrip ini, itu belum diaudit dengan baik untuk kerentanan keamanan . Ini dimaksudkan sebagai demonstrasi, dan akan menjadi perangkat lunak "alpha" jika dirilis sebagai bagian dari proyek. Selanjutnya...
Pengguna lain yang "menonton" mungkin dapat menemukan pengguna tersebut garam .
Karena keterbatasan dalam cara
mkpasswd
menerima data garam, skrip ini berisi kelemahan keamanan yang diketahui , yang Anda mungkin atau mungkin tidak anggap dapat diterima tergantung pada kasus penggunaan. Secara default, pengguna di Ubuntu dan sebagian besar sistem GNU / Linux lainnya dapat melihat informasi tentang proses yang dijalankan oleh pengguna lain (termasuk root), termasuk argumen baris perintah mereka. Baik input pengguna maupun hash kata sandi yang disimpan dilewatkan sebagai argumen baris perintah ke utilitas eksternal apa pun. Tapi garam , diambil darishadow
basis data, yang diberikan sebagai argumen baris perintah untukmkpasswd
, karena ini adalah satu-satunya cara yang utilitas menerima garam sebagai masukan.Jika
www-data
) menjalankan kode mereka, atau/proc
)dapat memeriksa argumen baris perintah
mkpasswd
saat dijalankan oleh skrip ini, kemudian mereka dapat memperoleh salinan garam pengguna darishadow
database. Mereka mungkin harus bisa menebak kapan perintah itu dijalankan, tetapi itu kadang-kadang dapat dicapai.Seorang penyerang dengan garam Anda tidak seburuk penyerang dengan garam dan hash Anda , tetapi itu tidak ideal. Garam tidak memberikan informasi yang cukup bagi seseorang untuk menemukan kata sandi Anda. Tapi itu memungkinkan seseorang untuk menghasilkan tabel pelangi atau hash kamus pra-dihitung khusus untuk pengguna pada sistem itu. Ini pada awalnya tidak berharga, tetapi jika keamanan Anda dikompromikan di kemudian hari dan hash lengkap diperoleh, maka dapat dipecah lebih cepat untuk mendapatkan kata sandi pengguna sebelum mereka mendapatkan kesempatan untuk mengubahnya.
Dengan demikian kelemahan keamanan ini merupakan faktor yang memperburuk skenario serangan yang lebih kompleks daripada kerentanan sepenuhnya dapat dieksploitasi. Dan Anda mungkin menganggap situasi di atas tidak masuk akal. Tapi saya enggan untuk merekomendasikan metode apapun untuk umum, penggunaan dunia nyata bahwa kebocoran setiap data non-publik dari
/etc/shadow
ke pengguna non-root.Anda dapat menghindari masalah ini sepenuhnya dengan:
Berhati-hatilah dengan panggilan skrip ini.
Jika Anda mengizinkan pengguna yang tidak dipercaya untuk menjalankan skrip ini sebagai root atau menjalankan proses apa pun sebagai root yang memanggil skrip ini, berhati-hatilah . Dengan mengubah lingkungan, mereka dapat membuat skrip ini - atau skrip apa pun yang berjalan sebagai root - melakukan apa saja . Kecuali Anda dapat mencegah hal ini terjadi, Anda tidak boleh mengizinkan pengguna hak istimewa tinggi untuk menjalankan skrip shell.
Lihat 10.4. Bahasa Shell Scripting (turunan sh dan csh) di Pemrograman Aman David A. Wheeler untuk Linux dan Unix HOWTO untuk informasi lebih lanjut tentang ini. Sementara presentasinya berfokus pada skrip setuid, mekanisme lain dapat menjadi mangsa beberapa masalah yang sama jika mereka tidak membersihkan lingkungan dengan benar.
Catatan lain
Ini mendukung bacaan hash dari
shadow
database saja.Kata sandi harus dibayangi agar skrip ini berfungsi (yaitu, hash mereka harus dalam
/etc/shadow
file terpisah yang hanya dapat dibaca oleh root, bukan di/etc/passwd
).Ini harus selalu menjadi kasus di Ubuntu. Dalam kasus apa pun, jika diperlukan, skrip dapat dengan mudah diperluas untuk membaca hash kata sandi
passwd
jugashadow
.Perlu
IFS
diingat saat memodifikasi skrip ini.Saya atur
IFS=$
di awal, karena tiga data dalam bidang hash dari entri bayangan dipisahkan oleh$
.$
, itulah sebabnya jenis dan garam hash"${ent[1]}"
dan"${ent[2]}"
bukannya"${ent[0]}"
dan"${ent[1]}"
, masing-masing.Satu-satunya tempat di skrip ini yang
$IFS
menentukan bagaimana shell membagi atau menggabungkan kata-kataketika data ini dipecah menjadi sebuah array, dengan menginisialisasi dari
$(
)
substitusi perintah yang tidak dikutip dalam:ketika array disusun kembali menjadi string untuk dibandingkan dengan bidang penuh dari
shadow
,"${ent[*]}"
ekspresi di:Jika Anda memodifikasi skrip dan membuatnya melakukan pemisahan kata (atau penggabungan kata) dalam situasi lain, Anda harus mengatur
IFS
nilai yang berbeda untuk perintah yang berbeda atau bagian skrip yang berbeda.Jika Anda tidak mengingatnya dan menganggap
$IFS
diatur ke spasi putih biasa ($' \t\n'
), Anda bisa membuat skrip Anda berperilaku dalam beberapa cara yang tampak aneh.sumber
Anda dapat menyalahgunakan
sudo
ini.sudo
memiliki-l
opsi, untuk menguji hak sudo yang dimiliki pengguna, dan-S
untuk membaca kata sandi dari stdin. Namun, tidak peduli apa tingkat hak istimewa yang dimiliki pengguna, jika berhasil diautentikasi,sudo
kembali dengan status keluar 0. Jadi, Anda dapat mengambil status keluar lainnya sebagai indikasi bahwa otentikasi tidak berfungsi (dengan asumsisudo
itu sendiri tidak memiliki masalah, seperti kesalahan izin atausudoers
konfigurasi yang tidak valid ).Sesuatu seperti:
Script ini sangat tergantung pada
sudoers
konfigurasi. Saya telah mengasumsikan pengaturan default. Hal-hal yang dapat menyebabkannya gagal:targetpw
ataurunaspw
diaturlistpw
adalahnever
Masalah lain termasuk (terima kasih Eliah):
/var/log/auth.log
sudo
harus dijalankan sebagai pengguna yang Anda autentikasi. Kecuali Anda memilikisudo
hak istimewa sehingga Anda dapat menjalankansudo -u foo sudo -lS
, itu berarti Anda harus menjalankan skrip sebagai pengguna target.Sekarang, alasan saya menggunakan di sini-docs adalah untuk menghambat menguping. Variabel yang digunakan sebagai bagian dari baris perintah lebih mudah diungkapkan dengan menggunakan
top
ataups
atau alat lain untuk memeriksa proses.sumber
sudo
konfigurasi yang tidak biasa (seperti yang Anda katakan) dan mengacaukan/var/log/auth.log
dengan catatan setiap upaya, ini cepat, sederhana, dan menggunakan utilitas yang ada, daripada menciptakan kembali roda (sehingga untuk berbicara). Saya menyarankan pengaturanIFS=
untukread
, untuk mencegah keberhasilan palsu untuk input pengguna dengan spasi dan kata sandi non-empuk, serta kegagalan palsu untuk input pengguna dengan spasi dan kata sandi empuk. (Solusi saya memiliki bug yang serupa.) Anda mungkin juga ingin menjelaskan bagaimana itu harus dijalankan sebagai pengguna yang kata sandinya sedang diperiksa.sudo -l
menyebabkan entri ditulis dengan "COMMAND=list
". Btw (tidak terkait), sementara itu tidak obyektif lebih baik untuk melakukannya, menggunakan string di sini sebagai pengganti dokumen di sini mencapai tujuan keamanan yang sama dan lebih kompak. Karena skrip sudah menggunakan bashismsread -s
dan&>
, penggunaannyaif sudo -lS &>/dev/null <<<"$PASSWD"; then
tidak kalah portabel. Saya tidak menyarankan Anda harus mengubah apa yang Anda miliki (tidak apa-apa). Sebaliknya, saya menyebutkannya sehingga pembaca tahu mereka juga memiliki opsi ini.sudo -l
menonaktifkan sesuatu - mungkin itu melaporkan ketika pengguna mencoba menjalankan perintah yang tidak diizinkan.Metode lain (mungkin lebih menarik untuk konten teoretis daripada aplikasi praktisnya).
Kata sandi pengguna disimpan di
/etc/shadow
.Kata sandi yang disimpan di sini dienkripsi, dalam rilis Ubuntu terbaru menggunakan
SHA-512
.Khususnya, pada saat pembuatan kata sandi, kata sandi dalam teks yang jelas akan digarami dan dienkripsi
SHA-512
.Salah satu solusi kemudian akan garam / mengenkripsi kata sandi yang diberikan dan mencocokkannya dengan kata sandi pengguna terenkripsi yang disimpan dalam pengguna yang diberikan
/etc/shadow
entri .Untuk memberikan uraian singkat tentang bagaimana kata sandi disimpan di setiap
/etc/shadow
entri pengguna , berikut ini/etc/shadow
entri sampel untuk penggunafoo
dengan kata sandibar
:foo
: nama pengguna6
: jenis enkripsi kata sandilWS1oJnmDlaXrx1F
: garam enkripsi kata sandih4vuzZVBwIE1Z6vT7N.spwbxYig9e/OHOIH.VDv9JPaC3.OtTusPFzma7g.R/oSZFW5QOI7IDdDY01G0zTGQE/
:SHA-512
salted / password terenkripsiUntuk mencocokkan kata sandi yang diberikan
bar
untuk pengguna yang diberikanfoo
, hal pertama yang harus dilakukan adalah mendapatkan garam:Maka seseorang harus mendapatkan kata sandi penuh asin / terenkripsi:
Kemudian kata sandi yang diberikan dapat diasinkan / dienkripsi dan dicocokkan dengan kata sandi pengguna asin / terenkripsi yang disimpan di
/etc/shadow
:Mereka cocok! Semuanya dimasukkan ke dalam
bash
skrip:Keluaran:
sumber
sudo getent shadow
>>sudo grep ...
. Kalau tidak, bagus. Inilah yang saya pikirkan pada awalnya, kemudian menjadi terlalu malas.getent
+grep
+cut
>grep
+cut
getent
dapat melakukan pencarian untuk Anda. Saya mengambil kebebasan mengedit.mkpasswd
untuk menghasilkan hash dari input pengguna dan garam yang ada (dan termasuk fitur tambahan dan diagnostik), Anda malah mengkodekan program Python sederhana yang mengimplementasikanmkpasswd
fungsi paling penting dan menggunakannya. Saya sarankan Anda mengaturIFS=
ketika membaca masukan password, dan kutipan${password}
dengan"
, sehingga upaya sandi dengan spasi tidak melanggar script.