Bagaimana Linux tahu bahwa kata sandi baru mirip dengan yang sebelumnya?

145

Beberapa kali saya mencoba untuk mengubah kata sandi pengguna di berbagai mesin Linux dan ketika kata sandi baru mirip dengan yang lama, OS mengeluh bahwa mereka terlalu mirip.

Saya selalu bertanya-tanya, bagaimana sistem mengetahui hal ini? Saya pikir kata sandi disimpan sebagai hash. Apakah ini berarti bahwa ketika sistem dapat membandingkan kata sandi baru untuk kesamaan, yang lama sebenarnya disimpan sebagai teks biasa?

Arkonix
sumber
30
1st off: teks biasa? tidak. Jika (!) Disimpan, Anda menyimpan hash dan membandingkan hash. Di Linux, ia memeriksa kata sandi saat ini dengan kata sandi baru. KEDUA disediakan oleh pengguna saat mengubah kata sandi.
Rinzwind
42
@Rinzwind Tapi membandingkan hash tidak akan berhasil karena perbedaan satu karakter akan menghasilkan hash yang sama sekali berbeda
slhck
17
Lihat juga Apakah Facebook menyimpan kata sandi teks biasa? tentang Keamanan Informasi untuk cara-cara lain untuk mendeteksi kesamaan yang diberikan hanya hash dari kata sandi lama dan plaintext dari kata sandi baru (tidak ada plaintext untuk kata lama)
Bob
21
Anda sebenarnya dapat menguji kesamaan antara kata sandi lama yang di-hash dan kata sandi baru plaintext. Cukup buat daftar kata sandi yang mirip dengan yang baru, hash semuanya, dan bandingkan hash yang dihasilkan dengan hash kata sandi lama. Jika ada yang cocok, maka itu mirip.
BWG
2
@ BBW: Itu sedikit terlalu menyederhanakan - skema hashing saat ini menggarami hash, jadi pertama-tama Anda harus mengekstrak garam dari hash kata sandi lama dan pastikan Anda menggunakan garam itu untuk kata sandi yang mirip dengan kata sandi baru. (Saya tunjukkan ini karena ada kemungkinan bahwa API tidak akan mengekspos cara untuk memaksakan garam tertentu.)
Ulrich Schwarz

Jawaban:

156

Karena Anda perlu memasukkan kata sandi lama dan kata sandi baru saat digunakan passwd, kata sandi tersebut dapat dengan mudah dibandingkan dalam plaintext, dalam memori, tanpa menuliskannya di drive.

Memang kata sandi Anda di-hash ketika akhirnya disimpan, tetapi sampai itu terjadi, alat tempat Anda memasukkan kata sandi tentu saja dapat mengaksesnya secara langsung seperti program lain yang dapat mengakses hal-hal yang Anda masukkan pada keyboard saat membaca dari STDIN.

Ini adalah fitur sistem PAM yang digunakan di latar belakang passwdalat. PAM digunakan oleh distribusi Linux modern.

Lebih khusus lagi, pam_cracklibadalah modul untuk PAM yang memungkinkan untuk menolak kata sandi berdasarkan beberapa kelemahan yang akan membuatnya sangat rentan.

Bukan hanya kata sandi yang terlalu mirip yang dapat dianggap tidak aman. The kode sumber memiliki berbagai contoh dari apa yang dapat diperiksa, misalnya apakah password adalah palindrom atau apa mengedit jarak antara dua kata. Idenya adalah untuk membuat kata sandi lebih tahan terhadap serangan kamus.

Lihat juga halaman pam_cracklibmanual.

slhck
sumber
apakah Anda memiliki ide dalam "bagaimana" penjelasan Anda sesuai dengan argumen yang dilaporkan dalam jawaban saya? Apakah ada dua pendekatan yang berbeda, yang diambil oleh aplikasi "passwd", ketika tuan rumah tidak sadar-PAM? PS: Tidak ada kritik sama sekali. Saya hanya ingin tahu (seperti PAM, BTW, adalah tebakan pertama saya ... sebelum mengambil kode sumber).
Damiano Verzulli
27
Yang lebih mengganggu adalah aturan kata sandi perusahaan yang mengingatkan Anda jika Anda telah menggunakan kata sandi yang sama atau serupa di antara empat yang terakhir.
Nick T
4
@NickT Bagaimana hal itu (tentu saja) mengganggu - tidak bisakah mereka menyimpan 4 hash terakhir Anda, lalu membandingkan masing-masing dengan hash baru yang Anda usulkan dengan cara yang sama seperti pertanyaan ini?
neminem
1
@neminem "... atau serupa"
Nick T
1
@NickT Ah, cukup adil, karena dalam kasus khusus ini Anda membandingkan dengan "kata sandi lama" yang dimasukkan oleh pengguna untuk mengubah kata sandi, bukan terhadap hash yang disimpan. Namun, Anda dapat secara hipotetis menggunakan metode yang diposting BWG dalam komentar, untuk setidaknya memeriksa perubahan yang sangat sederhana (satu substitusi karakter, satu karakter ditambahkan / dihapus, dll.).
neminem
46

Setidaknya di Ubuntu saya, pesan "terlalu mirip" muncul ketika: "... lebih dari separuh karakter adalah yang berbeda ...." (lihat detail di bawah). terima kasih atas dukungan PAM, sebagaimana dijelaskan dengan jelas dalam jawaban @slhck.

Untuk platform lain, di mana PAM tidak digunakan, pesan "terlalu mirip" keluar ketika: "... lebih dari separuh karakter adalah yang berbeda ...." (lihat detail di bawah)

Untuk lebih lanjut memeriksa pernyataan ini sendiri, dimungkinkan untuk memeriksa kode sumber. Begini caranya.

Program "passwd" termasuk dalam paket passwd:

verzulli@iMac:~$ which passwd
/usr/bin/passwd
verzulli@iMac:~$ dpkg -S /usr/bin/passwd
passwd: /usr/bin/passwd

Saat kita berhadapan dengan teknologi Open Source, kita memiliki akses tidak terbatas ke kode sumber. Mendapatkannya sesederhana:

verzulli@iMac:/usr/local/src/passwd$ apt-get source passwd

Setelah itu mudah untuk menemukan bagian kode yang relevan:

verzulli@iMac:/usr/local/src/passwd$ grep -i -r 'too similar' .
[...]
./shadow-4.1.5.1/NEWS:- new password is not "too similar" if it is long enough
./shadow-4.1.5.1/libmisc/obscure.c:     msg = _("too similar");

Pemeriksaan cepat ke "obscure.c" memberikan ini (saya hanya memotong dan menempelkan potongan kode yang relevan):

static const char *password_check (
    const char *old,
    const char *new,
    const struct passwd *pwdp)
{
    const char *msg = NULL;
    char *oldmono, *newmono, *wrapped;

    if (strcmp (new, old) == 0) {
            return _("no change");
    }
    [...]
    if (palindrome (oldmono, newmono)) {
            msg = _("a palindrome");
    } else if (strcmp (oldmono, newmono) == 0) {
            msg = _("case changes only");
    } else if (similar (oldmono, newmono)) {
            msg = _("too similar");
    } else if (simple (old, new)) {
            msg = _("too simple");
    } else if (strstr (wrapped, newmono) != NULL) {
            msg = _("rotated");
    } else {
    }
    [...]
    return msg;
}

Jadi, sekarang, kita tahu bahwa ada fungsi "mirip" yang didasarkan pada yang lama dan yang baru memeriksa apakah keduanya mirip. Berikut cuplikannya:

/*
 * more than half of the characters are different ones.
 */
static bool similar (const char *old, const char *new)
{
    int i, j;

    /*
     * XXX - sometimes this fails when changing from a simple password
     * to a really long one (MD5).  For now, I just return success if
     * the new password is long enough.  Please feel free to suggest
     * something better...  --marekm
     */
    if (strlen (new) >= 8) {
            return false;
    }

    for (i = j = 0; ('\0' != new[i]) && ('\0' != old[i]); i++) {
            if (strchr (new, old[i]) != NULL) {
                    j++;
            }
    }

    if (i >= j * 2) {
            return false;
    }

    return true;
}

Saya belum meninjau kode C. Saya membatasi diri dalam mempercayai komentar sebelum definisi fungsi :-)


Perbedaan antara platform yang sadar PAM dan NON-PAM didefinisikan dalam file "obscure.c" yang terstruktur seperti:

#include <config.h>
#ifndef USE_PAM
[...lots of things, including all the above...]
#else                           /* !USE_PAM */
extern int errno;               /* warning: ANSI C forbids an empty source file */
#endif                          /* !USE_PAM */
Damiano Verzulli
sumber
9
Ini adalah jawaban panjang yang sepertinya tidak langsung menjawab pertanyaan tentang bagaimana ia dapat dibandingkan dengan kata sandi lama ketika kata sandi sebagai hash.
jamesdlin
10
@jamesdlin: seperti yang dinyatakan dalam komentar Rinzwind terhadap pertanyaan awal, hash JANGAN memainkan peran apa pun dalam masalah ini: ketika Anda mengeluarkan perintah "passwd" untuk mengubah kata sandi, Anda harus memberikan kata sandi "lama" dan "baru". Jadi kode "passwd" tidak memiliki masalah sama sekali dalam membandingkan / memeriksa kedua kata sandi sekaligus (dalam bentuk yang jelas; tidak hash sama sekali).
Damiano Verzulli
3
@DamianoVerzulli Namun demikian, ini tidak benar-benar menjawab pertanyaan. Pertanyaannya bukan "kode C apa yang Anda gunakan untuk memberi tahu jika dua string serupa;" itu persis sama untuk kata sandi seperti untuk hal lain. Hal tentang kata sandi yang membuatnya menarik adalah bahwa kata sandi itu tidak pernah disimpan dalam plaintext, dan itulah pertanyaan yang ditanyakan. Ini menjawab "kriteria apa yang digunakan dan bagaimana melakukannya dalam C," tetapi terlalu lama untuk "kriteria apa" dan "bagaimana saya melakukan ini dalam C" adalah pertanyaan SO, bukan pertanyaan SU.
cpast
7
@DamianoVerzulli Dan fakta yang passwdmeminta kata sandi lama dan baru adalah jawabannya . Sisa dari jawaban ini tidak relevan.
jamesdlin
3
+1 untuk dan jawaban yang sangat relevan dan menarik! Sangat menyenangkan melihat bahwa kode aktual yang membandingkan kata sandi sebenarnya berfungsi pada plaintext dan, seperti yang diharapkan, bukan pada hash.
nico
36

Jawabannya jauh lebih sederhana dari yang Anda pikirkan. Bahkan, hampir memenuhi syarat sebagai sihir, karena begitu Anda menjelaskan triknya, itu akan hilang:

$ passwd
Current Password:
New Password:
Repeat New Password:

Password changed successfully

Ia tahu kata sandi baru Anda mirip ... Karena Anda mengetik yang lama hanya beberapa saat sebelumnya.

Cort Ammon
sumber
2
"... atau permen."
Nick T
1
Kelinci konyol, trix untuk anak-anak!
iAdjunct
1
Yang tidak dijelaskan adalah ketika mengetahui kata sandi dan masa lalu Anda :) "Kata sandi telah digunakan terlalu baru", yang mencegah bertukar beberapa kata sandi yang sama di lingkungan perusahaan.
Juha Untinen
3
@Juha Untinen: Itu benar, tapi itu bisa ditangani hanya dengan mengingat hash N terakhir. Menangkap "sama dengan kata sandi N" adalah mudah, itu " mirip dengan kata sandi N" yang sulit. Sejauh yang saya ketahui, sistem ini hanya memeriksa kesamaan dengan kata sandi terakhir, dan kesamaan dengan N. terakhir. Jika mereka memeriksa kesamaan dengan N terakhir ... itu trik yang sangat menarik sekarang, bukan! Saya tidak tahu bagaimana mereka melakukan itu.
Cort Ammon
7

Meskipun jawaban lain benar, mungkin perlu disebutkan bahwa Anda tidak perlu memberikan kata sandi lama agar ini berfungsi!

Bahkan, seseorang dapat menghasilkan banyak kata sandi yang mirip dengan kata sandi baru yang Anda berikan, memotongnya, dan kemudian memeriksa apakah hash ini cocok dengan yang lama. Jika ini masalahnya, maka kata sandi baru dinilai mirip dengan yang lama! :)

Semut
sumber
2
Meskipun ini memang sarana untuk mencapai prestasi ini (dan digunakan oleh banyak situs web), bukan itu yang terjadi dalam contoh ini.
Brian S
Itu trik yang rapi! Sedikit lebih intensif secara komputasi, tetapi pintar!
Cort Ammon
Anda setidaknya harus memberikan perkiraan berapa banyak kata sandi yang serupa perlu dihasilkan untuk mendapatkan pemeriksaan yang berarti, atau tautan ke sumber daya eksternal. Kalau tidak, ini hanya ide alternatif yang mungkin, bukan jawaban yang dibuktikan.
hyde
@ Hyde yang tergantung pada kriteria seseorang mungkin pikirkan. Bagi saya kata sandi serupa jika ada maks 3 karakter yang ditambahkan / dihapus / dimodifikasi. Jadi itu adalah 62 hash untuk setiap karakter (dan itu jika kita hanya menggunakan alfanumerik) kali kombinasi 3 dari panjang kata sandi ( n) 62 * (n!)/(6 * (n - 3)!), yang sama dengan 13540 untuk 12 karakter kata sandi panjang. Tetapi jika ada yang berpikir tentang sesuatu yang berbeda, persamaan itu tidak berguna, jadi mengapa repot-repot?
Killah
Jawaban bodoh, namun wawasan. Kenapa bodoh? 1. Anda harus menghasilkan hash yang tidak terbayangkan. 2. Pengaturan seperti itu akan melemahkan keamanan kata sandi asli. Jika seseorang mendapatkan hash dari semua kata sandi yang sama dan bukan hanya satu hash, mereka akan memiliki waktu yang lebih mudah untuk memecahkannya.
Rok Kralj
5

Satu aspek tidak dicakup: riwayat kata sandi. Beberapa sistem mendukung hal ini. Untuk melakukan itu, ia menyimpan riwayat kata sandi dan mengenkripsi mereka dengan kata sandi saat ini. Ketika Anda mengubah kata sandi Anda, kata sandi itu menggunakan kata sandi "lama" untuk mendekripsi daftar dan memverifikasi. Dan ketika menetapkan kata sandi baru, itu memang menyimpan daftar (lagi) yang dienkripsi dengan kunci yang berasal dari kata sandi baru.

Ini adalah cara remember=Nkerjanya di PAM (disimpan di /etc/security/opasswd). Tetapi juga Windows dan vendor Unix lainnya menawarkan fungsi serupa.

eckes
sumber