2012-12-09 10 views
11

मुझे आश्चर्य है कि यह टोकन सेट करने का एक सुरक्षित तरीका है, जब तक वास्तव में कोई टोकन उत्पन्न नहीं होता है, मैं एक उत्पन्न करता हूं, और इसे पूरे एप्लिकेशन और उन रूपों में उपयोग करता हूं। प्रति सत्र एक टोकन?क्या यह टोकन सीएसआरएफ सेट करने का एक सुरक्षित तरीका है?

if (!isset($_SESSION['token'])) { 
    $data['token'] = uniqid(rand(), true); 
    session_regenerate_id(); 
    $_SESSION['token'] = $data['token']; 
} 

क्या सबमिट किए गए फॉर्म पर टोकन को साफ़ करना आवश्यक होगा? या बस इसके साथ रहें, भले ही मैंने एक फॉर्म जमा किया हो?

+2

संभावित डुप्लिकेट: [सीएसआरएफ सुरक्षा: क्या हमें हर रूप के लिए टोकन उत्पन्न करना है?] (Http://stackoverflow.com/q/8655817/53114) – Gumbo

+1

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

उत्तर

11

यदि आप इन लिंक को नहीं जानते हैं, this आपको कुछ परिदृश्यों को समझने में मदद कर सकता है और विशेष रूप से this आपको डीओएस और डोंट बताएगा। आशा करता हूँ की ये काम करेगा।

+0

बस उस सामग्री को जोड़ने के लिए +1। यहां तक ​​कि मैं आम तौर पर केवल उत्तर को लिंक से नापसंद करता हूं, यह विकी के लिए है जहां एक से अधिक व्यक्ति इस विषय की परवाह करते हैं। – hakre

10

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

<?php 
$token = uniqid(rand(), true); 
$_SESSION['csrf_tokens'][$token] = true; 

एचटीएमएल

<form> 
    <input type="hidden" name="token" value="<?php echo $token ?>" /> 
</form> 

फ़ॉर्म सत्यापन पर::

if (isset($_SESSION['csrf_tokens'][$token]) && $_SESSION['csrf_tokens'][$token] === true) { 
    unset($_SESSION['csrf_tokens'][$token]); 
    // additional code here 
} 

मेरी अनुप्रयोगों में मैं प्रत्येक प्रपत्र इस तरह प्रदर्शन के लिए एक टोकन जेनरेट

+0

इससे कैसे प्रभावित होगा, अगर मैं अलग-अलग टैब खोलता हूं? आइए मान लें कि मैं प्रत्येक अनुरोध के लिए एक टोकन उत्पन्न करता हूं, जो समस्याएं पैदा करेगा यदि लोग मेरी साइट पर कई टैब खोलते हैं – user1831020

+0

उदाहरण के साथ मेरा उत्तर अपडेट किया गया –

+0

प्रति टोकन एक टोकन का लाभ यह है कि यह स्वचालित रूप से डुप्लिकेट फ़ॉर्म सबमिशन को रोकता है ... – Laurence

2

per-session token का उपयोग करने के बजाय मैं अतिरिक्त सुरक्षा के लिए per-form/url token पसंद करूंगा, कुछ लोग तर्क दे सकते हैं कि per-request token सबसे सुरक्षित है लेकिन उपयोगिता को प्रभावित करता है।

मुझे लगता है कि आपके सत्र स्टोरेज को अपने टोकन स्टोरेज से अलग करना बेहतर है और Memcache जैसे कुछ का उपयोग करना बेहतर है। जब आप गति की जरूरत है कई आवेदन सर्वर आदि एक विशिष्ट उदाहरण

एचटीएमएल

का उपयोग कर मैं भी इसे पसंद करते क्योंकि मैं पूरे session

यहाँ को प्रभावित किए बिना एक कस्टम expiration to the token जोड़ सकते हैं है, तो यह बेहतर है

<form method="POST" action="#"> 
    IP:<input type="text" name="IP" /> <input type="hidden" name="token" 
     value="<?php echo Token::_instance()->generate(); ?>" /> <input 
     type="Submit" value="Login" /> 
</form> 

प्रसंस्करण

$id = "id44499900"; 
Token::_instance()->initialise($id); // initialise with session ID , user ID or IP 

try { 

    Token::_instance()->authenticate(); 
    // Process your form 
} catch (TokenException $e) { 
    http_response_code(401); // send HTTP Error 401 Unauthorized 
    die(sprintf("<h1>%s</h1><i>Thief Thief Thief</i>", $e->getMessage())); 
} 

कक्षा में प्रयुक्त

class Token { 
    private $db; 
    private $id; 
    private static $_instance; 

    function __construct() { 
     $this->db = new Memcache(); 
     $this->db->connect("localhost"); 
    } 

    public static function _instance() { 
     self::$_instance === null and self::$_instance = new Token(); 
     return self::$_instance; 
    } 

    public function initialise($id) { 
     $this->id = $id; 
    } 

    public function authenticate(array $source = null, $key = "token") { 
     $source = $source !== null ? $source : $_POST; 

     if (empty($this->id)) { 
      throw new TokenException("Token not Initialised"); 
     } 

     if (! empty($source)) { 
      if (! isset($source[$key])) 
       throw new TokenException("Missing Token"); 
      if (! $this->get($this->id . $source[$key])) { 
       throw new TokenException("Invalid Token"); 
      } 
     } 
    } 

    public function get($key) { 
     return $this->db->get($key); 
    } 

    public function remove($key) { 
     return $this->db->delete($key); 
    } 

    public function generate($time = 120) { 
     $key = hash("sha512", mt_rand(0, mt_getrandmax())); 
     $this->db->set($this->id . $key, 1, 0, $time); 
     return $key; 
    } 
} 
class TokenException extends InvalidArgumentException { 
} 

नोट: ध्यान दें कि उदाहरण प्रभावित कर सकता है "वापस" बटन या ताज़ा क्योंकि टोकन स्वचालित रूप से 120 सेकंड के बाद हटा दिया जाएगा और इस

+0

-1 आपका दृष्टिकोण अभी भी कमजोर है। आपके पास आईपी या मूल उपयोगकर्ता के सत्र में "बाध्यकारी" नहीं है। अटैकर रीयलटाइम पर अपना टोकन प्राप्त कर सकता है और हमले के लिए इसका इस्तेमाल कर सकता है। इसके अलावा आप हैशिंग एक संख्या के साथ टोकन उत्पन्न करते हैं - जो क्रूर-फोर्कबल हो सकता है। – Zaffy

+1

मैं ज़फ़ी से सहमत नहीं हूं। आईपी ​​के लिए बाध्यकारी सत्र इन दिनों उपयोगकर्ता के अनुकूल तरीके नहीं हैं जहां बहुत से उपयोगकर्ता बदलते ips के साथ मोबाइल डिवाइस का उपयोग करते हैं। साथ ही, अगर कोई किसी की कुकीज़ या नेटवर्क स्ट्रीम को पढ़ने में सक्षम है, तो आपके पास इससे भी बदतर समस्याएं हैं। –

+0

@DanielM मैंने आईपी 'या 'सत्र पर बाध्यकारी लिखा है, लेकिन उन्होंने कभी भी आईपी या सत्र के साथ विशिष्ट उपयोगकर्ता को टोकन असाइन नहीं किया है और इसलिए हमलावर को आपकी कुकीज़ को जानने की आवश्यकता नहीं है क्योंकि वह सिर्फ अपने टोकन का उपयोग आपके रूप में कर सकता है। – Zaffy

2

मैं कर रहा हूँ उपयोगकर्ता के अनुकूल क्षमता प्रभावित हो सकती है यह सोचकर कि यह टोकन

सेट करने का एक सुरक्षित तरीका है, यह इस बात पर निर्भर करता है कि आपके वेब ऐप को कितना सुरक्षित होना चाहिए।

uniqid(rand(), true); 

यह एक हमलावर/जानवर बल का निर्धारण इस के लिए संभव हो सकता है अगर टोकन पीढ़ी के समय ज्ञात है: यह पंक्ति को क्रिप्टोग्राफी सुरक्षित (uniqid() और रैंड() के लिए PHP डॉक्स में चेतावनी दी के रूप में) नहीं है/निर्धारित और रैंड() बीज ज्ञात/निर्धारित है। हालांकि, आपके उद्देश्यों के लिए यह ठीक हो सकता है क्योंकि यह अभी भी सीएसआरएफ हमलों को रोक देगा जहां हमलावर को टोकन मूल्य का कोई ज्ञान नहीं है।

प्रति सत्र एक टोकन?

प्रति सत्र एक टोकन का उपयोग आपके उद्देश्यों के लिए ठीक हो सकता है। हालांकि, सचेत रहें: एक सत्र n मिनट है

  1. तो लंबे समय से तो एक हमलावर का निर्धारण करने या अपने टोकन मूल्य प्राप्त करने के लिए और एक CSRF हमले निष्पादित करने के लिए प्रयास करने के लिए एक n मिनट खिड़की है। जबकि यह जोखिम कम हो जाता है जब टोकन प्रति रूप से उत्पन्न होते हैं या जब टोकन समय-समय पर पुन: उत्पन्न होता है क्योंकि वे लंबे समय तक पर्याप्त नहीं रहते हैं।
  2. प्रति सत्र एक टोकन का उपयोग करके आपके सभी एप्लिकेशन की कार्यक्षमता (जो उस टोकन का उपयोग करती है) को हमला करने के लिए हमलावर को टोकन निर्धारित/प्राप्त करना चाहिए। जबकि प्रति टोकन का उपयोग करना एक ही रूप में एक हमले को प्रतिबंधित करता है।

क्या सबमिट किए गए फॉर्म पर टोकन को साफ़ करने की आवश्यकता होगी? या बस इसके साथ रहें, भले ही मैंने एक फॉर्म जमा किया हो?

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

  1. या टोकन मूल्य मजबूर करने के लिए ब्रूट।
  2. टोकन जीवनकाल को कम करने के लिए समय-समय पर टोकन को पुन: उत्पन्न करना, टोकन निर्धारित या प्राप्त होने पर हमले की खिड़की को कम करना।
  3. टोकन निर्धारित या प्राप्त होने की स्थिति में हमलों को एक ही रूप में प्रतिबंधित करने के लिए प्रति फॉर्म टोकन उत्पन्न करना।
1

मैंने पहले से ही एक अलग मंच पर एक समान प्रश्न का उत्तर दिया है: here। उम्मीद है कि यह सहायक है। यह सीएसआरएफ रोकथाम की बुनियादी प्रक्रिया और सीएसआरएफ ढांचे के लिए कुछ कोड के लिंक बताता है।

यदि आप उच्च सुरक्षा चाहते हैं, तो प्रत्येक सत्र के लिए प्रत्येक अनुरोध के बाद टोकन बदलें। यदि आप बेहतर उपयोगिता चाहते हैं, तो प्रति सत्र एक टोकन रखें।

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