
Penpot का रिमोट इमेज इम्पोर्ट एक प्रमाणित फ़ाइल संपादक को एक सामान्य मीडिया सुविधा को बैकएंड-उत्पत्ति SSRF में बदलने देता है, क्योंकि हमलावर-नियंत्रित URL बिना गंतव्य फ़िल्टरिंग के रीडायरेक्ट-फ़ॉलो करने वाले सर्वर फ़ेच पथ में पार कर गए।
Penpot की रिमोट इमेज इम्पोर्ट सुविधा ने एक प्रमाणित फ़ाइल संपादक को एक सामान्य मीडिया सुविधा को बैकएंड-उत्पत्ति वाले SSRF में बदलने दिया, क्योंकि हमलावर-नियंत्रित URL बिना गंतव्य फ़िल्टरिंग के एक रीडायरेक्ट-फॉलो करने वाले सर्वर फ़ेच पथ में प्रवेश कर गए।
मुझे यह दोष Penpot की समीक्षा करते समय मिला, जो खुला-स्रोत डिज़ाइन और कोड सहयोग प्लेटफ़ॉर्म है, और मेरे मन में एक बहुत विशिष्ट प्रश्न था:
क्या होता है जब एक सहयोगी डिज़ाइन टूल एक उपयोगकर्ता को बैकएंड को एक दूरस्थ छवि URL देने देता है?
इस मामले में, उस प्रश्न ने एक वास्तविक बग पाया।
Penpot की रिमोट इमेज इम्पोर्ट प्रक्रिया ने उपयोगकर्ता-नियंत्रित URL स्वीकार किया और बैकएंड को सर्वर नेटवर्क संदर्भ से इसे लाने का कारण बनाया, बिना लूपबैक या निजी-नेटवर्क लक्ष्यों के लिए गंतव्य प्रतिबंध लागू किए। साझा HTTP क्लाइंट ने स्वचालित रूप से रीडायरेक्ट का पालन भी किया।
इसने एक सामान्य मीडिया सुविधा को एक प्रमाणित बैकएंड-उत्पत्ति SSRF प्रिमिटिव में बदल दिया और अंततः CVE-2026-45806 बन गया।
Penpot: Penpot GitHub पर
CVE: CVE-2026-45806
CVSS: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N
यह Penpot को प्रभावित करता था। इसकी आधिकारिक साइट और मीडिया किट पर, Penpot स्वयं को +1M बढ़ते उपयोगकर्ता आधार के रूप में प्रस्तुत करता है और कहता है कि हज़ारों संगठन इसका उपयोग करते हैं, जिनमें Blender, Mozilla, Fedora, NTT Data, MIT, Société Générale, Cisco, Fujitsu, Indra, और ByteDance शामिल हैं।
प्रमाणित फ़ाइल संपादक -> हमलावर-नियंत्रित रिमोट इमेज URL -> create-file-media-object-from-url -> बैकएंड download-image फ़ेच रीडायरेक्ट सक्षम के साथ -> अंतिम अनुरोध आंतरिक-केवल इमेज एंडपॉइंट पर पहुँचता है -> बैकएंड-उत्पत्ति SSRF / आंतरिक पहुँच योग्यता
Penpot एक खुला-स्रोत डिज़ाइन और कोड सहयोग प्लेटफ़ॉर्म है।
यह निम्नलिखित चीज़ों को संभालता है:
इसका अर्थ है कि इसका मीडिया आयात पथ एक वास्तविक विश्वास सीमा पर स्थित है।
यहाँ महत्वपूर्ण प्रश्न यह नहीं था कि क्या Penpot रिमोट इमेज आयात का समर्थन करता है।
असली प्रश्न था:
क्या Penpot प्रतिबंधित करता है कि जब कोई उपयोगकर्ता एक रिमोट इमेज आयात करता है तो बैकएंड कहाँ कनेक्ट कर सकता है?
इस मामले में, इसने नहीं किया।
बहुत से लोग रिमोट आयात सुविधाओं को कम आंकते हैं।
यह एक गलती है।
जिस क्षण कोई एप्लिकेशन:
यह एक वास्तविक आउटबाउंड विश्वास सीमा बनाता है।
यही यहाँ समस्या थी।
यह बग इमेज रेंडरिंग में नहीं था। यह फ़ाइल भंडारण में नहीं था। यह किसी फ़ाइल को संपादित करने के लिए सामान्य अनुमति जाँच में नहीं था।
यह एक क्लासिक सर्वर-साइड विश्वास विफलता थी:
एक वास्तविक कमज़ोरी पैदा करने के लिए यह पर्याप्त है।
मैंने Penpot को अंधाधुंध RPC विधियों को फ़ज़ करके या पहले क्रैश देखकर नहीं पहुँचा।
सबसे मजबूत दृष्टिकोण सबसे आशाजनक सुरक्षा सीमा की पहचान करना था।
Penpot के लिए, वह रिमोट मीडिया आयात था।
क्यों?
क्योंकि यह सुविधा इन चीज़ों को जोड़ती है:
यह निरीक्षण करने के लिए सही सीमा थी।
और यह ठीक वहीं था जहाँ बग रहता था।
बग एक छोटी विश्वास श्रृंखला में सिमट जाता है।
फ्रंटएंड में:
(defn upload-media-url
[name file-id url]
(rp/cmd!
:create-file-media-object-from-url
{:name name
:file-id file-id
:url url
:is-local true}))
उपयोगकर्ता-नियंत्रित url सीधे RPC कॉल में भेजा जाता है।
फिर बैकएंड में:
(sv/defmethod ::create-file-media-object-from-url
...
[{:keys [::db/pool] :as cfg} {:keys [::rpc/profile-id file-id] :as params}]
(files/check-edition-permissions! pool profile-id file-id)
...
(let [_ (files/get-minimal-file cfg file-id)
mobj (create-file-media-object-from-url cfg (assoc params :profile-id profile-id))])
और:
(defn- create-file-media-object-from-url
[cfg {:keys [url name] :as params}]
(let [content (media/download-image cfg url)
बैकएंड जाँचता है कि कॉल करने वाला लक्ष्य फ़ाइल को संपादित कर सकता है, फिर हमलावर-नियंत्रित URL को media/download-image में पास करता है।
फ़ेच कार्यान्वयन यहाँ है:
(defn download-image
"Download an image from the provided URI and return the media input object"
[{:keys [::http/client]} uri]
...
(http/req! client
{:method :get :uri uri}
{:response-type :input-stream})
और साझा HTTP क्लाइंट इस प्रकार कॉन्फ़िगर किया गया है:
(http/build-client {:connect-timeout 30000
:follow-redirects :always}))
यह पूरी कमज़ोरी है:
क्योंकि हमलावर को केवल आवश्यकता है:
हमला श्रृंखला सीधी है:
यह पूरा बग है।
महत्वपूर्ण अंतर यह है कि अनुरोध कहाँ होता है।
सवाल यह नहीं है:
"क्या Penpot URL से इमेज आयात कर सकता है?"
असली सवाल है:
"क्या कोई प्रमाणित उपयोगकर्ता Penpot बैकएंड को आंतरिक गंतव्यों से कनेक्ट करने के लिए बना सकता है जिन तक उपयोगकर्ता को एप्लिकेशन के माध्यम से नहीं पहुँचना चाहिए?"
इस मामले में, उत्तर हाँ था।
यह मायने रखता है क्योंकि इसमें वास्तविक अंतर है:
इमेज सत्यापन इस अंतर को नहीं मिटाता।
यह कुछ प्रत्यक्ष डेटा निकासी मामलों को संकीर्ण करता है, लेकिन SSRF की स्थिति या नेटवर्क सीमा उल्लंघन को नहीं हटाता।
मैंने इस मुद्दे को एक नियंत्रित स्थानीय प्रमाण के साथ मान्य किया जो सीधे समीक्षित Penpot कोड पथ से जुड़ा था।
लक्ष्य तीसरे पक्ष के बुनियादी ढांचे को हिट करना नहीं था। लक्ष्य सटीक सुरक्षा गुण साबित करना था:
मैंने एक स्व-निहित Java वैधकर्ता बनाया जो प्रासंगिक व्यवहार को दर्शाता था:
content-type और content-length पर आधारित इमेज स्वीकृति जाँचमैंने दो मामलों को मान्य किया।
वैधकर्ता ने अनुरोध किया:
http://127.0.0.1:7790/internal.png
देखा गया परिणाम:
http://127.0.0.1:7790/internal.pnghttp://127.0.0.1:7790/internal.png200image/pngइसने साबित किया कि इम्पोर्ट-शैली फ़ेच तर्क ने सीधे एक आंतरिक-केवल इमेज एंडपॉइंट को स्वीकार किया।
फिर वैधकर्ता ने अनुरोध किया:
http://localhost:7791/redirect-to-internal
उस एंडपॉइंट ने एक HTTP रीडायरेक्ट लौटाया:
http://127.0.0.1:7790/internal.png
देखा गया परिणाम: