แฮชรหัสผ่านตัวที่ 6 ของ Linux คืออะไรและทำไมจึงเป็นเครื่องหมายทับ


83

บน Linux ตัวที่หกของแฮชรหัสผ่านถูกเก็บไว้ใน/etc/shadowอะไร

บนกล่อง linux style puppy ของฉันหากฉันพยายามสร้างรหัสผ่านแบบสุ่ม 100 รหัสโดยใช้shufและ/dev/urandomจากนั้นตัวอักษรตัวที่หกก็/ประมาณครึ่งหนึ่ง

คำถามของฉันไม่ได้มีวัตถุประสงค์เพื่อการผลิตเนื่องจากฉันบูตมันขึ้นมาใหม่ทุกครั้งจากซีดี นี่หมายความว่าระบบของฉันถูกตั้งค่าผิดหรือไม่ปลอดภัยในบางวิธีหรือไม่?

ฉันรันไฟล์shufเพื่อดูว่าเป็นbusyboxลิงก์หรือไม่

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

ฉันไม่คิดว่าshufเป็น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 ตัวในช่องรหัสผ่าน มีโอกาสมากที่จะใช้ตัวแปรเบส 64 บางตัว ดังนั้นฉันเดาว่าสิ่งที่คุณเห็นคือฐานรอง 64 แต่มันแปลกที่ว่ามันไม่ได้อยู่ท้ายเกลือแล้ว ...
Derobert

1
ด้วยการทดสอบ Debian และ mkpasswd นี้ไม่ได้เกิดขึ้นอยากรู้อยากเห็นถ้ามันเกิดขึ้นกับ mkpasswd สำหรับคุณ (ตามที่ต้องการจะง่ายต่อการทดสอบกว่าจริงการตั้งค่ารหัสผ่าน root):for ((i=0; i<50; ++i)); do pwgen -1 -s 16 | mkpasswd -m sha-256 --stdin ; done | cut -c9 | sort | uniq -c
derobert

ฉันไม่สามารถทำซ้ำได้บน Ubuntu ปัจจุบัน 14.04 หรือ 16.04 Slash อยู่ใกล้กลางรายการความถี่ (ใช้ @derobert ส่วนย่อยด้านบนพร้อมกับ 5000 ลูปแทนที่จะเป็น 50) แต่ก็ยังดูไม่สม่ำเสมอ, char ที่พบบ่อยที่สุด (q) ที่ 2.00% จากทั้งหมดคือ 1.63 บ่อยกว่าอย่างน้อยที่สุด บ่อยครั้งหนึ่ง (r) @ 1.22% จากทั้งหมด
arielf

@ ตัวเองฉันสงสัยว่าเป็นนัยสำคัญทางสถิติ คุณต้องทำอะไรบางอย่างเช่นการทดสอบχ2เพื่อให้แน่ใจ แต่มันก็อยู่นอกอาณาเขตของUnix & Linuxและเข้าสู่ดินแดนที่ผ่านการตรวจสอบแล้ว
Derobert

คำตอบ:


86

รูปแบบแฮชและแหล่งที่มา

รูปแบบของแฮชรหัสผ่านคือ$<type>$<salt>$<hash>ที่ซึ่งแฮชที่<type> 5ใช้ SHA-256 เกลือมักจะมีอย่างน้อย 8 ตัวอักษร (และเป็นตัวอย่างในคำถาม) ดังนั้นอักขระที่หกจึงเป็นส่วนหนึ่งของเกลือ

แฮชเหล่านั้นถูกสร้างขึ้นโดยชุดเครื่องมือเงา (แพ็คเกจ src shadowใน Debian shadow-utilsใน CentOS)

ฉันพยายามที่จะหาสาเหตุที่แน่นอนรหัสอคติเฉือน (ขอบคุณ @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) เลือกหกบิตจากค่าอินพุตและส่วนifคำสั่งเปลี่ยนค่าที่เกิดขึ้นจากเหล่านั้นเป็นตัวละคร ( .สำหรับศูนย์/สำหรับหนึ่ง0สำหรับสอง ฯลฯ )

l64aใช้เวลาlongแต่ค่าที่ส่งออกโดยrandom()ถูก จำกัดRAND_MAXซึ่งดูเหมือนจะเป็น 2147483647 หรือ 2 ^ 31 - 1 บน glibc ดังนั้นค่าที่ไปl64aเป็นจำนวนสุ่ม 31 บิต ด้วยการรับ 6 บิตต่อครั้งหรือค่า 31 บิตเราจะได้รับตัวละครที่มีการแจกแจงอย่างเท่าเทียมกันห้าตัวบวกที่หกที่มาจากบิตเดียว!

อักขระตัวสุดท้ายที่สร้างโดยl64aไม่สามารถเป็น.ได้อย่างไรก็ตามเนื่องจากลูปยังมีเงื่อนไขvalue != 0และแทนที่จะ.เป็นตัวอักษรตัวที่หกจึงl64aส่งกลับอักขระได้เพียงห้าตัว ดังนั้นครึ่งเวลาตัวอักษรตัวที่หกคือ a /และครึ่งเวลาl64aส่งคืนตัวละครห้าตัวหรือน้อยกว่า ในกรณีหลังต่อไปนี้l64aยังสามารถสร้างเครื่องหมายทับในตำแหน่งแรกดังนั้นในเกลือแบบเต็มอักขระที่หกควรเป็นเครื่องหมายทับมากกว่าครึ่งเวลา

รหัสนี้ยังมีฟังก์ชั่นการสุ่มความยาวของเกลือด้วยคือ 8 ถึง 16 ไบต์ อคติเดียวกันสำหรับตัวอักษรทับเกิดขึ้นด้วยการโทรต่อไปl64aซึ่งจะทำให้ตัวละครที่ 11 และ 12 มีเครื่องหมายทับบ่อยกว่าสิ่งอื่นใด เกลือที่นำเสนอในคำถาม 100 ข้อมีเครื่องหมายทับ 46 ตำแหน่งในตำแหน่งที่หกและ 13 และ 15 ในตำแหน่งที่ 11 และ 12 ตามลำดับ (เกลือที่น้อยกว่าครึ่งหนึ่งจะสั้นกว่า 11 ตัวอักษร)

บนเดเบียน

บนเดเบียนฉันไม่สามารถทำซ้ำสิ่งนี้ได้ด้วยวิธีตรงchpasswdดังที่แสดงในคำถาม แต่chpasswd -c SHA256แสดงพฤติกรรมเดียวกัน ตามคู่มือการดำเนินการเริ่มต้นโดยไม่มี-cคือให้ PAM จัดการกับการแปลงแป้นพิมพ์ดังนั้น PAM บนเดเบียนอย่างน้อยก็ใช้รหัสที่แตกต่างกันเพื่อสร้างเกลือ อย่างไรก็ตามฉันไม่ได้ดูรหัส PAM ในการแจกจ่ายใด ๆ

(รุ่นก่อนหน้าของคำตอบนี้ระบุว่าเอฟเฟกต์ไม่ปรากฏบนเดเบียนนั่นไม่ถูกต้อง)

ความสำคัญและข้อกำหนดสำหรับเกลือ

มันมีความสำคัญอย่างไร @RemcoGerlich ให้ความเห็นว่าเป็นเรื่องของการเข้ารหัสเท่านั้น มันมีประสิทธิภาพจะแก้ไขบิตของเกลือบางส่วนให้เป็นศูนย์ แต่มันก็เป็นไปได้ว่าจะไม่มีผลกระทบอย่างมีนัยสำคัญในกรณีนี้ตั้งแต่ต้นกำเนิดของบิตเหล่านั้นเป็นสายนี้srandomในseedRNG:

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

นี่คือความแตกต่างของเจ้าเก่าที่กำหนดของการเพาะ RNG ด้วยเวลาปัจจุบัน ( tv_secและtv_usecเป็นวินาทีและไมโครวินาทีของเวลาปัจจุบันgetpid()ให้รหัสกระบวนการหากกระบวนการที่กำลังทำงานอยู่) เนื่องจากเวลาและ PID นั้นไม่แน่นอนคาดเดาไม่ได้จำนวนการสุ่มที่นี่น่าจะไม่ใหญ่กว่าการเข้ารหัสที่สามารถเก็บได้

เวลาและ PID ไม่ใช่สิ่งที่คุณต้องการสร้างกุญแจด้วย แต่อาจคาดเดาไม่ได้สำหรับเกลือ เกลือจะต้องมีความแตกต่างเพื่อป้องกันการทดสอบด้วยรหัสผ่านหลายครั้งด้วยการคำนวณแบบเดียว แต่ควรคาดเดาไม่ได้เพื่อป้องกันหรือชะลอการกำหนดเป้าหมายล่วงหน้าซึ่งสามารถใช้ในการย่นระยะเวลาในการรับรหัสผ่านจริง ๆ .

แม้ว่าจะมีปัญหาเล็กน้อยตราบใดที่อัลกอริทึมไม่ได้สร้างรหัสผ่านเดียวกันสำหรับรหัสผ่านที่แตกต่างกันมันก็น่าจะใช้ได้ และดูเหมือนจะไม่เกิดขึ้นแม้ว่าจะสร้างสองสามโหลในการวนซ้ำตามรายการในคำถามที่แสดง

นอกจากนี้รหัสที่เป็นปัญหาไม่ได้ถูกนำไปใช้เพื่อการใด ๆ ยกเว้นการสร้างเกลือสำหรับรหัสผ่านดังนั้นจึงไม่มีความเกี่ยวข้องกับปัญหาอื่น ๆ

สำหรับเกลือเห็นเช่นนี้ในกองมากเกินและนี้ security.SE

ข้อสรุป

สรุปแล้วไม่มีอะไรผิดปกติกับระบบของคุณ การทำให้แน่ใจว่ารหัสผ่านของคุณนั้นดีและไม่ได้ใช้กับระบบที่ไม่เกี่ยวข้องจะมีประโยชน์มากกว่าที่คิด


2
ดังนั้นเกลือที่เกิดขึ้นจริงจะไม่ลำเอียงมันเป็นเพียงสิ่งประดิษฐ์ของวิธีการเข้ารหัสและมันไม่มีผลกระทบด้านความปลอดภัยใด ๆ ถูกต้องหรือไม่
RemcoGerlich

8
@RemcoGerlich นี่คือนิยามตำราเรียนของอคติ เพราะไม่ใช่ทุกบิตที่มีการคิดอย่างสม่ำเสมอ สิ่งนี้ยังมีความหมายในโครงการอื่น ๆ ที่ใช้รหัสนี้ในบริบทที่ไม่ใช่เกลือ เช่นเดียวกับเกลือในรหัสผ่านสำหรับ / etc / shadow มันไม่ใช่ showstopper แต่เป็นสิ่งที่น่ากังวล
Aaron Toponce

@RemcoGerlich ใช่แล้ว โอเคนั่นไม่ใช่ RNG ที่แข็งแกร่งดังนั้นเราจึงสามารถพูดคุยเกี่ยวกับอคติได้ แต่การรักษาความปลอดภัยที่ชาญฉลาดมันไม่สำคัญสำหรับเกลือ
ilkkachu

3
คุณตีความการรักษาความปลอดภัยผิดโพสต์ที่คุณเชื่อมโยงและคำตอบที่ยอมรับในโพสต์ SO ที่คุณเชื่อมโยงไปนั้นเป็นสิ่งที่ผิดซึ่งเป็นสาเหตุที่มีคำตอบอื่นที่มีมากกว่า 10 คะแนนโหวตขัดแย้งกับมัน คำแถลงว่า "เกลือจะต้องชัดเจนเท่านั้น" ไม่เป็นความจริง เอนโทรปีของเรื่องเกลือเพราะนั่นคือสิ่งที่ควบคุมโดยวิธีการมากมันจะเพิ่มความยากลำบากในการ precomputation เกลือเหล่านี้มีเอนโทรปีน้อยกว่าความยาวของมันเนื่องจากความลำเอียง ไม่น้อยกว่าช่วงวิกฤตแต่มีบางอย่างที่น้อยกว่า 5 บิต มันเป็นข้อบกพร่อง
ฮอบส์

บางทีใครบางคนควรสร้างความปลอดภัยคำถาม SE อ้างอิงโดยเฉพาะฟังก์ชั่นนี้เพื่อรับความเห็น
ฮอบส์

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
อคติในเกลือไม่เป็นอันตรายต่อตัวเอง (ต่างจากอคติพูดคีย์) เกลือนั้นต้องมีความเป็นเอกลักษณ์เท่านั้นและไม่จำเป็นต้องคาดเดาไม่ได้ เกลือที่ประกอบด้วยที่อยู่ MAC (หรือสิ่งที่ระบุเครื่องโดยเฉพาะ) และเวลา (สมมติว่านาฬิกาไม่ย้อนกลับ) จะไม่เป็นไร คำแถลงว่า“ ตัวละครเกลือควรมีน้ำหนักเท่ากัน” ผิด
Gilles

7
@thrig ไม่เกลือที่คาดการณ์ไม่ได้ช่วยในการโจมตีด้วยพจนานุกรมเพราะเกลือไม่สามารถช่วยในการโจมตีด้วยพจนานุกรมได้ เกลือช่วยในการโจมตีที่กำหนดเป้าหมายหลายบัญชี (แม่นยำยิ่งขึ้น: แฮชหลายครั้ง - และแฮชต่อเนื่องในบัญชีเดียวกัน) และสำหรับสิ่งนี้สิ่งที่สำคัญคือเกลือนั้นแตกต่างกันไปในแต่ละบัญชี ความไม่สามารถคาดเดาได้ของเกลือนั้นไม่เกี่ยวข้องเฉพาะความเป็นเอกลักษณ์ของพวกเขาเท่านั้น
Gilles

3
จุดสำคัญของสิ่งที่ Gilles พูดก็คือมีห้องพักมากมายสำหรับเครื่องกำเนิดเกลือที่น่าสงสาร แต่ก็ไม่เลวจนเกือบจะมีการชนกันจริงในไฟล์เงาเดียวกัน (หรือในหลาย ๆ ระบบที่ผู้โจมตีอาจโจมตีในครั้งเดียว ) นี่คือทั้งหมดที่สำคัญสำหรับเกลือในการทำงาน การสุ่มเพื่อเอาชนะตาราง Rainbowใช้เวลาเพียงเล็กน้อยเท่านั้น
Peter Cordes

7
อย่างไรก็ตามหากเกลือนั้นถูกสร้างอย่างไม่ดีมันจะไม่สร้างแรงบันดาลใจให้กับรหัส crypto ที่เหลือ
Immibis

3
ด้วยเกลือพวกเขาจะต้องไม่ซ้ำกันทั่วโลก พวกเขาไม่จำเป็นต้องสุ่มและพวกเขาไม่จำเป็นต้องเป็นความลับ แต่พวกเขาจะต้องไม่ซ้ำกันทั่วโลก ปรากฎว่ามันยากที่จะทำถ้าคุณพยายามเพิ่มตัวนับหรือสร้างอัลกอริธึมที่กำหนดขึ้นแฟนซีกว่าเพียงแค่หยิบบิตสุ่มจาก OS RNG หากคุณสร้าง 16 base64 ตัวอักษรแบบสุ่มแสดงว่าคุณมีโอกาส / 64 ^ 16 การชน แน่นอนว่าจุดรวมของเกลือคือการโจมตีโต๊ะสายรุ้งโดยไร้ผล ในกรณีนี้พื้นที่เกลือ 16 ตัวอักษร 64 จะเป็น 64 ^ 15 <n <64 ^ 16 ไม่ใช่ showstopper แต่แก้ไขได้ง่าย
Aaron Toponce

4

mkpasswd(1)อาจเป็น front-end crypt(3)แต่ไม่เหมือนการรันchpasswd(1)ซึ่งเป็นส่วนหนึ่งของแพ็คเกจ "shadow-utils" บน CentOS และ "passwd" บน Debian คุณควรเปรียบเทียบแอปเปิ้ลกับแอปเปิ้ลแทน พิจารณาสคริปต์ต่อไปนี้:

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

ผลลัพธ์จาก Debian Sid:

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 ใช่ไหม
บางคนที่มี

1
@someonewithpc เป็นวิธี POSIX สำหรับล้างไฟล์ touch(1)สร้างไฟล์หากไม่มีอยู่ แต่เพียงอัพเดตเวลาประทับที่แก้ไขหากมีอยู่ มันไม่ใช่วิธีที่ถูกต้องในการทำให้ไฟล์ว่างเปล่า : > fileจะรับประกันว่ามีอยู่และว่างเปล่า
Aaron Toponce

@Aaron ใช่คุณถูกต้องอย่างแน่นอน มันไม่ได้เจาะจงเฉพาะการแจกแจงครั้งเดียวเท่านั้น
ilkkachu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.