`sudo` के विकल्प के रूप में SSH
(whynothugo.nl)sudoऔरdoassetuid binaries और privilege escalation पर निर्भर करते हैं, इसलिए यह एक ऐसा प्रयोग है जिसमें localsshdको Unix domain socket से बाँधकर root commands चलाने की ज़िम्मेदारी दी जाती है- लक्ष्य यह है कि सिर्फ़ अधिकृत उपयोगकर्ता ही root commands चला सकें, और साथ ही पूरे user session में privilege escalation की क्षमता न बनी रहे
- इसका implementation एक root-only SSH key file, access-restricted
/run/sshd/sshd.sock,AuthorizedKeysFile, औरPermitRootLogin=yesoptions वाले अलगsshdinstance से मिलकर बना है sshमें मौजूदा socket को सीधे पास करने का option नहीं है, इसलिए शुरुआत मेंProxyCommandऔरsocatका उपयोग किया गया, बाद में ProxyUseFdpass और एक छोटी Python script से socket file descriptor पास किया गया- यह तरीका काम करता है और security handling मुख्य रूप से OpenSSH पर निर्भर करती है, लेकिन रोज़मर्रा के उपयोग के लिए
passfd.pyको एक छोटे executable में बदलकर पूरेsshcommand को wrapper से घेरना ज़्यादा उपयुक्त है
sudo और doas की संरचनात्मक सीमाएँ
sudoऔरdoas, commands को root के रूप में चलाने के लिएsetuidbinaries और privilege escalation पर निर्भर करते हैं- इस डिज़ाइन की कुछ सीमाएँ हैं
- पूरे user session को privilege escalation करने की क्षमता बनाए रखनी पड़ती है
- restricted user namespace के अंदर पूरे user session को चलाने पर यह काम नहीं करता
setuidbinaries, system-wide security configuration पर बंधन लगाते हैं
s6-sudodएक विकल्प है जो program को privileged server और unprivileged client में बाँटता है
प्रयोग का लक्ष्य
- local
sshका उपयोग करकेsudoजैसी भूमिका निभानी है, लेकिन उसsshdinstance को network पर expose नहीं करना है - दो मुख्य शर्तें हैं
- सिर्फ़ अधिकृत उपयोगकर्ता ही root के रूप में commands चला सकें
- privilege escalation का उपयोग न हो
local root login के लिए sshd configuration
- सिर्फ़ root authentication के लिए एक dedicated SSH key बनाई जाती है, और उसे सामान्य
authorized_keysकी जगह/root/.ssh/local_keysमें रखा जाता है - अलग
sshdinstance को Unix domain socket पर bind किया जाता है, और unauthorized users socket तक न पहुँच सकें इसके लिए/run/sshd/permissions सीमित की जाती हैं - एक run example में
s6-ipcserverके ज़रिए/run/sshd/sshd.sockबनाया जाता है, औरsshdको ये options दिए जाते हैंAuthorizedKeysFile=/root/.ssh/local_keysPermitRootLogin=yes
/etc/ssh/sshd_configको बदला नहीं जाता- क्योंकि network से bind किए गए मौजूदा
sshdपर root login की अनुमति नहीं देनी है - मौजूदा configuration में
PermitRootLogin noबना रहता है
- क्योंकि network से bind किए गए मौजूदा
root account lock और password login handling
- root account इस तरह lock था कि किसी भी तरीके से login न किया जा सके, और यह password hash के आगे
!जोड़कर किया गया था sshdइस!prefix को account lock के रूप में समझता है और root login की अनुमति नहीं देता/etc/passwdमें root password value बदलकर!को*से बदला जाता हैsshd,*को किसी विशेष lock value के रूप में नहीं समझता*किसी भी password hash से match नहीं करता, इसलिए password login व्यवहारिक रूप से निष्क्रिय ही रहता है
- अलग से
sshd_configमेंPasswordAuthentication noसेट है, औरsshdमें password-based authentication बंद रखना अधिक सुरक्षित है
ssh से Unix socket पर कनेक्ट करना
sshdमें मौजूदा socket पास करने के लिए-iflag है, लेकिनsshमें उसी काम के लिए कोई समान flag नहीं है- शुरुआत में
ProxyCommandके साथsocatका उपयोग करके/run/sshd/sshd.sockसे कनेक्ट किया गया - connection command में ये तत्व शामिल थे
ProxyCommand='socat STDIO UNIX-CONNECT:/run/sshd/sshd.sock'- dedicated root key को
-i .ssh/root-key.pubसे निर्दिष्ट करना root@rootसे कनेक्ट करना- वर्तमान directory में जाने के बाद login shell चलाना
- इस्तेमाल की गई SSH key एक hardware-bound key थी, इसलिए connection approval के लिए physical device को tap करना पड़ता था
- ऐसा
ssh-agentभी एक विकल्प हो सकता है जो सिर्फ़ explicit approval के बाद key public करे, जैसेhissh-agent
socat overhead और ProxyUseFdpass
socat,sshका सारा input पढ़ने के बाद उसे socket में लिखता है, इसलिए connection overhead लगभग दोहर जाता हैProxyUseFdpasscommand को socket file descriptorstdoutके ज़रिएsshको भेजने देता है, और फिरsshउसी socket से कनेक्ट करता है- 2016 के OpenSSH ProxyUseFdpass usage example के आधार पर Python script
passfd.pyलिखी गई- Unix domain socket
/run/sshd/sshd.sockसे कनेक्ट करना sendmsgऔरSCM_RIGHTSसे file descriptor पास करना
- Unix domain socket
- इसके बाद connection command में
ProxyCommandमेंpassfd.pyदिया गया औरProxyUseFdpass=yesजोड़ा गया nc -FU /run/sshd/sshd.sockभी संभव लगता है, लेकिन manual साफ़ कहता है कि-Fको-Uके साथ उपयोग नहीं किया जा सकता
निष्कर्ष और व्यावहारिक उपयोग का रूप
- यह तकनीक काम करती है, और संवेदनशील security handling मुख्य रूप से OpenSSH पर छोड़ी जाती है
- OpenSSH का रिकॉर्ड अच्छा है, और इसमें hardware-based SSH keys सहित कई authentication methods इस्तेमाल किए जा सकते हैं
- नए host पर इसे configure करने की प्रक्रिया में कोई बहुत जटिल चरण नहीं हैं, और
ipcservercommand को system service manager के माध्यम से चलाया जा सकता है passfd.pyप्रयोग के लिए बनाया गया एक तेज़-तर्रार hack जैसा है- रोज़मर्रा के उपयोग के लिए, यही काम करने वाला एक छोटा executable बनाकर उसे
/usr/local/binमें रखना, और पूरेsshcommand को भी एक छोटे wrapper में लपेटना अधिक उपयुक्त है
1 टिप्पणियां
Hacker News की रायें
इस तरीके के खिलाफ सबसे बड़ी वजह complexity बढ़ना है। config file पढ़कर
exec()call करने वाले एक singlesuidbinary के बजाय, root के रूप में चलने वाला और UNIX socket सुनने वाला एक binary, और उस socket से बात करने वाला एक binary बन जाता है, और दोनों को asymmetric encryption भी संभालनी पड़ती हैअगर sudo/doas के खिलाफ मुख्य दलील यह है कि “एक
suidbinary है जिसे सभी user access कर सकते हैं, और अगर उसमें bug हो तो privilege escalation के लिए उसका दुरुपयोग हो सकता है”, तो नीचे जैसा किया जा सकता हैchgrp wheel /usr/bin/sudochmod o-rwx /usr/bin/sudosudo users को
wheelgroup में डाल दें, तो सिर्फ sudo कर सकने वाले user ही disk से file bytes पढ़ सकते हैं और उसे execute भी कर सकते हैं। UNIX socket को सिर्फwheelusers के लिए accessible बनाने वाले sshd तरीके से access control के लिहाज से सुरक्षा लगभग समान है, लेकिन complexity बहुत कम हैइसके अलावा sshd तरीका sudo की तरह root access को कुछ specific commands तक सीमित नहीं कर सकता, इसलिए sudo की command restrictions को bypass करने वाला bug हो भी, तो भी वह sshd तरीके से ज्यादा permissions नहीं देता
अगर चिंता है कि package manager
/usr/bin/sudoकी permissions बिगाड़ देगा, तो cron से समय-समय पर उन्हें ठीक करवा सकते हैं, या sudo को पूरी तरह हटाकर source से किसी दूसरी जगह manually install कर सकते हैं। बेशक, फिर maintenance और upgrades भी खुद करने होंगे/etcमें हुए सभी changes track करता हूं। software install/upgrade हो या किसी इंसान का किया change, सब record होता है, और नई release पर upgrade करते समय local changes का patch बनाकर clean install पर apply किया जा सकता है और फिर 3-way merge से conflicts जांचे जा सकते हैं—यह उपयोगी हैhttps://etckeeper.branchable.com/
wheelgroup में डालकर सिर्फ sudo कर सकने वाले users को file पढ़ने और execute करने देना काफी reasonable है। हैरानी है कि यह हर जगह default setting क्यों नहीं है/usr/bin/sudoको immutable बनाना भी संभव नहीं होगा? इससे package manager द्वारा इसे छेड़ने से रोकने में मदद मिल सकती हैक्या यही अभी systemd run0 नहीं करता? systemd में
run0नाम का नया tool है, लेकिन असल में यह पूरी तरह नया tool होने के बजाय पुरानेsystemd-runकोrun0नाम के symbolic link से call करने पर sudo replacement की तरह behave करने का तरीका हैमुख्य अंतर यह है कि यह वास्तव में
SUIDनहीं है। यह service manager से target user के UID में command या shell चलाने का request करता है, नया PTY allocate करता है, और फिर original TTY और इस PTY के बीच data forward करता हैदूसरे शब्दों में, target command client का context inherit नहीं करती, बल्कि PID 1 से newly fork हुए isolated execution context में चलती है।
$TERMpass किया जाता है, लेकिन यह explicit exception है—यानी denylist के बजाय allowlist के करीबकई मायनों में
run0,sudoकी तुलना मेंsshके behavior के ज्यादा करीब माना जा सकता हैhttps://mastodon.social/@pid_eins/112353324518585654
क्या मैं कुछ miss कर रहा हूं? root के रूप में ssh login करना sudo इस्तेमाल करने से कैसे ज्यादा सुरक्षित है, यह समझ नहीं आ रहा। हमेशा यही सिखाया गया कि इसे allow मत करो, इसलिए सच में यह कितना risky है, यह भी ठीक से नहीं जानता
यहां लगता है कि remote users को रोकने के लिए कुछ सोच-विचार किया गया है, इसलिए मैं उस security aspect की बात नहीं कर रहा
शायद इसका संबंध sudo की limitation नंबर 3 से हो, लेकिन कम से कम नंबर 1 से तुलना करने पर कोई फायदा नहीं दिखता
समझता हूं कि यह एक experiment है, लेकिन sudo से कम vulnerable नहीं बल्कि ज्यादा vulnerable लगता है। open socket proxy man-in-the-middle attack के प्रति vulnerable दिखता है
फिर भी पुराने tools से की जा सकने वाली कुछ techniques सीखीं, और कुछ नया दिखाने वाली बात अच्छी लगी
sudobinary suid root है और privileged binary होने के कारण untrusted users के सामने सीधे exposed रहती है। sudo के अंदर कुछ गलत हो जाए तो user का पूरा environment attack surface बनकर exploit हो सकता हैssh तरीका
suidbinary expose नहीं करता और ssh network layer का इस्तेमाल करता है। इसलिए यह network के जरिए ssh access करने से कम सुरक्षित नहीं है, और उसे काफी सुरक्षित माना जाता हैsudo bashजैसी चीज चलाने के बजाय individual commands को sudo से चलाकर auditability बढ़ाई जा सकती हैउस daemon में भी configuration mistakes या vulnerabilities हो सकती हैं, और यह user-based authorization layers की कई परतों को एक single root level में घटा देता है
फिर भी शायद इसे ज्यादा सुरक्षित माना जा रहा है। reasonable security perspective से इसे ज्यादा सुरक्षित नहीं कहा जा सकता; यह बस अलग तरीका है
असल में remote SSH में user के रूप में login करके
sudoइस्तेमाल करने की तुलना में सीधे root के रूप में SSH login करना, सख्ती से देखें तो ज्यादा सुरक्षित हैअगर
user@home,root@serverमें ssh करता है, तोroot@serverकेवल तभी compromised होगा जबuser@homecompromised होइसके उलट अगर
user@home,user@serverमें ssh करता है और फिर sudo सेroot@serverबनता है, तोuser@homeयाuser@serverमें से कोई एक भी compromised हो तो root compromised हो जाता है। खासकरuser@serverपर daemon या cron jobs जैसे दूसरे software आमतौर पर चलते रहते हैंऐसे रास्ते से infection में सफल हुए व्यक्ति को मुफ्त root privilege escalation, और password reuse के कारण अक्सर होने वाली lateral movement भी नहीं देनी चाहिए
बेशक, अगर sudo को allowlist commands-only mode में इस्तेमाल किया जा रहा हो, और वह password या remote host से पूरी तरह accessible credentials नहीं लेता हो, तो यह लागू नहीं होता
अगर boot के समय ssh शुरू न हो तो क्या होगा? मुझे याद है कि आम config में यह network पर निर्भर होकर शुरू होता है। तब failsafe console से भी login नहीं कर पाएंगे
sudo या su की तुलना में असल में क्या हासिल होता है, समझ नहीं आता। setuid binary से बचने के बजाय, root privileges के साथ एक network service चला रहे होते हैं, भले ही वह सिर्फ socket से connect होती हो
SSD मर जाए तो क्या? तब भी failsafe console में login नहीं कर पाएंगे
30 साल Linux इस्तेमाल करते हुए hard disk के मरने की घटनाएं, sshd daemon के start न होने से कहीं ज्यादा हुई हैं; ratio के हिसाब से तो यह zero से divide करने जैसा है
अगर operating system का sshd daemon यूं ही कभी-कभी start नहीं होता, तो मैं इसे अधिक stable operating system पर जाने का संकेत मानूंगा
sudo या su की तुलना में फायदा यह है कि local privilege escalation exploit बहुत मुश्किल हो जाता है
ttyS*devices sudo या su का इस्तेमाल नहीं करतेऐसे console
gettyजैसे program या window manager इस्तेमाल करते हैं, और ये root के रूप में शुरू होने वाले non-suid programs होते हैंconsole login के लिए root password set रखना ही सही है
kubectlendpoint इस्तेमाल किया जा सकता हैअगर login कर सकते हैं, तो root में setuid कर सकें ऐसा रखा है। अगर k8s box है, तो वह platform infra team का मामला है, और उसके ऊपर service access k8s permissions provider के जरिए होता है
platform infra team के नजरिए से अगर सिर्फ metrics और logs चाहिए, तो वे पहले से box के बाहर हैं, और अगर कोई task या workflow trigger करना हो तो pipeline इस्तेमाल कर सकते हैं
फिर भी अगर कोई login करके root task करता है, तो मैं audit log छोड़ना चाहूंगा
मेरे पास जिन boxes पर किसी को login permission है, उनमें ऐसा कोई case याद नहीं आता जहां उसके पास पूरा root access न हो
बेशक services के setuid करने की बात समझ आती है, लेकिन service के मामले में आम तौर पर systemd privileges बढ़ाने के लिए नहीं, घटाने के लिए setuid करता है
systems.unit=emergency.target,init=/bin/bash,rd.break=pre-pivotset कर सकते हैं या live CD environment से boot कर सकते हैं। आम emergency recovery options सभी काम करते हैंकम गंभीर emergency हो तो, इस sshd instance को network से बंधा होना चाहिए, इसकी वजह भी नहीं दिखती
इस approach के सभी downsides शामिल नहीं किए गए, यह थोड़ा अफसोसजनक है। sudo यह control कर सकता है कि कौन सा group कौन सा command चला सकता है, उस command को कौन से arguments मिल सकते हैं, subshell creation allow करना है या नहीं, आदि
यह तरीका ऐसे बहुत सारे fine-grained control खो देता है, और sudoers file edit करने की तुलना में manage करने में कठिन trusted keys पर निर्भर करता है
sudo की चौंकाने वाली capabilities देखने के लिए Sudo Mastery किताब सच में recommend करूंगा
यह Systemd के run0 जैसी सोच है: https://news.itsfoss.com/systemd-run0/
ssh की समस्याओं में से एक यह है कि process creation protocol का हिस्सा नहीं है। और यह remote protocol है, इसलिए local resources को child process तक नहीं भेज सकता
इसलिए null-separated argument array पास करना, extra file descriptors पास करना, या executable specify करना संभव नहीं है
इसके बजाय server पर configured shell को एक string दी जाती है। फिर shell escaping की जरूरत पड़ती है, और यह भी जानना पड़ता है कि server side पर कौन सा shell चल रहा है
SSH को सही sudo replacement की तरह इस्तेमाल करना हो तो extension के रूप में
posix_spawnके करीब की functionality चाहिएhttps://bugzilla.mindrot.org/show_bug.cgi?id=2283
पूरी तरह सहमत। मैं भी कुछ ऐसा ही करता हूं, और पहले HN comment में भी समझा चुका हूं
मेरा तरीका थोड़ा अलग है। physical SSH console के लिए एक dedicated machine इस्तेमाल करता हूं, और यह machine घर की दूसरी machines से अलग private LAN पर है। managed switch नहीं, सामान्य switch है; Ethernet cable इस्तेमाल होती है और trunk नहीं है
login सिर्फ SSH से संभव है, और इसमें Yubikey जोड़ी हुई है
desktop PC का अपना firewall है, और यह इस SSH console के IP/MAC address से आने वाले SSH traffic को ही allow करता है। यह सिर्फ उस private LAN पर है जो ये दोनों share करते हैं; दूसरे physical LAN पर desktop internet access कर सकता है
sshd daemon सिर्फ public/private key login allow करता है और password login block है
root चाहिए तो “SSH console” boot करता हूं। लगभग खाली machine है, इसलिए बहुत जल्दी on हो जाती है। login करता हूं, up arrow से
ssh root@...वाली line फिर बुलाता हूं, Enter दबाता हूं और Yubikey press करता हूंवह SSH console और keyboard desk पर, हमेशा हाथ की पहुंच में रहते हैं
private LAN, वह भी दूसरे private LAN से physically अलग जगह पर मौजूद iptables/nftables + sshd, sudo binary या su से ज्यादा safe है या कम safe, यह हर कोई खुद तय करे
“क्यों” पूछें तो मेरा जवाब होगा “क्योंकि कर सकता हूं।” इतना पहले set किया था कि कब किया याद भी नहीं। शायद लगभग 2 साल पहले इस idea से खेलना शुरू किया था, और तब से लगातार इस्तेमाल कर रहा हूं। कोई समस्या बिल्कुल नहीं हुई
यह इस समस्या का elegant solution है। users को बच्चों की तरह treat करने की जरूरत नहीं, लेकिन साथ ही sensible defaults से संभावित गलतियों से बचना चाहिए
root चाहिए तो console से root login कर लें, इसलिए मुझे लगता है कि
suभी जरूरी नहीं। यह तरीका console tty पर root के रूप में login करने के जितना करीब हो सकता हैपहली, sudo के विपरीत सभी users को root password पता होना चाहिए
दूसरी, अगर सब सीधे root के रूप में login करते हैं, तो असल में कौन login हुआ और उसने क्या किया, इसका audit करने का कोई तरीका नहीं रहता
10 साल पहले मैंने कुछ ऐसा ही करके देखा था। UNIX socket वाला हिस्सा नहीं था; localhost पर ही listen करने वाला एक अलग sshd चलाया था, और
SCM_RIGHTSको handle करने की भी जरूरत नहीं पड़ी थीनतीजा खास अच्छा या बुरा कुछ नहीं रहा; बस रुचि कम हो गई, इसलिए अगली मशीन पर यह setup नहीं ले गया