2010-03-29 11 views
12

मुझे अभी प्रबंधित करने के लिए एक साइट मिली है, लेकिन पिछले व्यक्ति ने लिखे गए कोड के बारे में भी निश्चित नहीं हूं। मैं नीचे लॉगिन प्रक्रिया चिपका रहा हूं, क्या आप देख सकते हैं और मुझे बता सकते हैं कि क्या कोई सुरक्षा भेद्यता है? पहली नज़र में, ऐसा लगता है कि कोई एसक्यूएल इंजेक्शन या कुकीज़ में हेरफेर कर सकता है और? M = पैरामीटर।क्या इस PHP कोड में कोई सुरक्षा भेद्यता है?


 

define ('CURRENT_TIME', time());// Current time. 
define ('ONLINE_TIME_MIN', (CURRENT_TIME - BOTNET_TIMEOUT));// Minimum time for the status of "Online". 
define ('DEFAULT_LANGUAGE', 'en');// Default language. 
define ('THEME_PATH', 'theme');// folder for the theme. 

// HTTP requests. 
define ('QUERY_SCRIPT', basename ($ _SERVER [ 'PHP_SELF'])); 
define ('QUERY_SCRIPT_HTML', QUERY_SCRIPT); 
define ('QUERY_VAR_MODULE', 'm');// variable contains the current module. 
define ('QUERY_STRING_BLANK', QUERY_SCRIPT. '? m =');// An empty query string. 
define ('QUERY_STRING_BLANK_HTML', QUERY_SCRIPT_HTML. '? m =');// Empty query string in HTML. 
define ('CP_HTTP_ROOT', str_replace ('\ \', '/', (! empty ($ _SERVER [ 'SCRIPT_NAME'])? dirname ($ _SERVER [ 'SCRIPT_NAME']):'/')));// root of CP. 

// The session cookie. 
define ('COOKIE_USER', 'p');// Username in the cookies. 
define ('COOKIE_PASS', 'u');// user password in the cookies. 
define ('COOKIE_LIVETIME', CURRENT_TIME + 2592000)// Lifetime cookies. 
define ('COOKIE_SESSION', 'ref');// variable to store the session. 
define ('SESSION_LIVETIME', CURRENT_TIME + 1300)// Lifetime of the session. 

////////////////////////////////////////////////// ///////////////////////////// 
// Initialize. 
////////////////////////////////////////////////// ///////////////////////////// 

// Connect to the database. 
if (! ConnectToDB()) die (mysql_error_ex()); 

// Connecting topic. 
require_once (THEME_PATH. '/ index.php'); 

// Manage login. 
if (! empty ($ _GET [QUERY_VAR_MODULE])) 
( 
// Login form. 
    if (strcmp ($ _GET [QUERY_VAR_MODULE], 'login') === 0) 
    ( 
    UnlockSessionAndDestroyAllCokies(); 

    if (isset ($ _POST [ 'user']) & & isset ($ _POST [ 'pass'])) 
    ( 
     $ user = $ _POST [ 'user']; 
     $ pass = md5 ($ _POST [ 'pass']); 

    // Check login. 
     if (@ mysql_query ("SELECT id FROM cp_users WHERE name = '". addslashes ($ user). "' AND pass = '". addslashes ($ pass). "' AND flag_enabled = '1 'LIMIT 1") & & @ mysql_affected_rows() == 1) 
     ( 
     if (isset ($ _POST [ 'remember']) & & $ _POST [ 'remember'] == 1) 
     ( 
      setcookie (COOKIE_USER, md5 ($ user), COOKIE_LIVETIME, CP_HTTP_ROOT); 
      setcookie (COOKIE_PASS, $ pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 
     ) 

     LockSession(); 
     $ _SESSION [ 'Name'] = $ user; 
     $ _SESSION [ 'Pass'] = $ pass; 
     // UnlockSession(); 

     header ('Location:'. QUERY_STRING_BLANK. 'home'); 
    ) 
     else ShowLoginForm (true); 
     die(); 
    ) 

    ShowLoginForm (false); 
    die(); 
) 

// Output 
    if (strcmp ($ _GET [ 'm'], 'logout') === 0) 
    ( 
    UnlockSessionAndDestroyAllCokies(); 
    header ('Location:'. QUERY_STRING_BLANK. 'login'); 
    die(); 
) 
) 

////////////////////////////////////////////////// ///////////////////////////// 
// Check the login data. 
////////////////////////////////////////////////// ///////////////////////////// 

$ logined = 0,// flag means, we zalogininy. 

// Log in session. 
LockSession(); 
if (! empty ($ _SESSION [ 'name']) & &! empty ($ _SESSION [ 'pass'])) 
( 
    if (($ r = @ mysql_query ("SELECT * FROM cp_users WHERE name = '". addslashes ($ _SESSION [' name'])."' AND pass = ' ". addslashes ($ _SESSION [' pass']). " 'AND flag_enabled = '1' LIMIT 1 ")))$ logined = @ mysql_affected_rows(); 
) 
// Login through cookies. 
if ($ logined! == 1 & &! empty ($ _COOKIE [COOKIE_USER]) & &! empty ($ _COOKIE [COOKIE_PASS])) 
( 
    if (($ r = @ mysql_query ("SELECT * FROM cp_users WHERE MD5 (name)='". addslashes ($ _COOKIE [COOKIE_USER ])."' AND pass = '". addslashes ($ _COOKIE [COOKIE_PASS]). " 'AND flag_enabled = '1' LIMIT 1 ")))$ logined = @ mysql_affected_rows(); 
) 
// Unable to login. 
if ($ logined! == 1) 
( 
    UnlockSessionAndDestroyAllCokies(); 
    header ('Location:'. QUERY_STRING_BLANK. 'login'); 
    die(); 
) 

// Get the user data. 
$ _USER_DATA = @ Mysql_fetch_assoc ($ r); 
if ($ _USER_DATA === false) die (mysql_error_ex()); 
$ _SESSION [ 'Name'] = $ _USER_DATA [ 'name']; 
$ _SESSION [ 'Pass'] = $ _USER_DATA [ 'pass']; 

// Connecting language. 
if (@ strlen ($ _USER_DATA [ 'language'])! = 2 | |! SafePath ($ _USER_DATA [ 'language']) | |! file_exists ('system/lng .'.$_ USER_DATA [' language '].' . php'))$_ USER_DATA [ 'language'] = DEFAULT_LANGUAGE; 
require_once ('system/lng .'.$_ USER_DATA [' language'].'. php '); 

UnlockSession(); 
+4

इस साइट का पता शामिल करें, और मैं आपको बता दूंगा। :) – MusiGenesis

+0

जोड़ों का उपयोग (एमडी 5 ($ पास)) अनावश्यक है। एसक्यूएल इंजेक्शन इसे md5() नहीं सोच सकता है, यह कभी-कभी * इसे जोड़ों को जोड़ सकता है()। इसके अलावा md5() एकल-कोट्स, डबल-क्यूटो, बैकस्लाश या नल बाइट्स कभी भी उत्पन्न नहीं करेगा, इसलिए addlashes() किसी md5() हैश पर कभी भी कुछ नहीं करेगा। Adodb और parametrized प्रश्नों का उपयोग करने के लिए यह बेहतर है। – rook

उत्तर

17

हाँ, वहाँ इस कोड में कुछ कमजोरियों हैं।

define ('QUERY_SCRIPT', basename ($ _SERVER [ 'PHP_SELF'])); 

PHP_SELF बुरा है क्योंकि एक हमलावर इस चर को नियंत्रित कर सकते हैं:

यह संभवतः एक समस्या हो सकती है। उदाहरण के लिए जब आप इस यूआरएल के साथ स्क्रिप्ट तक पहुंचते हैं तो PHP_SELF प्रिंट करने का प्रयास करें: http://localhost/index.php/test/junk/hacked। जितना संभव हो सके इस चर से बचें, अगर आप इसका इस्तेमाल करते हैं, तो सुनिश्चित करें कि आप इसे स्वच्छ कर दें। इस चर का उपयोग करते समय एक्सएसएस फसल को देखना बहुत आम है।

1 भेद्यता:

setcookie (COOKIE_USER, md5 ($ user), COOKIE_LIVETIME, CP_HTTP_ROOT); 
setcookie (COOKIE_PASS, $ pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 

यह एक नहीं बल्कि गंभीर जोखिम है। यदि किसी हमलावर के पास आपके आवेदन में एसक्यूएल इंजेक्शन था तो वे md5() हैश को तोड़ने के बिना एमडी 5 हैश और उपयोगकर्ता नाम और लॉगिन तुरंत प्राप्त कर सकते थे। ऐसा लगता है कि आप स्पष्ट पाठ में पासवर्ड संग्रहीत कर रहे हैं।

यह सत्र भेद्यता दो गुना है, यह एक "अमर सत्र" भी है, सत्र आईडी हमेशा बड़े यादृच्छिक रूप से जेनरेट किए गए मानों की अवधि समाप्त होनी चाहिए। अगर वे समाप्त नहीं होते हैं तो वे बलपूर्वक बलपूर्वक बहुत आसान होते हैं।

आप चाहिए कभी फिर से आविष्कार पहिया, आपके आवेदन की शुरुआत में session_start() फोन और यह स्वचालित रूप से एक सुरक्षित सत्र id कि समाप्त हो रहा है उत्पन्न होगा। तब

2 भेद्यता ट्रैक रखने के लिए करता है, तो ब्राउज़र वास्तव में प्रवेश होने $_SESSION['user'] की तरह एक सत्र चर का उपयोग:।

$ pass = md5 ($ _POST [ 'pass']); 

md5() क्योंकि टकराव जानबूझकर उत्पन्न हो रही हैं असुरक्षित साबित हो रहा है। md5() कभी पासवर्ड के लिए उपयोग नहीं किया जाना चाहिए। आपको sha2 परिवार के सदस्य का उपयोग करना चाहिए, शा -256 या शा -512 बहुत अच्छे विकल्प हैं।

3 भेद्यता:

CSRF

मैं तुम्हें प्रमाणीकरण तर्क के लिए किसी भी CSRF संरक्षण नहीं दिख रहा। मुझे संदेह है कि आपके आवेदन में सभी अनुरोध सीएसआरएफ के लिए कमजोर हैं।

+1

ओएमजी क्या अफवाहों पर आधारित उत्तर ... ज्ञान नहीं है। –

+2

विशिष्टता कर्नल के साथ अपने बिंदु को मापने के लिए देखभाल? – Neil

+4

@ कोल। वास्तव में Shrapnel? मैं जो कुछ भी देखता हूं वह सख्त तथ्य है जो अनुसंधान के वर्षों से समर्थित है। – rook

0

स्वीकृत उत्तर कुछ चीजों के बारे में बहुत कुछ गलत और गलत है। यहां कोडों में दिखाई देने वाली भेद्यताएं हैं:

define('QUERY_SCRIPT', basename($_SERVER['PHP_SELF'])); 

जैसा कि कहीं और कहा गया है, इसमें केवल स्क्रिप्ट पथ से अधिक हो सकता है। इसके बजाए $_SERVER['SCRIPT_NAME'] या __FILE__ का उपयोग करें।

define('CP_HTTP_ROOT', ... 

यह निरंतर कुकी पथ को स्क्रिप्ट पथ पर सेट करने के लिए उपयोग किया जाता है। यह असुरक्षित नहीं है लेकिन उपयोगकर्ता को प्रत्येक स्क्रिप्ट में अलग से लॉग इन करने की आवश्यकता होगी। इसके बजाय सत्रों का उपयोग करें (नीचे चर्चा की गई) और अपने ऐप के लिए एक बेस पथ सेट करें।

UnlockSessionAndDestroyAllCokies() 

मुझे नहीं पता कि यह वास्तव में क्या कर रहा है, लेकिन यह अच्छा नहीं लगता है। बस प्रत्येक अनुरोध के लिए स्क्रिप्ट में सत्र शुरू करें। सत्र में उपयोगकर्ता जानकारी मौजूदा जानना चाहते हैं कि वे पहले से ही प्रवेश किया हो लिए जाँच करें।

$pass = md5($_POST['pass']); 

पासवर्ड प्रत्येक हैश के साथ एक अद्वितीय नमक होना चाहिए, और अधिमानतः एक बेहतर हैशिंग एल्गोरिथ्म का उपयोग करें। इन दिनों (PHP 5.5+) आपको अपने लिए पासवर्ड हैशिंग विवरण की देखभाल करने के लिए password_hash और password_verify का उपयोग करना चाहिए।

mysql_query("SELECT id FROM cp_users WHERE name = '". addslashes($user)... 

यह एक पुरानी सवाल है, लेकिन आज mysql_ पीएचपी कार्यों अब समर्थित नहीं हैं। mysqli या पीडीओ का प्रयोग करें। असमर्थित लाइब्रेरी का उपयोग करके आप अप्रतिबंधित भेद्यता पर खुलते हैं। addslashes एसक्यूएल इंजेक्शन के खिलाफ एकदम सही सुरक्षा नहीं है। तैयार बयान, या कम से कम लाइब्रेरी के स्ट्रिंग से बचने के कार्यों का उपयोग करें।

if (isset($_POST['remember']) && $_POST['remember'] == 1) 
( 
    setcookie(COOKIE_USER, md5($user), COOKIE_LIVETIME, CP_HTTP_ROOT); 
    setcookie(COOKIE_PASS, $pass, COOKIE_LIVETIME, CP_HTTP_ROOT); 
) 

और यहां सबसे बड़ी समस्या है। कुकीज़ उपयोगकर्ता प्रमाण-पत्र संग्रहित कर रहे हैं। आप एक हैश किए गए उपयोगकर्ता नाम वापस भेज रहे हैं और प्रतिक्रिया के साथ कुकी मान के रूप में पासवर्ड धोया है। इन्हें आसानी से पढ़ा जा सकता है और किसी तीसरे पक्ष द्वारा उपयोग किया जा सकता है। चूंकि यह स्क्रिप्ट एक साधारण हैश का उपयोग करती है, इसलिए इंद्रधनुष तालिका किसी को उपयोगकर्ता के पासवर्ड को देखने देगी। लेकिन चूंकि प्रतिक्रिया में "सुरक्षित" प्रमाण-पत्र शामिल हैं, इसलिए हमलावर को लॉग इन करने के किसी अन्य अनुरोध में उन्हें पास करने के अलावा कुछ भी करने की आवश्यकता नहीं होगी। यह उपयोगकर्ता को "याद रखने" का उचित तरीका नहीं है और यह आवश्यक नहीं है।

अनुरोध के लिए उपयोगकर्ता का कनेक्शन केवल सत्र में ही संभाला जाना चाहिए। यही उनका उद्देश्य है। अनुरोध और प्रतिक्रियाओं में एक यादृच्छिक पहचानकर्ता के साथ एक कुकी होती है। उपयोगकर्ता का विवरण केवल सर्वर पर रहता है और इस पहचानकर्ता से लिंक करता है। (साइड नोट:। वहाँ एक बग है कि इस ब्लॉक ब्रेसिज़ के बजाय कोष्ठकों के साथ लिपटे है है)

$_SESSION['Pass'] = $pass; 

अब उपयोगकर्ता का पासवर्ड दो स्थानों में संग्रहित किया जा रहा है: डेटाबेस और सत्र भंडारण। यदि सत्र डेटाबेस के बाहर संग्रहीत होते हैं (और PHP उन्हें डिफ़ॉल्ट रूप से डिस्क पर संग्रहीत करता है), तो अब आपके पास दो तरीके हैं जो उपयोगकर्ता प्रमाण-पत्र चोरी करने का प्रयास कर सकते हैं।

if ($logined !== 1 && !empty($_COOKIE[COOKIE_USER]) ... 
    if (($r = @mysql_query("SELECT * FROM cp_users WHERE MD5(name)='". addslashes($_COOKIE [COOKIE_USER ])."' AND pass = '". addslashes($_COOKIE [COOKIE_PASS]).. 

एक हमलावर अब बस एक उपयोगकर्ता नाम और पासवर्ड है, जो पिछले एक जवाब में उन्हें सौंप दिया गया था के MD5 हैश के साथ एक अनुरोध में कुकी हेडर पास करके में प्रवेश करने का प्रयास कर सकते हैं। लॉगिन फॉर्म उपयोगकर्ता प्रमाण-पत्र लेने और उन्हें लॉग इन करने वाला एकमात्र स्थान होना चाहिए। इस फ़ॉर्म (और अन्य सभी) को सीएसआरएफ टोकन का उपयोग करना चाहिए।

UnlockSession(); 

फिर मुझे नहीं पता कि यह क्या कर रहा है, लेकिन स्क्रिप्ट के अंत में सत्र को केवल भंडारण में लिखा जाना चाहिए।

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