कई उपयोगी जवाबों के बारे में, मुझे इस धागे में कुछ मूल्य जोड़ने की उम्मीद है।
एसक्यूएल इंजेक्शन एक ऐसा हमला है जो उपयोगकर्ता इनपुट (इनपुट जो किसी उपयोगकर्ता द्वारा भरा जाता है और फिर प्रश्नों के अंदर उपयोग किया जाता है) के माध्यम से किया जा सकता है। SQL इंजेक्शन पैटर्न सही क्वेरी सिंटैक्स होते हैं जब हम इसे कॉल कर सकते हैं: बुरे कारणों के लिए बुरे प्रश्न, और हम मानते हैं कि एक बुरा व्यक्ति हो सकता है जो गुप्त जानकारी (एक्सेस कंट्रोल को दरकिनार) करने की कोशिश करता है जो सुरक्षा के तीन सिद्धांतों को प्रभावित करता है (गोपनीयता) अखंडता, और उपलब्धता)।
अब, हमारा कहना है कि सुरक्षा खतरों जैसे SQL इंजेक्शन के हमलों को रोकने के लिए, सवाल पूछ रहा है (PHP का उपयोग करके SQL इंजेक्शन के हमले को कैसे रोका जाए), अधिक यथार्थवादी हो, डेटा इनपुट या क्लीयरिंग इनपुट डेटा मामला है जब उपयोगकर्ता-इनपुट डेटा का उपयोग कर अंदर इस तरह की क्वेरी, PHP या किसी अन्य प्रोग्रामिंग भाषा का उपयोग करना मामला नहीं है, या जैसा कि अधिक लोगों द्वारा आधुनिक तकनीक का उपयोग करने की सिफारिश की गई है जैसे कि तैयार बयान या कोई अन्य उपकरण जो वर्तमान में SQL इंजेक्शन की रोकथाम का समर्थन कर रहे हैं, विचार करें कि ये उपकरण अब उपलब्ध नहीं हैं? आप अपने आवेदन को कैसे सुरक्षित करते हैं?
SQL इंजेक्शन के प्रति मेरा दृष्टिकोण है: डेटाबेस में भेजने से पहले उपयोगकर्ता-इनपुट डेटा को साफ़ करना (किसी भी क्वेरी के अंदर उपयोग करने से पहले)।
के लिए डेटा फ़िल्टरिंग (असुरक्षित डेटा को सुरक्षित डेटा में परिवर्तित करना)
गौर करें कि PDO और MySQLi उपलब्ध नहीं हैं। आप अपने आवेदन को कैसे सुरक्षित कर सकते हैं? क्या आप मुझे उनका उपयोग करने के लिए मजबूर करते हैं? PHP के अलावा अन्य भाषाओं के बारे में क्या? मैं सामान्य विचारों को प्रदान करना पसंद करता हूं क्योंकि इसका उपयोग व्यापक सीमा के लिए किया जा सकता है, न कि केवल एक विशिष्ट भाषा के लिए।
- SQL उपयोगकर्ता (उपयोगकर्ता विशेषाधिकार को सीमित करना): सबसे आम SQL ऑपरेशन हैं (SELECT, UPDATE, INSERT), फिर, UPDATE को उस उपयोगकर्ता को विशेषाधिकार क्यों दें जिसकी आवश्यकता नहीं है? उदाहरण के लिए, लॉगिन और खोज पृष्ठ केवल SELECT का उपयोग कर रहे हैं, फिर, इन पृष्ठों में DB उपयोगकर्ताओं को उच्च विशेषाधिकार के साथ क्यों उपयोग करें?
नियम: सभी विशेषाधिकारों के लिए एक डेटाबेस उपयोगकर्ता नहीं बनाएं। सभी SQL संचालन के लिए, आप आसान उपयोग के लिए उपयोगकर्ता नाम के रूप में अपनी योजना बना सकते हैं (भ्रम, चयनकर्ता, अद्यतनकर्ता)।
कम से कम विशेषाधिकार का सिद्धांत देखें ।
डेटा फ़िल्टरिंग: किसी भी क्वेरी उपयोगकर्ता इनपुट के निर्माण से पहले, इसे मान्य और फ़िल्टर किया जाना चाहिए। प्रोग्रामर के लिए, प्रत्येक उपयोगकर्ता-इनपुट चर के लिए कुछ गुणों को परिभाषित करना महत्वपूर्ण है:
डेटा प्रकार, डेटा पैटर्न और डेटा लंबाई । एक फ़ील्ड जो (x और y) के बीच की संख्या है, सटीक नियम का उपयोग करके बिल्कुल मान्य होनी चाहिए, और एक फ़ील्ड के लिए जो एक स्ट्रिंग (पाठ) है: पैटर्न मामला है, उदाहरण के लिए, एक उपयोगकर्ता नाम में केवल कुछ वर्ण होने चाहिए, आइए [a-zA-Z0-9_-] कहें। लंबाई (x और n) के बीच भिन्न होती है जहां x और n (पूर्णांक, x <= n)।
नियम: सटीक फ़िल्टर और सत्यापन नियम बनाना मेरे लिए सर्वोत्तम अभ्यास हैं।
अन्य उपकरणों का उपयोग करें: यहां, मैं आपके साथ एक तैयार कथन (पैराड्राइज्ड क्वेरी) और संग्रहीत प्रक्रियाओं से भी सहमत हूं। यहां नुकसान इन तरीकों से उन्नत कौशल की आवश्यकता होती है जो अधिकांश उपयोगकर्ताओं के लिए मौजूद नहीं हैं। यहां मूल विचार SQL क्वेरी और अंदर उपयोग किए जाने वाले डेटा के बीच अंतर करना है। दोनों तरीकों का उपयोग असुरक्षित डेटा के साथ भी किया जा सकता है, क्योंकि यहां उपयोगकर्ता-इनपुट डेटा मूल क्वेरी, जैसे (किसी भी या x = x) में कुछ भी नहीं जोड़ता है।
अधिक जानकारी के लिए, कृपया OWASP SQL इंजेक्शन निवारण धोखा शीट पढ़ें ।
अब, यदि आप एक उन्नत उपयोगकर्ता हैं, तो इस रक्षा का उपयोग करना शुरू करें जैसा कि आप चाहते हैं, लेकिन, शुरुआती लोगों के लिए, यदि वे जल्दी से एक संग्रहीत प्रक्रिया को लागू नहीं कर सकते हैं और बयान तैयार कर सकते हैं, तो इनपुट डेटा को फ़िल्टर करना बेहतर होगा जितना वे कर सकते हैं।
अंत में, आइए विचार करें कि कोई उपयोगकर्ता अपने उपयोगकर्ता नाम दर्ज करने के बजाय नीचे यह पाठ भेजता है:
[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'
इस इनपुट को बिना किसी तैयार किए गए स्टेटमेंट और स्टोर की गई प्रक्रियाओं के बिना जल्दी से चेक किया जा सकता है, लेकिन यूजर-डेटा फ़िल्टरिंग और सत्यापन के बाद उनका उपयोग करना सुरक्षित पक्ष पर होना चाहिए।
अंतिम बिंदु अप्रत्याशित व्यवहार का पता लगा रहा है जिसके लिए अधिक प्रयास और जटिलता की आवश्यकता होती है; यह सामान्य वेब अनुप्रयोगों के लिए अनुशंसित नहीं है।
उपरोक्त उपयोगकर्ता इनपुट में अप्रत्याशित व्यवहार SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA, और रूट है। एक बार जब इन शब्दों का पता चला, तो आप इनपुट से बच सकते हैं।
अद्यतन 1:
एक उपयोगकर्ता ने टिप्पणी की कि यह पोस्ट बेकार है, ठीक है! यहाँ OWASP.ORG प्रदान किया गया है :
प्राथमिक बचाव:
विकल्प # 1: तैयार किए गए विवरणों का उपयोग (परिमित क्वेरीज़)
विकल्प # 2: संग्रहीत कार्यविधियाँ
विकल्प # 3 का उपयोग: सभी उपयोगकर्ता अनुपूरित इनपुट से बचना
अतिरिक्त बचाव:
इसके अलावा लागू करें: कम से कम विशेषाधिकार
भी निष्पादित करें: श्वेत सूची इनपुट सत्यापन
जैसा कि आप जानते हैं, एक लेख का दावा करना वैध तर्क द्वारा समर्थित होना चाहिए, कम से कम एक संदर्भ द्वारा! अन्यथा, यह एक हमला और एक बुरा दावा माना जाता है!
अपडेट 2:
PHP मैनुअल से, PHP: तैयार विवरण - मैनुअल :
बचने और एसक्यूएल इंजेक्शन
बाध्य चर सर्वर द्वारा स्वचालित रूप से बच जाएंगे। निष्पादन से पहले सर्वर स्टेटमेंट टेम्प्लेट में उपयुक्त स्थानों पर उनके बच गए मूल्यों को सम्मिलित करता है। उपयुक्त रूपांतरण बनाने के लिए, बाउंड चर के प्रकार के लिए एक संकेत सर्वर को प्रदान किया जाना चाहिए। अधिक जानकारी के लिए mysqli_stmt_bind_param () फ़ंक्शन देखें।
SQL इंजेक्शन को रोकने के लिए सर्वर के भीतर मानों का स्वचालित रूप से बचना कभी-कभी एक सुरक्षा विशेषता माना जाता है। गैर-तैयार बयानों के साथ सुरक्षा का एक ही अंश प्राप्त किया जा सकता है यदि इनपुट मान सही ढंग से बच गए हैं।
अपडेट 3:
मैंने पीडीओ और MySQLi ने तैयार स्टेटमेंट का उपयोग करते समय MySQL सर्वर को क्वेरी कैसे भेजते हैं, यह जानने के लिए टेस्ट केस बनाए:
पीडीओ:
$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));
क्वेरी लॉग:
189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
189 Quit
MySQLi:
$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();
क्वेरी लॉग:
188 Prepare SELECT * FROM awa_user WHERE username =?
188 Execute SELECT * FROM awa_user WHERE username ='\'\'1\'\''
188 Quit
यह स्पष्ट है कि एक तैयार बयान भी डेटा से बच रहा है, और कुछ नहीं।
जैसा कि उपरोक्त कथन में भी बताया गया है,
SQL इंजेक्शन को रोकने के लिए सर्वर के भीतर मानों का स्वचालित रूप से बचना कभी-कभी एक सुरक्षा विशेषता माना जाता है। गैर-तैयार बयानों के साथ सुरक्षा की एक ही डिग्री प्राप्त की जा सकती है, यदि इनपुट मान सही ढंग से बच गए हैं
इसलिए, यह साबित करता है कि डेटा सत्यापन जैसे intval()
किसी भी प्रश्न को भेजने से पहले पूर्णांक मूल्यों के लिए एक अच्छा विचार है। इसके अलावा, क्वेरी भेजने से पहले दुर्भावनापूर्ण उपयोगकर्ता डेटा को रोकना एक सही और मान्य दृष्टिकोण है ।
कृपया इस प्रश्न को और अधिक विस्तार से देखें: PDO MySQL को कच्ची क्वेरी भेजता है जबकि मैसकली तैयार क्वेरी भेजता है, दोनों एक ही परिणाम उत्पन्न करते हैं
संदर्भ:
- SQL इंजेक्शन धोखा शीट
- एसक्यूएल इंजेक्षन
- सूचना सुरक्षा
- सुरक्षा सिद्धांत
- डेटा मान्य