4 पॉइंट द्वारा GN⁺ 2024-06-24 | 1 टिप्पणियां | WhatsApp पर शेयर करें
  • sudo और doas setuid binaries और privilege escalation पर निर्भर करते हैं, इसलिए यह एक ऐसा प्रयोग है जिसमें local sshd को 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=yes options वाले अलग sshd instance से मिलकर बना है
  • ssh में मौजूदा socket को सीधे पास करने का option नहीं है, इसलिए शुरुआत में ProxyCommand और socat का उपयोग किया गया, बाद में ProxyUseFdpass और एक छोटी Python script से socket file descriptor पास किया गया
  • यह तरीका काम करता है और security handling मुख्य रूप से OpenSSH पर निर्भर करती है, लेकिन रोज़मर्रा के उपयोग के लिए passfd.py को एक छोटे executable में बदलकर पूरे ssh command को wrapper से घेरना ज़्यादा उपयुक्त है

sudo और doas की संरचनात्मक सीमाएँ

  • sudo और doas, commands को root के रूप में चलाने के लिए setuid binaries और privilege escalation पर निर्भर करते हैं
  • इस डिज़ाइन की कुछ सीमाएँ हैं
    • पूरे user session को privilege escalation करने की क्षमता बनाए रखनी पड़ती है
    • restricted user namespace के अंदर पूरे user session को चलाने पर यह काम नहीं करता
    • setuid binaries, system-wide security configuration पर बंधन लगाते हैं
  • s6-sudod एक विकल्प है जो program को privileged server और unprivileged client में बाँटता है

प्रयोग का लक्ष्य

  • local ssh का उपयोग करके sudo जैसी भूमिका निभानी है, लेकिन उस sshd instance को network पर expose नहीं करना है
  • दो मुख्य शर्तें हैं
    • सिर्फ़ अधिकृत उपयोगकर्ता ही root के रूप में commands चला सकें
    • privilege escalation का उपयोग न हो

local root login के लिए sshd configuration

  • सिर्फ़ root authentication के लिए एक dedicated SSH key बनाई जाती है, और उसे सामान्य authorized_keys की जगह /root/.ssh/local_keys में रखा जाता है
  • अलग sshd instance को Unix domain socket पर bind किया जाता है, और unauthorized users socket तक न पहुँच सकें इसके लिए /run/sshd/ permissions सीमित की जाती हैं
  • एक run example में s6-ipcserver के ज़रिए /run/sshd/sshd.sock बनाया जाता है, और sshd को ये options दिए जाते हैं
    • AuthorizedKeysFile=/root/.ssh/local_keys
    • PermitRootLogin=yes
  • /etc/ssh/sshd_config को बदला नहीं जाता
    • क्योंकि network से bind किए गए मौजूदा sshd पर root login की अनुमति नहीं देनी है
    • मौजूदा configuration में PermitRootLogin no बना रहता है

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 पास करने के लिए -i flag है, लेकिन 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 लगभग दोहर जाता है
  • ProxyUseFdpass command को socket file descriptor stdout के ज़रिए ssh को भेजने देता है, और फिर ssh उसी socket से कनेक्ट करता है
  • 2016 के OpenSSH ProxyUseFdpass usage example के आधार पर Python script passfd.py लिखी गई
    • Unix domain socket /run/sshd/sshd.sock से कनेक्ट करना
    • sendmsg और SCM_RIGHTS से file descriptor पास करना
  • इसके बाद 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 करने की प्रक्रिया में कोई बहुत जटिल चरण नहीं हैं, और ipcserver command को system service manager के माध्यम से चलाया जा सकता है
  • passfd.py प्रयोग के लिए बनाया गया एक तेज़-तर्रार hack जैसा है
  • रोज़मर्रा के उपयोग के लिए, यही काम करने वाला एक छोटा executable बनाकर उसे /usr/local/bin में रखना, और पूरे ssh command को भी एक छोटे wrapper में लपेटना अधिक उपयुक्त है

1 टिप्पणियां

 
GN⁺ 2024-06-24
Hacker News की रायें
  • इस तरीके के खिलाफ सबसे बड़ी वजह complexity बढ़ना है। config file पढ़कर exec() call करने वाले एक single suid binary के बजाय, root के रूप में चलने वाला और UNIX socket सुनने वाला एक binary, और उस socket से बात करने वाला एक binary बन जाता है, और दोनों को asymmetric encryption भी संभालनी पड़ती है
    अगर sudo/doas के खिलाफ मुख्य दलील यह है कि “एक suid binary है जिसे सभी user access कर सकते हैं, और अगर उसमें bug हो तो privilege escalation के लिए उसका दुरुपयोग हो सकता है”, तो नीचे जैसा किया जा सकता है
    chgrp wheel /usr/bin/sudo
    chmod o-rwx /usr/bin/sudo
    sudo users को wheel group में डाल दें, तो सिर्फ sudo कर सकने वाले user ही disk से file bytes पढ़ सकते हैं और उसे execute भी कर सकते हैं। UNIX socket को सिर्फ wheel users के लिए 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 भी खुद करने होंगे

    • व्यक्तिगत रूप से मैं etckeeper से /etc में हुए सभी changes track करता हूं। software install/upgrade हो या किसी इंसान का किया change, सब record होता है, और नई release पर upgrade करते समय local changes का patch बनाकर clean install पर apply किया जा सकता है और फिर 3-way merge से conflicts जांचे जा सकते हैं—यह उपयोगी है
      https://etckeeper.branchable.com/
    • sudo users को wheel group में डालकर सिर्फ sudo कर सकने वाले users को file पढ़ने और execute करने देना काफी reasonable है। हैरानी है कि यह हर जगह default setting क्यों नहीं है
    • मेरी अनभिज्ञता माफ करें। wheel group क्या है और क्या करता है, इसका explanation सुनना चाहूंगा। मुझे पता है कि इससे एक जटिल बहस खुल सकती है
    • क्या /usr/bin/sudo को immutable बनाना भी संभव नहीं होगा? इससे package manager द्वारा इसे छेड़ने से रोकने में मदद मिल सकती है
    • specific commands तक root access सीमित नहीं कर सकने वाली बात के लिए ForcedCommand infrastructure मौजूद है
  • क्या यही अभी 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 में चलती है। $TERM pass किया जाता है, लेकिन यह explicit exception है—यानी denylist के बजाय allowlist के करीब
    कई मायनों में run0, sudo की तुलना में ssh के behavior के ज्यादा करीब माना जा सकता है
    https://mastodon.social/@pid_eins/112353324518585654

    • systemd को हर चीज फिर से क्यों बनानी पड़ती है?
  • क्या मैं कुछ 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 सीखीं, और कुछ नया दिखाने वाली बात अच्छी लगी

    • sudo binary suid root है और privileged binary होने के कारण untrusted users के सामने सीधे exposed रहती है। sudo के अंदर कुछ गलत हो जाए तो user का पूरा environment attack surface बनकर exploit हो सकता है
      ssh तरीका suid binary expose नहीं करता और ssh network layer का इस्तेमाल करता है। इसलिए यह network के जरिए ssh access करने से कम सुरक्षित नहीं है, और उसे काफी सुरक्षित माना जाता है
    • sudo के बड़े फायदों में से एक यह है कि सिर्फ sudo bash जैसी चीज चलाने के बजाय individual commands को sudo से चलाकर auditability बढ़ाई जा सकती है
    • root के रूप में ssh login करने से, लेख में मतलब Unix socket सुनने वाले extra SSH server से है। internet पर root login expose करने का आम threat model शायद यहां लागू न हो
    • यह तरीका theoretical configuration mistake या हो भी सकती/न भी हो सकती vulnerabilities की तुलना, नया daemon चलाने से बने नए attack surface से कर रहा है
      उस daemon में भी configuration mistakes या vulnerabilities हो सकती हैं, और यह user-based authorization layers की कई परतों को एक single root level में घटा देता है
      फिर भी शायद इसे ज्यादा सुरक्षित माना जा रहा है। reasonable security perspective से इसे ज्यादा सुरक्षित नहीं कहा जा सकता; यह बस अलग तरीका है
    • linked article के approach को लेकर मैं skeptical हूं, लेकिन “root के रूप में direct remote SSH login खतरनाक है” वाली बात में fear, uncertainty, and doubt के प्रभाव में आने वाला पहलू है
      असल में remote SSH में user के रूप में login करके sudo इस्तेमाल करने की तुलना में सीधे root के रूप में SSH login करना, सख्ती से देखें तो ज्यादा सुरक्षित है
      अगर user@home, root@server में ssh करता है, तो root@server केवल तभी compromised होगा जब user@home compromised हो
      इसके उलट अगर 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 होती हो

    • इसी तरह का config इस्तेमाल करने वाले के तौर पर कहूं तो, मैं अपने main desktop पर ऐसा करता हूं। अगर सबसे बुरा भी हो जाए, तो सबका backup है, system फिर से install कर देता हूं
      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 बहुत मुश्किल हो जाता है
    • Linux console, यानी local display या remote KVM पर दिखने वाला tty, serial port और IPMI SoL के ttyS* devices sudo या su का इस्तेमाल नहीं करते
      ऐसे console getty जैसे program या window manager इस्तेमाल करते हैं, और ये root के रूप में शुरू होने वाले non-suid programs होते हैं
      console login के लिए root password set रखना ही सही है
    • मेरे मामले में मैं setuid/sudo को audit logs की वजह से इस्तेमाल करता हूं। अब मैं multi-user, multi-service boxes बहुत कम चलाता हूं, और जो multi-tenant हैं वे ज्यादातर k8s हैं, इसलिए ssh के बजाय kubectl endpoint इस्तेमाल किया जा सकता है
      अगर 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 करता है
    • अगर bootloader तक access है, तो अब भी systems.unit=emergency.target, init=/bin/bash, rd.break=pre-pivot set कर सकते हैं या 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 करूंगा

    • SSH भी ForceCommand से उनमें से कुछ कर सकता है, लेकिन मैं सहमत हूं कि वह उतना flexible या precise नहीं है
  • यह Systemd के run0 जैसी सोच है: https://news.itsfoss.com/systemd-run0/

    • और run0 कोई अपने हाथ से बनाया temporary workaround नहीं है। इसका audit हुआ है, और शायद खुद बनाए गए solution से बेहतर होगा
  • 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 चाहिए

  • पूरी तरह सहमत। मैं भी कुछ ऐसा ही करता हूं, और पहले 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 से खेलना शुरू किया था, और तब से लगातार इस्तेमाल कर रहा हूं। कोई समस्या बिल्कुल नहीं हुई

    • आपका setup पूरी तरह वही नहीं है, लेकिन bastion host concept जैसा लगता है
  • यह इस समस्या का elegant solution है। users को बच्चों की तरह treat करने की जरूरत नहीं, लेकिन साथ ही sensible defaults से संभावित गलतियों से बचना चाहिए
    root चाहिए तो console से root login कर लें, इसलिए मुझे लगता है कि su भी जरूरी नहीं। यह तरीका console tty पर root के रूप में login करने के जितना करीब हो सकता है

    • root चाहिए तो console से root login करो—इस तरीके में दो समस्याएं हैं
      पहली, sudo के विपरीत सभी users को root password पता होना चाहिए
      दूसरी, अगर सब सीधे root के रूप में login करते हैं, तो असल में कौन login हुआ और उसने क्या किया, इसका audit करने का कोई तरीका नहीं रहता
  • 10 साल पहले मैंने कुछ ऐसा ही करके देखा था। UNIX socket वाला हिस्सा नहीं था; localhost पर ही listen करने वाला एक अलग sshd चलाया था, और SCM_RIGHTS को handle करने की भी जरूरत नहीं पड़ी थी
    नतीजा खास अच्छा या बुरा कुछ नहीं रहा; बस रुचि कम हो गई, इसलिए अगली मशीन पर यह setup नहीं ले गया