W systemie Linux, gdzie jest przechowywany szósty znak skrótu hasła /etc/shadow
?
W moim linuksowym pudełku w stylu szczeniaka, jeśli spróbuję wygenerować 100 losowych haseł za pomocą shuf
i /dev/urandom
, wtedy szósta postać będzie /
mniej więcej w połowie.
Moje pytanie nie jest przeznaczone do celów produkcyjnych, ponieważ uruchamiam go za każdym razem, gdy jest świeżo z płyty CD. Czy to oznacza, że mój system jest w jakiś sposób źle skonfigurowany lub niepewny?
Uruchomiłem plik, shuf
aby sprawdzić, czy jest to busybox
link.
file /usr/bin/shuf
shuf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, stripped
Nie sądzę, że shuf
jest to busybox
link tutaj.
ls -l /usr/bin/shuf
-rwxr-xr-x 1 root root 41568 Mar 7 2015 /usr/bin/shuf
podczas
ls -l /bin/wget
lrwxrwxrwx 1 root root 14 Apr 29 03:49 wget -> ../bin/busybox
Oto przybliżony pomysł na to, co zrobiłem:
# ! / b i n / b a s h
## don't try this on any real computer
## this is not a production script, it is just psuedo code
## with pseudo results to illustrate a point
## for this run of 100 ?random? passwords,
## 46 of the 6th character of the hash stored in
## '/ect/shadow' were '/'
function is_this_really_a_random_password () {
PERHAPS_RANDOM=''
for (( Z=0 ; Z<=8 ; Z++ )) do
PERHAPS_RANDOM="$PERHAPS_RANDOM$( shuf --head-count=1 --random-source=/dev/urandom $FILE_OF_SAFE_CHARACTERS )"
done
echo "$USER_NAME:$PERHAPS_RANDOM" | chpasswd
}
rm sixth-character-often-forward-slash.txt
for (( I=1; I<=100; I++ )) do
is_this_really_a_random_password
grep --regexp=root /etc/shadow | cut --characters=-40 >> sixth-character-often-forward-slash.txt
done
root:$5$56YsS//DE$HasM6O8y2mnXbtgeE64zK root:$5$ho8pk/4/A6e/m0eW$XmjA5Up.0Xig1e root:$5$jBQ4f.t1$vY/T/1kX8nzAEK8vQD3Bho root:$5$BJ44S/Hn$CsnG00z6FB5daFteS5QCYE root:$5$Jerqgx/96/HlV$9Wms5n1FEiM3K93A8 root:$5$qBbPLe4zYW$/zXRDqgjbllbsjkleCTB root:$5$37MrD/r0AlIC40n6$8hplf2c3DgtbM1 root:$5$.4Tt5S6F.3K7l7E$dAIZzFvvWmw2uyC root:$5$A4dX4ZlOoE$6axanr4GLPyhDstWsQ9B root:$5$HXAGhryJ/5$40tgmo7q30yW6OF7RUOE root:$5$EzNb9t5d$/nQEbEAQyug7Dk9X3YXCEv root:$5$HHS5yDeSP$LPtbJeTr0/5Z33vvw87bU root:$5$sDgxZwTX5Sm$6Pzcizq4NcKsWEKEL15 root:$5$FK1du/Paf/$hAy8Xe3UQv9HIpOAtLZ2 root:$5$xTkuy/BLUDh/N$/30sESA.5nVr1zFwI root:$5$PV4AX/OjZ$VU8vX651q4eUqjFWbE2b/ root:$5$iDuK0IUGijv4l$cdGh8BlHKJLYxPB8/ root:$5$0DEUp/jz$JBpqllXswNc0bMJA5IFgem root:$5$Wz3og/W3Jra/WKA.$6D7Wd4M1xxRDEp root:$5$ntHWB.mC3x$Kt4DNTjRZZzpbFvxpMxP root:$5$g/uEc/cq$Ptlgu8CXV.vrjrmuok9RRT root:$5$/XAHs/5x$Z9J4Zt4k6NxdjJ27PpLmTt root:$5$mgfbZeWD0h/$UDGz8YX.D85PzeXnd2K root:$5$f4Oh3/bF2Ox/eN$xt/Jkn0LxPnfKP8. root:$5$J0mZZXGJG7/v$e16VxghNvZZKRONown root:$5$SNza9XFl9i$Qq7r/N6Knt2j74no8H0x root:$5$aFCu//xiL$Ocn9mcT2izcnm3rUlBOJg root:$5$kMkyos/SLZ/Mm6$wNYxZ9QeuJ8c8T.o root:$5$ujXKC/Xnj0h/nQ$PUmePvJZr.UXmTGK root:$5$wtEhA/YKaTKH$6VCSXUiIdsfelkCYWV root:$5$I1taRlq59YZUGe$4OyIfByuvJeuwsjM root:$5$N54oH//j4nbiB$K4i6QOiS9iaaX.RiD root:$5$ps8bo/VjPGMP0y4$NTFkI6OeaMAQL7w root:$5$IRUXnXO8tSykA8$NatM5X/kKHHgtDLt root:$5$VaOgL/8V$m45M9glUYnlTKk8uCI7b5P root:$5$/lPDb/kUX73/F3$jJL.QLH5o9Ue9pVa root:$5$/sHNL/tVzuu//cr$QasvQxa02sXAHOl root:$5$hGI.SMi/7I$fYm0rZP0F5B2D1YezqtX root:$5$WsW2iENKA$4HhotPoLRc8ZbBVg4Z5QW root:$5$cN6mwqEl$q5S3U85cRuNHrlxS9Tl/PC root:$5$wwzLR/YMvk5/7ldQ$s3BJhq5LyrtZww root:$5$GUNvr/d15n8/K$CiNHwOkAtxuWJeNy1 root:$5$nGE75/8mEjM/A$pD/84iLunN/ZNI/JK root:$5$77Dn2dHLS$d5bUQhTz.OU4UA.67IGMB root:$5$EWrI//1u$uubkPk3YhAnwYXOYsvwbah root:$5$Hzfw1UCudP/N/U$Rjcdzdbov1YgozSJ root:$5$2y8CKTj.2eTq$7BEIgMWIzAJLl1SWBv root:$5$lcWsD/42g8zEEABA$r/vGxqqUZTkJ0V root:$5$LPJLc/Xz$tnfDgJh7BsAT1ikpn21l76 root:$5$ucvPeKw9eq8a$vTneH.4XasgBIeyGSA root:$5$Fwm2eUR7$ByjuLJRHoIFWnHtvayragS root:$5$yBl7BtMb$KlWGwBL6/WjgHVwXQh9fJS root:$5$1lnnh2kOG$rdTLjJsSpC3Iw4Y6nkPhq root:$5$WfvmP6cSfb066Z$1WvaC9iL11bPCAxa root:$5$qmf/hHvalWa4GE25$m3O2pdu25QBCwU root:$5$4P.oT/9HQ$Ygid4WXi0QCEObLVNsqFZ root:$5$FNr4Bkj56Y$38mG7mKV0mdb1PMCxrVd root:$5$hoNcyURtV$aTidBWHjngc1I0vUTi5bB root:$5$rzHmykYT$ATiXdUDUvUnB2fNMUQgwvE root:$5$o11Yb/ZQv2/k3wg9$5yShpVejDBk6HB root:$5$REPGN//y9H$awpPmUvCqvi6Bd/6bQxF root:$5$HbAEY/djXJx$y56GhMwavd7xTQ.jPg6 root:$5$3T1k5.LZUcy$Cup.LM5AnaBTIaJtBnF root:$5$wXaSC/P8bJ$y/0DoYJVjaP09O6GWiki root:$5$YuFfY8QPqm/dD$IIh0/tyn.18xEBl5Y root:$5$uTTBpjsKG//3Et8$9ibN9mVwSeVyOI4 root:$5$dASlMLzbVbFMnZ$N4uGBwGHhdg93z/V root:$5$03.FA/LnRBb.k7Zl$XOHU2ZlHkV9oz9 root:$5$2zL1p/VDCi$/QRT7Bo3cZ3Rxb8Y7ddo root:$5$0NpZqZs/qt/jIv.$8W/TTM3Gy2UMOWy root:$5$a4SXynoro7ucT$qFM2C79QJ15jQ0ZlL root:$5$RL0Eg/jroH8/ONP$EzceXz.pz74k104 root:$5$O3R5V/n1$U.mmCTbpID8xMXbvtzd4ch root:$5$0T2nVrv/P/xaRwUD$YVm17XF8kTsL0f root:$5$2bRwMNIXobZwn$Q228FJqg6/iRCe9GQ root:$5$PyYgL/axfgj/$uaL5y/kdzU4Kzi.JlB root:$5$A6QtfJdJ4Gwvx4$d4PA5AJ0806NzRnm root:$5$H8Mta5LDgGXp$QGdOJh.bFWgR3L719Z root:$5$H06URjv4BtOAbA$EJs1mZYhdKIVgCmn root:$5$OeB.O/GrmFB/az$SoE759KE9WIE17Uf root:$5$huiB9/sk$el3XMf7SGX81LnD3.SaF8J root:$5$fO7tfM.fjdSHA8G6$s.QIjfNniCzFdU root:$5$32at3SQJAD/xlw$HbXmBLVXTTyZfxQv root:$5$FHBFL/QdFl$FMipxpW0HlEFUIAr7IxF root:$5$sHvKf/M5OPdBuZZ$dz4qLOkTLGeCINX root:$5$hw4Vu/e34$/82lXu7ISrse.Ihk.qbqT root:$5$k1JOy/jRWZ$30YSk7kbhdKOjfDaiWVf root:$5$MnX.LUzqrB/B2$JuwqC.SmKFnMUWkEf root:$5$arRYf/PG$Xw6PpZNFO656p.Eb636iLt root:$5$5op/p8Hqs5$Nj2jA0Qxm80aG4fHW3oz root:$5$VHIT9/8yzZ$CpIK4ODps78GcqcsgiMT root:$5$.AlH7jBJoh/8$sjuVt.PcRH.vyvB3og root:$5$f7Ewinqm$nrJ2p/hKTuiEK//IfCTjth root:$5$N.dv/VCvrCADg$peSXfo35KN1dmbw/n root:$5$PSc4W./54l/SroH$CFFVOHRYK.Jj8Sp root:$5$8UBP3f4IcnAd/N1/$P.ud49qTStQ7Lw root:$5$qnXsZ/NlLZh/$nlaQVTS3FCJg1Jb2QG root:$5$xOpbbBqENR/7$boYJQzkCkZhRf7Uicf root:$5$V93tjZhzT$LrsIZWZmYo4ocRUvCixO6 root:$5$1MVz8/lf5oC/$rUKpnX23MhFx4.y2ZS
Mniej więcej połowa szóstych znaków skrótu to /
:
cat sixth-character-often-forward-slash.txt | cut --character=14 | sort
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
/
.
.
.
.
2
5
6
8
8
B
d
D
e
e
E
f
H
I
j
j
j
J
k
k
K
l
L
M
M
n
n
N
q
r
r
r
s
S
S
t
t
T
U
U
U
U
V
w
x
X
X
X
Z
Z
Z
man 3 crypt
i przeczytaj sekcję UWAGI, aby uzyskać pełny opis tego pola.for ((i=0; i<50; ++i)); do pwgen -1 -s 16 | mkpasswd -m sha-256 --stdin ; done | cut -c9 | sort | uniq -c
Odpowiedzi:
Format skrótu i źródło
Format skrótu hasła to
$<type>$<salt>$<hash>
, gdzie<type>
5
jest skrót skrótu oparty na SHA-256. Sól ma zwykle co najmniej 8 znaków (i jest w przykładach w pytaniu), więc szósty znak jest częścią soli.Te skróty są prawdopodobnie generowane przez wersję pakietu narzędzi Shadow (pakiet src
shadow
w Debianie,shadow-utils
w CentOS)Próbowałem dowiedzieć się, dlaczego dokładnie kod stronniczy na slash. (dzięki @thrig za pierwotne wykopanie kodu).
TLDR: To trochę interesujące, ale nie ma znaczenia.
Kod generujący sól
W
libmisc/salt.c
znajdujemygensalt
funkcję, która wywołujel64a
w pętli:Pętla pobiera losową liczbę
random()
, zamienia ją w kawałek struny i łączy ją z ciągiem tworzącym sól. Powtarzaj, aż zgromadzi się wystarczająca liczba znaków.To, co się dzieje,
l64a
jest jednak bardziej interesujące. Wewnętrzna pętla generuje jeden znak na raz z wartości wejściowej (która pochodzirandom()
):Pierwszy wiersz loop (
digit = value & 0x3f
) wybiera sześć bitów z wartości wejściowej, aif
klauzule zamieniają wartość utworzoną przez te znaki w znak. (.
dla zera,/
dla jednego,0
dla dwóch itd.)l64a
bierzelong
ale wartości wyjściowerandom()
są ograniczone doRAND_MAX
, który wydaje się być 2147483647 lub 2 ^ 31 - 1 na glibc. Tak więc wartość, która idzie dol64a
jest losową liczbą 31 bitów. Biorąc 6 bitów na raz lub wartość 31 bitów, otrzymujemy pięć rozsądnie równomiernie rozmieszczonych znaków, a także szósty, który pochodzi tylko z jednego bitu!Ostatni znak wygenerowany przez
l64a
nie może być.
jednak, ponieważ pętla ma również warunekvalue != 0
i zamiast.
szóstego znakul64a
zwraca tylko pięć znaków. Dlatego połowa czasu, szósta postać to a/
, a połowa czasul64a
zwraca pięć lub mniej znaków. W tym drugim przypadku następujący elementl64a
może również generować ukośnik na pierwszych pozycjach, więc w pełnej soli szósty znak powinien być ukośnikiem nieco ponad połowę czasu.Kod ma również funkcję losowego wybierania długości soli, ma od 8 do 16 bajtów. To samo nastawienie dla postaci z ukośnikiem występuje również w przypadku kolejnych wywołań, w
l64a
których 11. i 12. postać również będzie miała ukośnik częściej niż cokolwiek innego. 100 soli przedstawionych w pytaniu ma 46 ukośników odpowiednio na szóstej pozycji, a 13 i 15 odpowiednio na 11. i 12. pozycji. (nieco mniej niż połowa soli ma mniej niż 11 znaków).Na Debianie
Na Debianie nie mogłem tego odtworzyć za pomocą prostej,
chpasswd
jak pokazano w pytaniu. Alechpasswd -c SHA256
wykazuje to samo zachowanie. Zgodnie z instrukcją domyślną akcją bez-c
jest umożliwienie PAM obsługi mieszania, więc najwyraźniej PAM na Debianie przynajmniej używa innego kodu do wygenerowania soli. Jednak nie patrzyłem na kod PAM w żadnej dystrybucji.(Poprzednia wersja tej odpowiedzi stwierdzała, że efekt nie pojawił się na Debianie. To nie było poprawne).
Znaczenie i wymagania dotyczące soli
Czy to ma jednak znaczenie? Jak skomentował @RemcoGerlich, jest to tylko kwestia kodowania. Będzie to skutecznie naprawić niektóre kawałki soli do zera, ale jest prawdopodobne, że będzie to miało żadnego znaczącego wpływu w tym przypadku, ponieważ pochodzenie tych bitów jest to wywołanie
srandom
wseedRNG
:Jest to wariant dawnego zwyczaju wysiewu RNG z bieżącym czasem. (
tv_sec
itv_usec
są sekundami i mikrosekundami bieżącego czasu,getpid()
podają identyfikator procesu, jeśli jest uruchomiony). Ponieważ czas i PID nie są bardzo nieprzewidywalne, ilość losowości tutaj prawdopodobnie nie będzie większa niż to, co może utrzymać kodowanie.Czas i PID nie są czymś, za pomocą którego chcesz tworzyć klucze , ale mogą być nieprzewidywalne dla soli. Sole muszą być wyraźne, aby zapobiec testowaniu wielokrotnych skrótów haseł za pomocą jednego obliczenia, ale powinny być również nieprzewidywalne, aby zapobiec lub spowolnić celowane obliczenia wstępne, które mogłyby zostać wykorzystane do skrócenia czasu od uzyskania skrótów haseł do uzyskania rzeczywistych haseł .
Nawet z drobnymi problemami, o ile algorytm nie generuje tej samej soli dla różnych haseł, powinno być w porządku. I wydaje się, że tak nie jest, nawet jeśli generuje kilkadziesiąt w pętli, jak pokazuje lista w pytaniu.
Ponadto kod, o którym mowa, nie jest używany do niczego poza generowaniem soli do haseł, więc nie ma to wpływu na problemy gdzie indziej.
W przypadku soli zobacz także np. Ten na Stack Overflow i ten na security.SE .
Wniosek
Podsumowując, nie ma nic złego w twoim systemie. Sprawdzenie, czy hasła są dobre i nieużywane w niepowiązanych systemach, jest bardziej przydatne do przemyślenia.
źródło
Ta postać jest częścią soli zgodnie z
crypt(3)
instrukcją. Biorąc pod uwagę, że długość soli (ciąg między$5$
identyfikatorem a kolejnymi$
) różni się dla wyświetlanych skrótów, nie jestem do końca pewien, co ilustruje wybranie losowego znaku z tej konkretnej kolumny dla kilku haseł.Z drugiej strony,
/
występuje częściej (102 wystąpienia) w całej soli w porównaniu z innymi możliwymi postaciami (około 18), więcchpasswd
wydaje się, że coś w niej faworyzuje tę postać w soli;w systemie RedHat EL 6 pojawia się:
I tak, kod wewnątrz
shadow-utils-4.1.5.1-5.el6
wykazuje tendencyjność,/
która może ułatwić ataki słownikowe:Co skutkuje w:
A następnie korzystając z tych samych procedur z najnowszego https://github.com/shadow-maint/shadow/blob/master/libmisc/salt.c , stwierdzamy, że nadal istnieje uprzedzenie
/
. Więc, tak, to jest błąd, który powinien zostać załatany, więc/
nie jest tak bardzo faworyzowany, ponieważ idealnie postacie z soli powinny mieć jednakową wagę.źródło
mkpasswd(1)
może być nakładką nacrypt(3)
, ale to nie to samo, co uruchamianiechpasswd(1)
, które jest częścią pakietu „shadow-utils” w CentOS i „passwd” w Debianie. Zamiast tego powinieneś porównać jabłka z jabłkami. Rozważ następujący skrypt:Dane wyjściowe z Debian Sid:
Dane wyjściowe z CentOS 7:
Tak więc problem nie jest unikalny dla CentOS, ale prawdopodobnie pochodzi z góry, z którego czerpią oba projekty.
źródło
: > /tmp/salts.txt
to samo cotouch /tmp/salts.txt
?:
jest NOP, prawda?touch(1)
tworzy plik, jeśli nie istnieje, ale po prostu aktualizuje zmodyfikowany znacznik czasu, jeśli istnieje. To nie jest właściwy sposób na opróżnienie pliku.: > file
zagwarantuje, że istnieje i że jest pusty.