Linux에서 비밀번호 해시의 6 번째 문자는 무엇이며 왜 종종 슬래시입니까?


83

Linux에서 비밀번호 해시의 여섯 번째 문자는 무엇 /etc/shadow입니까?

내 강아지 스타일의 리눅스 상자에서 shufand를 사용하여 100 개의 임의의 암호를 생성하려고 /dev/urandom하면 여섯 번째 문자는 /약 절반입니다.

내 질문은 CD에서 새로 시작할 때마다 부팅하기 때문에 프로덕션 목적이 아닙니다. 이것은 시스템이 잘못 구성되었거나 안전하지 않다는 것을 의미합니까?

파일 shufbusybox링크 인지 확인하기 위해 파일을 실행 했습니다 .

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

나는 생각하지 않는다 shufA는 busybox여기 링크.

ls -l /usr/bin/shuf

    -rwxr-xr-x 1 root root 41568 Mar  7  2015 /usr/bin/shuf

동안

ls -l /bin/wget

    lrwxrwxrwx 1 root root 14 Apr 29 03:49 wget -> ../bin/busybox

내가 한 일에 대한 대략적인 아이디어는 다음과 같습니다.

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

6 번째 해시 문자의 대략 절반은 다음과 /같습니다.

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

3
man 3 crypt이 필드에 대한 자세한 설명은 참고 섹션을 읽으십시오.
Stephen Harris

(완전히 조사하고자하는 사람을위한 힌트로 왼쪽) : 비밀번호 필드에는 64자가 사용됩니다. 아마 일부 base64 변형이 사용되었을 것입니다. 그래서 나는 것 같아요 당신이보고있는 것은 base64로 패딩이지만 ... 그 다음 소금의 끝이 아니다 것은 이상
derobert

1
데비안 테스트와 mkpasswd를 사용하면 이런 일이 발생하지 않습니다. 실제로 mkpasswd를 사용하면 실제로 루트 암호를 설정하는 것보다 테스트하기가 더 쉽습니다.for ((i=0; i<50; ++i)); do pwgen -1 -s 16 | mkpasswd -m sha-256 --stdin ; done | cut -c9 | sort | uniq -c
derobert

현재 우분투 14.04 또는 16.04에서 이것을 재현 할 수 없습니다. 슬래시는 빈도 목록의 중간에 가깝습니다 (50 대신 5000 루프로 위의 @derobert 스 니펫 사용). 그러나 여전히 약간 균일하지 않습니다. 가장 자주 발생하는 문자 (q) @ 총 2.00 %는 최소보다 1.63 더 빈번합니다. 빈번한 1 (r) @ 총 1.22 %.
arielf

@arielf 나는 이것이 통계적으로 유의미하다고 의심합니다. 확인하려면 χ2 테스트 와 같은 작업을 수행 해야하지만 Unix & Linux 영역 외부에 있고 Cross Validated 영역에 들어가는 것 입니다.
derobert

답변:


86

해시 형식 및 소스

비밀번호 해시의 형식은입니다 $<type>$<salt>$<hash>. 여기서 <type> 5SHA-256 기반 해시입니다. 소금은 일반적으로 8 자 이상이며 문제의 예에서 6 번째 문자는 소금의 일부입니다.

이러한 해시는 섀도우 도구 모음 ( CentOS의 shadow데비안의 src 패키지) 버전에 의해 생성 될 수 있습니다.shadow-utils

정확히 코드가 슬래시를 바이어스하는 이유를 찾으려고 노력했습니다. (원래 코드를 파낸 @thrig 덕분에.)

TLDR : 약간 흥미롭지 만 중요하지 않습니다.


소금을 생성하는 코드

에서 libmisc/salt.c, 우리는 찾을 gensalt함수 호출 l64a루프를 :

strcat (salt, l64a (random()));
do {
       strcat (salt, l64a (random()));
} while (strlen (salt) < salt_size);

루프는에서 임의의 숫자를 가져 와서 random()문자열로 변환하여 소금을 형성하는 문자열에 연결합니다. 충분한 문자가 수집 될 때까지 반복하십시오.

l64a그래도 더 흥미로운 일 이 있습니다. 내부 루프는 입력 값 (에서 온 random()) 에서 한 번에 한 문자 씩 생성합니다 .

for (i = 0; value != 0 && i < 6; i++) {
    digit = value & 0x3f;

    if (digit < 2) {
        *s = digit + '.';
    } else if (digit < 12) {
        *s = digit + '0' - 2;
    } else if (digit < 38) {
        *s = digit + 'A' - 12;
    } else {
        *s = digit + 'a' - 38;
    }

    value >>= 6;
    s++;
}

루프의 첫 번째 줄 ( digit = value & 0x3f)은 입력 값에서 6 비트를 선택하고 if절은 해당 값으로 구성된 값을 문자로 바꿉니다. ( .0, /1, 02 등)

l64aa를 사용 long하지만로 출력되는 값 random()은으로 제한 RAND_MAX되며 glibc에서 2147483647 또는 2 ^ 31-1로 나타납니다. 따라서 값 l64a은 31 비트의 난수입니다. 한 번에 6 비트 또는 31 비트 값을 취함으로써 합리적으로 분포 된 5 개의 문자와 1 비트에서만 나오는 6 개의 문자를 얻습니다!

에 의해 생성 된 마지막 문자는 l64a수 없습니다 .루프는 조건이 있기 때문에,하지만 value != 0, 대신에의 .같은 여섯 번째 문자, l64a다섯 문자를 반환합니다. 따라서 시간의 절반, 여섯 번째 문자는 a /이고 시간의 절반 l64a은 5 자 이하의 문자를 반환합니다. 후자의 경우 다음 l64a은 첫 번째 위치에서 슬래시를 생성 할 수 있으므로 전체 소금에서 여섯 번째 문자는 절반보다 약간 긴 슬래시 ​​여야합니다.

이 코드에는 소금의 길이를 무작위로 추출하는 기능이 있으며 8 ~ 16 바이트입니다. 슬래시 문자에 대한 동일한 편향이 발생하여 추가 호출 l64a이 발생하여 11 번째 및 12 번째 문자도 다른 것보다 더 자주 슬래시를 갖습니다. 이 질문에 제시된 100 개의 소금은 각각 6 위에 46 슬래시, 11 위와 12 위에 13과 15가 있습니다. (소금의 절반 미만이 11 자보다 짧습니다).

데비안에서

데비안에서는 chpasswd질문에 표시된 것처럼 똑바로 이것을 재현 할 수 없었습니다 . 그러나 chpasswd -c SHA256같은 행동을 보여줍니다. 매뉴얼에 따르면,없는 기본 동작 -c은 PAM이 해싱을 처리하도록하는 것이므로 Debian의 PAM은 적어도 다른 코드를 사용하여 소금을 생성합니다. 그러나 배포판에서 PAM 코드를 보지 않았습니다.

(이 답변의 이전 버전은 그 효과가 데비안에 나타나지 않았다고 언급했습니다. 정확하지 않습니다.)

염의 중요성 및 요구 사항

그래도 문제가 되나요? @RemcoGerlich가 언급했듯이 인코딩의 문제 일뿐입니다. 그것은 소금의 일부 비트를 0으로 효과적으로 고정시킬 것이지만,이 비트의 원점이 다음에서 호출되기 때문에이 경우에는 큰 영향을 미치지 않을 것 srandom입니다 seedRNG.

srandom (tv.tv_sec ^ tv.tv_usec ^ getpid ());

이것은 현재 시간으로 RNG를 파종하는 오래된 관습의 변형입니다. ( tv_sec하고 tv_usec초와 현재 시간의 마이크로이며, getpid()시간으로. 실행중인 프로세스의 경우 프로세스 ID를 제공)와 PID를 매우 예측할 수없는, 여기 난수의 양이 인코딩에 저장할 수있는 것보다 더 큰 가능성이있다.

시간과 PID는 를 만들려 는 것이 아니지만 소금에 대해 예측할 수 없을 수도 있습니다. 솔트 단일 계산으로 여러 암호 해시를 무차별 테스트하는 것을 방지하기 위해 구별 되어야 하지만 예측 된 예측할 수 없어 대상 사전 계산을 방지하거나 느리게 해야 합니다. .

약간의 문제가 있더라도 알고리즘이 다른 암호에 대해 동일한 소금을 생성하지 않는 한 괜찮습니다. 그리고 질문 목록에 나와 있듯이 루프에서 수십 개를 생성 할 때조차 보이지 않습니다.

또한 문제의 코드는 암호에 대한 염분을 생성하는 것 외에 다른 용도로 사용되지 않으므로 다른 문제에 대한 영향은 없습니다.

소금에 대해서는 스택 오버플로보안 대한 예도 참조하십시오 .

결론

결론적으로 시스템에는 아무런 문제가 없습니다. 암호가 올바른지 확인하고 관련없는 시스템에서 사용하지 않는 것이 더 유용합니다.


2
따라서 실제 소금은 편중되지 않으며, 그것이 어떻게 인코딩되는지의 유물 일 뿐이며 보안에 영향을 미치지 않습니다. 맞습니까?
RemcoGerlich

8
@RemcoGerlich 이것은 바이어스의 교재 정의입니다. 모든 비트가 균일하게 설명되지는 않기 때문입니다. 이것은 또한이 코드가 비 소금 상황에서 사용되는 다른 프로젝트에도 영향을 미칩니다. / etc / shadow에 대한 암호의 소금으로 showtopper는 아니지만 걱정입니다.
Aaron Toponce

@RemcoGerlich, 거의 그렇습니다. 좋아, 그것은 강력한 RNG가 아니기 때문에 우리는 그 편견에 대해 이야기 할 수 있습니다. 그러나 보안 측면에서 소금은 중요하지 않습니다.
ilkkachu

3
귀하가 연결 한 security.SE 게시물을 잘못 해석했으며 연결 한 SO 게시물에 대한 수락 된 답변이 잘못되었으므로, 투표와 모순되는 10 배 이상의 다른 답변이 있습니다. "소금은 구별 될 필요가있다"는 진술은 사실이 아니다. 소금 의 엔트로피 가 중요합니다. 왜냐하면 그것이 사전 계산의 어려움을 얼마나 많이 증가 시키는가에 달려 있기 때문입니다. 이 소금은 편견 때문에 길이에 비해 엔트로피가 적습니다. 아니 매우 적은 있지만, 뭔가 5와 같은 비트 이하. 결함입니다.
hobbs

아마도 누군가는 security.SE 질문을 작성하여 자격을 갖춘 의견을 얻기 위해이 기능을 구체적으로 참조해야합니다.
hobbs

26

그 특성은 crypt(3)매뉴얼 에 따라 소금의 일부입니다 . 소금의 길이 ( $5$ID와 후속 문자열 사이의 문자열 $)가 표시된 해시에 따라 다르므로 몇 가지 암호에 대해 특정 열에서 임의의 문자를 선택하는 것이 무엇인지 정확히 알 수 없습니다.

한편,이 / 입니다 오히려 더에서 (102 개 인스턴스) 널리 전체 에 이렇게 뭔가 (18 정도) 다른 가능한 문자에 비해 소금 chpasswd소금에 그 문자를 선호하는 것처럼 보인다;

for x in `seq 1 100000`; do
  echo testacct:asdfasdfasdf | chpasswd -c SHA256
  awk -F: '/testacct/{print $2}' /etc/shadow | awk -F\$ '{print $3}' >> salts
done
perl -nle 'print for m/(.)/g' salts | sort | uniq -c | sort -nr | head -5

RedHat EL 6 시스템에서 다음이 실행됩니다.

   1006 /
    195 X
    193 U
    193 q
    193 e

그렇습니다.이 코드는 사전 공격을보다 쉽게 ​​만들 수 shadow-utils-4.1.5.1-5.el6있는 편견을 나타냅니다 /.

#include <sys/time.h>

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

// these next two borrowed from libmisc/salt.c of shadow-4.1.5.1 from
// Centos 6.8 RPM at http://vault.centos.org/6.8/os/Source/SPackages/shadow-utils-4.1.5.1-5.el6.src.rpm
char *l64a(long value)
{
    static char buf[8];
    char *s = buf;
    int digit;
    int i;

    if (value < 0) {
        abort();
    }

    for (i = 0; value != 0 && i < 6; i++) {
        digit = value & 0x3f;

        if (digit < 2) {
            *s = digit + '.';
        } else if (digit < 12) {
            *s = digit + '0' - 2;
        } else if (digit < 38) {
            *s = digit + 'A' - 12;
        } else {
            *s = digit + 'a' - 38;
        }

        value >>= 6;
        s++;
    }

    *s = '\0';

    return (buf);
}

static void seedRNG(void)
{
    struct timeval tv;
    static int seeded = 0;

    if (0 == seeded) {
        (void) gettimeofday(&tv, NULL);
        srandom(tv.tv_sec ^ tv.tv_usec ^ getpid());
        seeded = 1;
    }
}

int main(void)
{
    seedRNG();
    for (int x = 0; x < 1000; x++) {
        printf("%s\n", l64a(random()));
    }

    exit(0);
}

결과 :

% ./salttest | perl -nle 'print for m/(.)/g' | sort | uniq -c | sort -nr | head -3
 593 /
  96 8
  93 3

그리고 최신 https://github.com/shadow-maint/shadow/blob/master/libmisc/salt.c 와 동일한 루틴을 사용하면 여전히에 대한 편견이 있음을 알 수 /있습니다. 그렇습니다. /이것은 패치되어야하는 버그입니다. 이상적으로는 소금 문자의 가중치가 동일해야하기 때문에 많이 선호되지는 않습니다.


14
소금에 담긴 Biases는 그 자체로는 해롭지 않습니다 (예 : 편견과는 달리). 소금은 독창적이어야하며 예측할 필요가 없습니다. MAC 주소 (또는 기계를 고유하게 식별하는 것)와 시간 (시계가 거꾸로 돌아 가지 않는다고 가정)으로 구성된 소금은 괜찮을 것입니다. “이상적으로 소금 문자의 무게가 같아야한다”는 말이 잘못되었습니다.
Gilles

7
@thrig 아니요, 소금은 사전 공격에 도움이되지 않기 때문에 예측 가능한 소금은 사전 공격에 도움이되지 않습니다. 솔트는 여러 계정을 대상으로하는 공격 (보다 정확하게는 여러 계정-동일한 계정의 연속 해시)에 도움이되며, 중요한 점은 각 계정마다 솔트가 다르다는 것입니다. 소금의 예측 불가능 성은 관련성이 없으며 고유성 만 있습니다 (실제로 반복 횟수가 적더라도 충분합니다).
Gilles

3
Gilles가 말한 핵심 요점은 소금 생성기가 나쁘지만 그다지 나쁘지 않은 동일한 공간 파일 (또는 공격자가 한 번에 공격 할 수있는 여러 시스템에서 실제 충돌이 발생할 수 있음)이 많이 있다는 것입니다. ). 이것이 소금이 작동하는 데 중요한 전부입니다. Rainbow 테이블 을 물리 치기 위해서는 약간의 무작위성이 필요합니다 .
Peter Cordes

7
그러나 소금이 잘못 생성되면 나머지 암호 코드에 대한 확신을 얻지 못합니다.
immibis

3
소금을 사용하면 전 세계적으로 독창적이어야합니다. 그들은 무작위 일 필요가 없으며 비밀 일 필요도 없습니다. 그러나 전 세계적으로 고유해야합니다. OS RNG에서 임의의 비트를 가져 오는 것보다 카운터를 늘리거나 멋진 결정 론적 알고리즘을 만들려고하면 수행하기가 더 어렵다는 것이 밝혀졌습니다. 16 개의 base64 문자를 무작위로 생성하면 충돌 할 확률이 64/16입니다. 물론, 소금의 요점은 무지개 테이블 공격을 결실없이 만드는 것입니다. 이 경우 16 자의 base64 소금 공간은 64 ^ 15 <n <64 ^ 16입니다. 쇼 토퍼는 아니지만 쉽게 고칠 수 있습니다.
Aaron Toponce 2012 년

4

mkpasswd(1)에 대한 프론트 엔드 crypt(3)일 수 있지만 chpasswd(1)centOS의 "shadow-utils"패키지와 Debian의 "passwd"의 일부인 running 과 는 다릅니다 . 대신, 사과와 사과를 비교해야합니다. 다음 스크립트를 고려하십시오.

#!/bin/bash

# This repeatedly changes a `saltuser' password
# and grabs the salt out of /etc/shadow.
# Requires root and the existence of `saltuser' user.

if [ $EUID -ne 0 ]; then
    echo "This script requires root access to read /etc/shadow."
    exit 1
fi

grep -q saltuser /etc/passwd

if [ $? -ne 0 ]; then
    echo "This script requires the 'saltuser' to be present."
    exit 2
fi

: > /tmp/salts.txt

for i in {1..1000}; do
    PW=$(tr -cd '[[:print:]]' < /dev/urandom | head -c 64)
    echo "saltuser:${PW}" | chpasswd -c SHA256 -s 0 2> /dev/urandom
    awk -F '$' '/^saltuser/ {print $3}' /etc/shadow >> /tmp/salts.txt
done

while read LINE; do
    # 6th character in the salt
    echo ${LINE:5:1}
done < /tmp/salts.txt | sort | uniq -c | sort -rn

데비안 시드의 출력 :

512 /
 14 T
 13 W
 13 v
 13 t
 12 x
 12 m
 12 d
 11 p
 11 L
 11 F
 11 4
 10 s
 10 l
 10 g
 10 f
 10 7
 10 6
  9 Z
  9 w
  9 N
  9 H
  9 G
  9 E
  9 A
  8 Y
  8 X
  8 r
  8 O
  8 j
  8 c
  8 B
  8 b
  8 9
  7 u
  7 R
  7 q
  7 P
  7 M
  7 k
  7 D
  6 z
  6 y
  6 U
  6 S
  6 K
  6 5
  5 V
  5 Q
  5 o
  5 J
  5 I
  5 i
  5 C
  5 a
  5 3
  4 n
  4 h
  4 e
  4 2
  4 0
  4 .
  3 8
  3 1

CentOS 7의 출력 :

504 /
 13 P
 13 B
 12 s
 12 Z
 11 e
 11 Y
 11 O
 11 L
 11 G
 10 w
 10 u
 10 q
 10 i
 10 h
 10 X
 10 I
 10 E
  9 x
  9 g
  9 f
  9 W
  9 F
  9 C
  9 9
  9 8
  8 v
  8 t
  8 c
  8 b
  8 S
  8 H
  8 D
  8 0
  7 z
  7 y
  7 o
  7 k
  7 U
  7 T
  7 R
  7 M
  7 A
  7 6
  7 4
  7 1
  6 p
  6 d
  6 a
  6 Q
  6 J
  6 5
  6 .
  5 r
  5 m
  5 j
  5 V
  5 3
  5 2
  4 n
  4 l
  4 N
  4 K
  3 7

따라서이 문제는 CentOS에만 국한된 것이 아니라 두 프로젝트가 모두 끌어 오는 업스트림에서 비롯된 것일 수 있습니다.


: > /tmp/salts.txt은 동일 touch /tmp/salts.txt? :NOP입니까?
someonewithpc

1
@someonewithpc 파일을 비우는 POSIX 방식입니다. touch(1)존재하지 않는 경우 파일을 생성하지만 수정 된 타임 스탬프가 존재하는 경우에만 업데이트합니다. 파일을 비우는 올바른 방법이 아닙니다. : > file존재하고 비어 있음을 보장합니다.
Aaron Toponce

@Aaron, 네, 당신은 절대적으로 정확합니다. 한 배포판에만 국한된 것은 아닙니다.
ilkkachu
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.