सेवा unprivileged user म्हणून कशी चालवावी?
सेवा root म्हणून चालवल्यास एका bug मुळे संपूर्ण server access मिळू शकतो. प्रत्येक सेवेला स्वतंत्र unprivileged account द्या किंवा systemd मध्ये DynamicUser वापरा.
root म्हणून सर्व काही का चालवू नये
root खाते मशीनवर कोणतीही कृती करू शकते: प्रत्येक फाइल वाचू शकते, कोणतीही setting बदलू शकते आणि संपूर्ण system delete करू शकते. एखादी सेवा root म्हणून चालवताना तुम्ही ही सर्व अधिकारक्षमता त्या सेवेला देता. सेवेमध्ये attacker exploit करू शकेल असा bug असल्यास, त्याला फक्त त्या सेवेचा access मिळत नाही; त्याला root access मिळतो आणि root म्हणजे संपूर्ण server. unprivileged user म्हणून सेवा चालवल्याने हानी मर्यादित राहते. मर्यादित account म्हणून चालणाऱ्या सेवेमधील bug मुळे attacker ला त्या account ला उपलब्ध असलेल्या गोष्टींपुरताच access मिळतो. हा access जवळजवळ काहीही नसावा.
यालाच least privilege चे तत्त्व म्हणतात: system च्या प्रत्येक भागाला त्याचे काम करण्यासाठी आवश्यक तेवढाच access द्या आणि त्यापेक्षा अधिक काहीही देऊ नका. compromise झाल्यास होणारी हानी मर्यादित ठेवण्यासाठी ही सर्वात प्रभावी सवय आहे. आधुनिक server वर हे लागू करण्यासाठी जवळजवळ कोणताही अतिरिक्त खर्च येत नाही.
प्रत्येक सेवेसाठी स्वतंत्र खाते
पारंपरिक पद्धतीत प्रत्येक सेवेसाठी स्वतंत्र system user तयार केला जातो. त्या वापरकर्त्याच्या मालकीच्या फक्त संबंधित सेवेच्या फाइल्स असतात आणि त्याला login करता येत नाही. web app साठीचे system account असे दिसू शकते:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin appsvcप्रत्येक flag महत्त्वाचा आहे. --system मुळे हे मानवी login साठीचे खाते नसून service account बनते. --no-create-home मुळे आवश्यक नसलेली home directory तयार केली जात नाही. --shell /usr/sbin/nologin मुळे हल्लेखोराने कोणत्याही प्रकारे या खात्याचा ताबा मिळवला तरी त्याद्वारे shell उघडता येत नाही. हे खाते केवळ process आणि त्याच्या फाइल्सच्या मालकीसाठी असते.
यानंतर त्या वापरकर्त्याला आवश्यक तेवढ्याच फाइल्सची परवानगी द्या:
sudo chown -R appsvc:appsvc /opt/myappआता सेवा तिच्या स्वतःच्या directory मधून फाइल्स वाचू आणि लिहू शकते. डिस्कवरील इतरत्र तिला प्रवेशाची आवश्यकता नसते. तिच्यावर कधी exploit झाल्यास, हल्लेखोर बदलू शकणाऱ्या फाइल्स /opt/myapp पर्यंत मर्यादित राहतात. हे खाते world-readable असलेल्या कोणत्याही फाइल्स वाचू शकते; परंतु उर्वरित system मध्ये बदल करू शकत नाही.
त्या वापरकर्त्याच्या नावाने systemd कडून ते चालवा
खाते तयार झाल्यावर, सेवा त्या खात्याच्या नावाने चालवण्यास systemd ला सांगा. Unit file मध्ये यासाठी एक ओळ पुरेशी आहे:
[Service]
ExecStart=/opt/myapp/bin/server
User=appsvc
Group=appsvcUser=appsvc मुळे process root चे privileges न वापरता त्या खात्याच्या मर्यादित privileges सह सुरू होतो. systemd अंतर्गत application चालवण्याची ही प्रमाणित पद्धत आहे. तुम्ही ज्या प्रत्येक सेवेसाठी unit तयार करता, त्या प्रत्येक सेवेसाठी ही पद्धत वापरणे योग्य आहे. मात्र systemd चुकीच्या process वर लक्ष ठेवत असेल, तर privileges कमी केल्याने समस्या सुटणार नाही. Daemon शांतपणे बंद झाल्यानंतरही unit active दाखवत असेल, तर process ज्या पद्धतीने सुरू होतो त्यासाठी तुम्ही योग्य Type= निवडले आहे का ते तपासा.
DynamicUser वापरून खाते पूर्णपणे वगळा
systemd आणखी एक पाऊल पुढे जाऊन तुमच्यासाठी तात्पुरता user तयार करू शकते. हा user फक्त सेवा चालू असेपर्यंत अस्तित्वात असतो. DynamicUser=yes सेट केल्यास खाते व्यवस्थापित करण्याची गरजच राहत नाही:
[Service]
ExecStart=/opt/myapp/bin/server
DynamicUser=yes
StateDirectory=myappसेवा सुरू होताना systemd वापरात नसलेला user ID नियुक्त करते. सेवा थांबताना तो ID मुक्त करते. सेवेला स्वतःचे खाजगी /tmp देखील मिळते. तसेच तिला filesystem चा बहुतांश भाग read-only स्वरूपात दिसतो. StateDirectory= तिच्यासाठी /var/lib/myapp अंतर्गत writable state directory तयार करून उपलब्ध करून देते. SysV init मध्ये असे काही शक्य नव्हते. तिथे privileges कमी करण्याची जबाबदारी प्रत्येक सेवेच्या start script ने कशी हाताळली यावर अवलंबून असे. हाच फरक distributions ने सुरुवातीला systemd का स्वीकारले यामागील महत्त्वाचा कारणांपैकी एक आहे. स्वतःच्या state directory शिवाय इतर कशाचीही गरज नसलेल्या self-contained सेवेसाठी DynamicUser=yes हा मजबूत isolation मिळवण्याचा सर्वात कमी प्रयत्नांचा मार्ग आहे. कारण हल्लेखोर लक्ष्य करू शकेल असे दीर्घकाळ टिकणारे खाते अस्तित्वातच राहत नाही.
Units स्वतः लिहिणे किचकट असते. तसेच hardening directives योग्यरीत्या सेट करणे हा या प्रक्रियेतील मोठा लाभ आहे. systemd service आणि timer guide मधील generator हे पर्याय तुमच्यासाठी भरून देऊ शकते. त्यामुळे unit पहिल्याच वेळी योग्य तयार होते.
ही रचना इतर उपायांशी कशी जुळते
किमान विशेषाधिकार हा सुरक्षेचा एक स्तर आहे. तो इतर स्तरांची जागा घेत नाही; त्यांच्यासोबत कार्य करतो. default-deny firewall सेवेशी कोण पोहोचू शकते हे नियंत्रित करतो. सेवा unprivileged user म्हणून चालवल्यास ती breached झाल्यावर काय करू शकते हे मर्यादित होते. hardened SSH हल्लेखोरांना सुरुवातीलाच सर्व्हरमध्ये प्रवेश करण्यापासून रोखतो. यापैकी एकही उपाय स्वतंत्रपणे पुरेसा नाही. हे सर्व उपाय एकत्र वापरल्यास एका सेवेतील bug मुळे संपूर्ण सर्व्हरचा ताबा मिळत नाही. Secrets सुरक्षित ठेवणारी सेवा host केल्यावर या स्तरांच्या मर्यादा स्पष्ट होतात. Restricted account मुळे breached process कोणत्या गोष्टींना स्पर्श करू शकते हे मर्यादित होते. मात्र Vaultwarden सारखा self-hosted password manager अजूनही त्याच्या admin token आणि backup file चे संरक्षण कसे करता यावर अवलंबून असतो. User isolation यापैकी कोणत्याही गोष्टीचे संरक्षण करत नाही.
पुढे जाण्यापूर्वी संपूर्ण सर्व्हरसाठी hardening checklist तपासा आणि त्यावर काम करण्यासाठी तुमच्यासाठी तयार केलेली प्रत निर्माण करा:
FAQ
मी सेवा root म्हणून का चालवू नये?
root या account ला मशीनवरील कोणतीही कृती करण्याची परवानगी असते. त्यामुळे root म्हणून चालणाऱ्या सेवेचा गैरफायदा घेतला गेला, तर आक्रमणकर्त्याला केवळ त्या सेवेपुरता नव्हे, तर संपूर्ण सर्व्हरपुरता प्रवेश मिळतो. सेवा मर्यादित, unprivileged account म्हणून चालवल्यास त्या account ला उपलब्ध असलेल्या गोष्टींपुरतेच नुकसान मर्यादित राहते. root चा वापर प्रशासनासाठी राखून ठेवा आणि प्रत्येक दीर्घकाळ चालणारी सेवा restricted user म्हणून चालवा.
लॉग इन करू न शकणारा user कसा तयार करावा?
sudo useradd --system --no-create-home --shell /usr/sbin/nologin NAME चालवा. nologin shell मुळे credentials चोरीला गेले तरी account interactive session उघडू शकत नाही. --system मुळे तो service account म्हणून चिन्हांकित होतो. --no-create-home मुळे त्याला आवश्यक नसलेली home directory तयार केली जात नाही. chown वापरून त्या user ला फक्त त्याच्याच files चे ownership द्या.
systemd DynamicUser म्हणजे काय?
DynamicUser=yes systemd ला सेवा चालू असेपर्यंत अस्तित्वात राहणारा temporary user तयार करण्यास सांगते. त्यामुळे दीर्घकाळ टिकणारे account व्यवस्थापित करण्याची गरज राहत नाही. यामुळे सेवेला private /tmp, बहुतांश read-only filesystem view आणि managed state directory देखील मिळते. Self-contained सेवा तात्पुरत्या, low-privilege identity अंतर्गत चालवण्याचा हा सर्वात कमी प्रयत्नांचा मार्ग आहे.
non-root user म्हणून सेवा चालवल्याने firewall ची गरज संपते का?
नाही. ते वेगवेगळ्या गोष्टींचे संरक्षण करतात. unprivileged user म्हणून सेवा चालवल्याने सेवा breached झाल्यास ती काय करू शकते यावर मर्यादा येते. firewall मुळे सेवेकडे कोणते network traffic पोहोचू शकते यावर मर्यादा येते. hardened SSH सोबत दोन्ही वापरा. त्यामुळे प्रत्येक स्तर इतर स्तरांच्या मर्यादा भरून काढतो.
service user कडे कोणत्या files चे ownership असावे?
सेवेला प्रत्यक्षात आवश्यक असलेल्या files चेच ownership असावे. त्यापेक्षा अधिक files चे नसावे. त्या account ला त्याच्या working directory आणि data चे ownership द्या. इतर सर्व files root च्या ownership खाली ठेवा. Application directory साठी sudo chown -R svc-app:svc-app /opt/svc-app हा चांगला नमुना आहे. त्याच वेळी /etc अंतर्गत configuration root च्या ownership खाली ठेवा आणि ती केवळ सेवेला readable ठेवा. Process चा कधी गैरफायदा घेतला गेला, तरी तो बदलू शकणाऱ्या files फक्त त्याच्या स्वतःच्या data पुरत्याच मर्यादित राहाव्यात. System मधील इतर files बदलता येऊ नयेत, हे उद्दिष्ट आहे.