
Secure-by-default demo lab showing how container hardening (distroless images, non-root, read-only filesystem, runtime-injected secrets) can neutralize a critical Next.js/React Server Actions RCE (CVE-2025-55182 “React2Shell”), with side-by-side safe vs unsafe deployments and exploit logs
यह प्रोजेक्ट Next.js एप्लिकेशन (विशेष रूप से सर्वर एक्शन के माध्यम से) में एक गंभीर रिमोट कोड निष्पादन (RCE) भेद्यता प्रदर्शित करता है और दिखाता है कि कैसे इंफ्रास्ट्रक्चर सख्ती हमले को प्रभावी ढंग से बेअसर करती है, भले ही कोड भेद्यता बनी रहे।
यह एक मानक "असुरक्षित" तैनाती की तुलना एक कठोर "सुरक्षित" तैनाती से करता है, जिसमें Distroless इमेज और रीड-ओनली फ़ाइलसिस्टम का उपयोग किया गया है।
सॉफ्टवेयर भेद्यताएं अपरिहार्य हैं। जब कोड विफल होता है, तो आपके इंफ्रास्ट्रक्चर को हमलावर को अपने पैर जमाने से रोकना चाहिए।
Next.js द्वारा उपयोग किए जाने वाले React Server Components (RSC) कार्यान्वयन में एक गंभीर RCE (CVE-2025-55182, उर्फ React2Shell) मौजूद है।
spawnSync जैसा) की अनुमति देता है।curl, wget, ls, cat) का उपयोग करना।
child_process.spawnSync() का उपयोग करता है। यह बाइनरी को सीधे निष्पादित करता है, बिना किसी शेल (/bin/sh) की आवश्यकता के।chmod +x), और चलाता है।निम्नलिखित लॉग दर्शाते हैं कि एप्लिकेशन के दृष्टिकोण से हमले के प्रयास कैसे दिखते हैं। यह विरोधाभास सुरक्षा उपायों की प्रभावशीलता को स्पष्ट रूप से उजागर करता है।
logs/server.safe.log)लॉग बार-बार विफलता (ENOENT) दिखाते हैं।
spawnSync ls, id, curl चलाने का प्रयास करता है। Distroless इमेज में ये बाइनरी बिल्कुल नहीं हैं। यह केवल शेल के गायब होने के बारे में नहीं है; उपकरण स्वयं गायब हैं।[Instrumentation] Logging initialized. Writing to: /app/logs/server.safe.log
⨯ Error: NEXT_REDIRECT
... digest: '`{"step":"1. Write Initial Chunk to /tmp/hello_test","success":true}`'
⨯ Error: NEXT_REDIRECT
... digest: '`{"step":"2. Verify Binary was Written","verification":{...},"success":true}`'
⨯ Error: NEXT_REDIRECT
... digest: '`{"step":"4. Execute Binary","stdout":"","stderr":"","error_obj":{"message":"spawnSync /tmp/hello_test EACCES","code":"EACCES"},"success":true}`'
logs/server.unsafe.log)लॉग सफल कमांड निष्पादन और फ़ाइल सिस्टम हेरफेर की पुष्टि करते हैं।
[Instrumentation] Logging initialized. Writing to: /app/logs/server.unsafe.log
⨯ Error: NEXT_REDIRECT
... digest: '`{"step":"1. Write Initial Chunk to /tmp/hello_test","success":true}`'
⨯ Error: NEXT_REDIRECT
... digest: '`{"step":"4. Execute Binary","stdout":"Hello from Go binary!\\n","stderr":"","error_obj":null,"success":true}`'
⨯ Error: NEXT_REDIRECT
... digest: '`{"command":"id","args":[],"stdout":"uid=0(root) gid=0(root) ...","stderr":"","status":0,"signal":null}`'
⨯ Error: NEXT_REDIRECT
... digest: '`{"command":"cat","args":["/app/.env"],"stdout":"","stderr":"cat: can\'t open \'/app/.env\': No such file or directory\n","status":1,"signal":null}`'
(नोट: असुरक्षित लॉग में, उपरोक्त cat /app/.env विफल होता है क्योंकि फ़ाइल का नाम रूट में .env है, लेकिन पूर्ण लॉग में ls -la निर्देशिका संरचना प्रकट करेगा।)
मानक शेल कमांड चलाने का प्रयास।
id, ls, cat .env चला सकता है और संवेदनशील डेटा तक पहुंच सकता है।spawnSync /bin/sh ENOENT। कमांड को निष्पादित करने के लिए कोई शेल नहीं है।एक कस्टम बाइनरी अपलोड करके "गायब उपकरणों" को बायपास करने का प्रयास।
/tmp/malware पर लिखता है।chmod +x चलाता है।EROFS: read-only file system।क्या हमलावर एक बाइनरी को वेरिएबल में लोड कर सकता है और उसे सीधे मेमोरी से निष्पादित कर सकता है?
global.payload = "...") में संयोजित करें, फिर इसे निष्पादित करें।child_process फ़ंक्शन (spawn, exec) को एक फ़ाइल पथ की आवश्यकता होती है। वे किसी बफर या स्ट्रिंग को सीधे निष्पादित नहीं कर सकते।memfd_create (RAM में एक अनाम फ़ाइल बनाने के लिए एक सिसकॉल) की आवश्यकता होती है।memfd_create को उजागर नहीं करता है। इसे एक्सेस करने के लिए एक C++ ऐडन (जैसे ffi-napi) को node_modules में पूर्व-स्थापित करने की आवश्यकता होगी।gcc, make) नहीं हैं, हमलावर मौके पर इस ऐडन का निर्माण नहीं कर सकता।"Distroless" इमेज में केवल आपका एप्लिकेशन और उसके रनटाइम निर्भरताएं होती हैं। उनमें पैकेज मैनेजर, शेल या मानक UNIX उपकरण नहीं होते हैं।
ls), फ़ाइलें डाउनलोड नहीं कर सकते (curl), या विशेषाधिकार नहीं बढ़ा सकते।अपने कंटेनर रनटाइम को रूट फ़ाइलसिस्टम को केवल-पढ़ने के लिए माउंट करने के लिए कॉन्फ़िगर करें।
docker-compose.yml में:
read_only: true
tmpfs:
- /tmp:noexec # महत्वपूर्ण: स्पष्ट रूप से निष्पादन को ब्लॉक करें!
/tmp में लिख सकता है (लिखना सफल), लेकिन noexec फ़्लैग के कारण निष्पादन EACCES (अनुमति निषेध) के साथ विफल हो जाता है। यह कार्यक्षमता (लिखने योग्य tmp) को सुरक्षा के साथ संतुलित करता है।अपने कंटेनर इमेज में .env फ़ाइल को शिप न करें। यदि कोई हमलावर फ़ाइलें पढ़ सकता है (जैसे, cat .env), तो आपके रहस्य समझौता हो जाते हैं।
environment कुंजी के माध्यम से)।वातावरण प्रारंभ करें:
सुरक्षित और असुरक्षित दोनों एप्लिकेशन एक ही docker-compose.yml फ़ाइल में परिभाषित हैं।
docker compose up --build -d
शोषण चलाएं: आप अंतर देखने के लिए विशिष्ट पोर्ट पर शोषण चला सकते हैं।
असुरक्षित ऐप को लक्षित करना (पोर्ट 3001):
# 1. मानक RCE (LotL) - सफल
python exploit/poc.py http://localhost:3001
# 2. उन्नत हमला (BYOL) - सफल
python exploit/poc_advanced.py http://localhost:3001
सुरक्षित ऐप को लक्षित करना (पोर्ट 3000):
# 1. मानक RCE (LotL) - विफल (ENOENT)
python exploit/poc.py http://localhost:3000
# 2. उन्नत हमला (BYOL) - विफल (EACCES/EROFS)
python exploit/poc_advanced.py http://localhost:3000
सफाई:
docker compose down
| फ़ीचर | ❌ असुरक्षित वातावरण (पोर्ट 3001) | ✅ सुरक्षित वातावरण (पोर्ट 3000) |
|---|
| बेस इमेज | node:20-alpine (इसमें ls, curl, wget आदि हैं) | gcr.io/distroless/nodejs20-debian12 (कोई शेल नहीं, कोई टूल नहीं) |
| फ़ाइलसिस्टम | लिखने योग्य (मानक Docker डिफ़ॉल्ट) | रीड-ओनली (read_only: true) |
| गुप्त जानकारी | डिस्क पर .env फ़ाइल (cat .env से भेद्य) | पर्यावरण चर (रनटाइम पर इंजेक्ट किए गए) |
| उपयोगकर्ता | root (डिफ़ॉल्ट) | गैर-रूट (Distroless द्वारा लागू) |