PHP

2009-12-16 10 views
24

ग्रीटिंग्स, में फ़ाइल पथ को स्वच्छ करें, मैं अपने छोटे प्रोग्राम को सुरक्षित बनाने की उम्मीद कर रहा हूं ताकि संभावित दुर्भावनापूर्ण उपयोगकर्ता सर्वर पर संवेदनशील फ़ाइलों को नहीं देख सकें।PHP

$path = "/home/gsmcms/public_html/central/app/webroot/{$_GET['file']}"; 


    if(file_exists($path)) { 
     echo file_get_contents($path); 
    } else { 
     header('HTTP/1.1 404 Not Found'); 
    } 

मेरे सिर के ऊपर बंद मुझे पता है कि इनपुट जैसे कि '../../../../../../etc/passwd' मुसीबत होगा, लेकिन सोच के रूप में अन्य क्या दुर्भावनापूर्ण इनपुट मुझे उम्मीद करनी चाहिए और उन्हें कैसे रोकें।

+1

बस किसी भी ../ – halfdan

+2

सहमत है कि एक समस्या का समाधान होगा युक्त इनपुट बाहर करते हैं, लेकिन मैं कई अन्य खतरों मैं के लिए बाहर देखने की जरूरत है देखते हैं कि यह सोचते हैं रहा हूँ। मैं उन सभी के लिए एक अच्छा लौह पहना हुआ समाधान ढूंढ रहा हूं – SeanDowney

+3

@ अर्धदान - हमेशा इस तरह की सुरक्षा के लिए एक ब्लैक-लिस्ट दृष्टिकोण से बचने का प्रयास करें, हमेशा कुछ याद आएगा। जैसे बैकस्पेस वर्ण, टैब, न्यूलाइन, नल वर्ण, अन्य यूनिकोड वर्ण, या जानबूझकर टूटा हुआ यूनिकोड वर्ण जो आपके फ़िल्टर को पास करेगा, लेकिन फिर भी PHP फ़ंक्शन को ऐसा करने का कारण बनता है जिसे आप इसे से बचाने की कोशिश कर रहे थे। परीक्षण करें कि आप वास्तव में क्या चाहते हैं: परिणामी पथ एक सुरक्षित स्थान के नीचे है। – Cheekysoft

उत्तर

33

realpath() आपको किसी भी पथ को परिवर्तित करने देगा जो सापेक्ष जानकारी को पूर्ण पथ में रख सकता है ... आप तब सुनिश्चित कर सकते हैं कि पथ एक निश्चित उपनिर्देशिका के तहत है जिसे आप डाउनलोड से अनुमति देना चाहते हैं।

+4

यह मेरा अंतिम समाधान था: $ baseDir = "/ home/gsmcms/public_html/केंद्रीय/ऐप्स/webroot/"; $ पथ = रीयलपाथ ($ baseDir। $ _GET ['file']); // यदि बेसडियर आगे 0 == स्ट्रॉप्स पर नहीं है, तो संभवतः हैकिंग प्रयास (स्ट्रॉप्स ($ पथ, $ बेसडियर)) { \t मरें ('अमान्य पथ'); } elseif (file_exists ($ पथ)) { \t echo file_get_contents ($ पथ); } अन्य { \t शीर्षलेख ('HTTP/1।1 404 नहीं मिला '); \t गूंज "अनुरोधित फ़ाइल नहीं मिली"; } – SeanDowney

+1

@ सियानडाउन आपके समाधान में एक बग है, अर्थात् आपको यह जांचना चाहिए कि स्ट्रॉप्स झूठी या गैर-शून्य नहीं लौटाता है, जो आप नहीं कर रहे हैं। – Michael

+1

realpath() एक अच्छा दोस्त है लेकिन पर्याप्त नहीं है - यदि आप किसी मौजूदा पथ का जिक्र कर रहे हैं तो यह केवल पूर्ण पथ लौटाता है। अन्यथा यह झूठी वापसी होगी; कुछ मामलों में यह किसी भी परेशानी का कारण नहीं बनता है, लेकिन उपनिर्देशिका के ऑटो-निर्माण के साथ "सेव" ऑपरेशन पर विचार करने से, यह गेम को बर्बाद कर सकता है। (उपयोगकर्ता आपको बताता है कि फ़ाइल कहां रखना है, लेकिन रीयलपैथ झूठी रिटर्न के बाद से आप "अमान्य पथ" का जवाब देते हैं।) शायद यह नहीं है कि आप क्या कर रहे हैं; बस उल्लेख करने के लिए सोचा। – dkellner

11

उपयोगकर्ता द्वारा प्रदान किए जाने वाले सभी असुरक्षित पथों की अपेक्षा करने के बजाय basename का उपयोग करें।

+0

यह कुछ स्थितियों में काम कर सकता है, हालांकि मैं इनपुट को शामिल करने के लिए इनपुट की अपेक्षा कर रहा हूं, पूर्व: '/js/jquery/jquery.js' – SeanDowney

6

यदि आप कर सकते हैं, तो श्वेतसूची का उपयोग अनुमत फ़ाइलों की एक सरणी की तरह करें और इसके खिलाफ इनपुट जांचें: यदि उस उपयोगकर्ता में दी गई फ़ाइल उस सूची में मौजूद नहीं है, तो अनुरोध से इनकार करें।

+0

यह सबसे अच्छा विचार होगा, लेकिन शायद मैं जितना अधिक काम करना चाहता हूं :) – SeanDowney

+0

जब तक आप अपने वेबूट के नीचे अपनी सभी फाइलों के स्रोत को रिसाव नहीं करना चाहते हैं, तो शायद आप ऐसा करना चाहते हैं। – Cheekysoft

4

यहां एक अतिरिक्त और महत्वपूर्ण सुरक्षा जोखिम है। यह स्क्रिप्ट किसी भी सर्वर-साइड प्रोसेसिंग के बिना आउटपुट स्ट्रीम में फ़ाइल के स्रोत को इंजेक्ट करेगी। इसका मतलब है कि किसी भी सुलभ फाइलों के आपके सभी स्रोत कोड इंटरनेट पर लीक हो जाएंगे। ओपी द्वारा

+0

अच्छा बिंदु, मैं अनुमत एक्सटेंशन की श्वेतसूची जोड़ूंगा जैसे: जेएस, सीएसएस, जेपीजी, जीआईएफ ... – SeanDowney

7

समाधान:

$baseDir = "/home/gsmcms/public_html/central/app/webroot/"; 
$path = realpath($baseDir . $_GET['file']); 

// if baseDir isn't at the front 0==strpos, most likely hacking attempt 
if(strpos($path, $baseDir) !== 0 || strpos($path, $baseDir) === false) { 
    die('Invalid Path'); 
} elseif(file_exists($path)) { 
    echo file_get_contents($path); 
} else { 
    header('HTTP/1.1 404 Not Found'); 
    echo "The requested file could not be found"; 
} 
+0

कृपया उन्नत एसओ सुविधाओं का उपयोग करना सीखें! :) यह सरल बनाता है * कॉपी-पेस्ट * –

+0

एफवाईआई, मुझे इस समाधान में एक बग मिला, लेकिन फिक्स युक्त मेरा संपादन अस्वीकार कर दिया गया था। – Michael

+0

कृपया उपरोक्त जांचें। यह स्वच्छता उद्देश्य के लिए और अधिक स्पष्ट और उचित होना चाहिए। –

1

भले ही आप realpath उपयोग कर रहे हैं, तो आप अभी भी सभी उपयोग करने से पहले पट्टी चाहिए ".."। अन्यथा एक हमलावर ब्रूट फोर्स के साथ आपके सर्वर को संपूर्ण निर्देशिका संरचना पढ़ सकता है, उदा। "valid_folder /../../ test_if_this_folder_name_exists/valid_folder" - अगर एप्लिकेशन इस पथ को स्वीकार करता है, तो हमलावर जानता है कि फ़ोल्डर मौजूद है।

0

सभी /. /.. या \ को पट्टी करने के लिए। \ .. और सभी आगे स्लैश में कनवर्ट करें क्योंकि विभिन्न वातावरण आगे स्लैश स्वीकार करेंगे। यह पथ इनपुट के लिए एक काफी सुरक्षित फ़िल्टर प्रदान करना चाहिए। अपने कोड में आपको इसे मूल निर्देशिकाओं से तुलना करना चाहिए कि आप केवल मामले में पहुंच नहीं चाहते हैं।

$path = realpath(implode('/', array_map(function($value) {return trim($value, '.');}, explode('/', str_replace('\\', '/', $path))))); 
+0

@ कोबी: आपने मेरा जवाब क्यों संपादित किया? Str_replace सभी आगे slashes रखता है और realpath यह सब एकल स्लैश बनाता है .. मेरे कोड को संपादित नहीं करते हैं –

संबंधित मुद्दे

 संबंधित मुद्दे