दिलचस्प पोस्ट
जावास्क्रिप्ट में सबसे तेज़ एमडी 5 का कार्यान्वयन ब्राउज़र के पता बार छिपाए उसी विंडो में एक ही विंडो में खोलें और एक ही टैब में कोणीय कलेक्शन में कम्पाइल और लिंक फंक्शन में अंतर क्या है जावास्क्रिप्ट / jQuery का इस्तेमाल करने वाली छवियों को प्रीलोड करने का निश्चित सबसे अच्छा तरीका है? पावरशेल आईई 9 कॉम ऑब्जेक्ट में वेबपेज पर नेविगेट करने के बाद सभी रिक्त गुण हैं जावा में स्ट्रिंग के साथ इंट भी हो, जिसमें पत्र भी शामिल हैं I ड्रॉपबॉक्स मुद्दे के साथ गिट सी # बनाम एफ # या एफ # बनाम सी # का उपयोग करने के क्या लाभ हैं? जावा अपवाद कितना धीमा है? .NET और बिटमैप जीसी द्वारा स्वचालित रूप से निपटा नहीं जाता है जब कोई मेमोरी नहीं छोड़ा जाता है PHP लिप्यांतरण यूटीसी के कारण जेसनॉन स्ट्रिंग की तिथि का समय बदलता है JFrame में पृष्ठभूमि चित्र सेट करना स्विफ्ट: गार्ड बनाम अगर चलो

एसक्यूएल इंजेक्शन के हमलों से सुरक्षित बयान कैसे तैयार हो सकते हैं?

तैयार किए गए स्टेटमेंट हमें एसक्यूएल इंजेक्शन के हमलों को कैसे रोकते हैं?

विकिपीडिया का कहना है:

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

मैं कारण बहुत अच्छी तरह से नहीं देख सकता आसान अंग्रेजी और कुछ उदाहरणों में एक सरल व्याख्या क्या होगी?

वेब के समाधान से एकत्रित समाधान "एसक्यूएल इंजेक्शन के हमलों से सुरक्षित बयान कैसे तैयार हो सकते हैं?"

यह विचार बहुत सरल है – क्वेरी और डेटा एसक्यूएल सर्वर को अलग से भेजा जाता है।
बस इतना ही।

एसक्यूएल इंजेक्शन समस्या की जड़ कोड और डेटा के मिश्रण है।

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

$expected_data = 1; $query = "SELECT * FROM users where id=$expected_data"; 

एक नियमित क्वेरी का उत्पादन करेगा

 SELECT * FROM users where id=1 

जबकि यह कोड

 $spoiled_data = "1; DROP TABLE users;" $query = "SELECT * FROM users where id=$spoiled_data"; 

दुर्भावनापूर्ण अनुक्रम का उत्पादन करेगा

 SELECT * FROM users where id=1; DROP TABLE users; 

यह काम करता है क्योंकि हम सीधे प्रोग्राम बॉडी में डेटा जोड़ रहे हैं और यह कार्यक्रम का एक हिस्सा बन गया है।

इसलिए, डेटा प्रोग्राम को बदल सकता है और पारित किए गए डेटा के आधार पर, हम या तो नियमित आउटपुट या टेबल users हटाएंगे।

जबकि तैयार बयान के मामले में हम अपने कार्यक्रम में बदलाव नहीं करते हैं, यह बरकरार है
यही तो बात है।

हम पहले सर्वर पर कार्यक्रम भेज रहे हैं

 $db->prepare("SELECT * FROM users where id=?"); 

जहां डेटा "प्लेसहोल्डर" नामक कुछ वेरिएबल द्वारा प्रतिस्थापित किया जाता है

ध्यान दें कि सर्वर पर भेजे जाने वाली एक ही क्वेरी, बिना किसी डेटा के! और फिर हम दूसरे अनुरोध के साथ डेटा भेज रहे हैं, पूरी तरह से क्वेरी से अलग हो गए हैं:

 $db->execute($data); 

इसलिए, यह हमारे कार्यक्रम को बदल नहीं सकता है और कोई नुकसान नहीं पहुंचा सकता।
काफी सरल – क्या यह नहीं है?

हालांकि, यह ध्यान देने योग्य है कि हर बार जब आप प्लेसहोल्डर का उपयोग नहीं कर रहे हैं, तो इसे तैयार कथन के रूप में संसाधित किया जाता है

प्लेसहोल्डर भविष्य की प्रसंस्करण के लिए एक वैरिएबल के साथ वास्तविक डेटा को प्रतिस्थापित करने के लिए एक सामान्य विचार है, जबकि तैयार कथन उन में से केवल उपसमुच्चय है

इसलिए, कभी-कभी हमें वास्तव में डेटा के साथ क्वेरी लिखना पड़ता है, लेकिन अगर हर बिट डेटा ठीक प्रकार से स्वरूपित होता है – तो कुछ भी गलत नहीं हो सकता

इसलिए, उदाहरण के लिए, डिफ़ॉल्ट रूप से PDO तैयार बयान का उपयोग नहीं करते हैं बल्कि नियमित क्वेरी तैयार करते हैं । लेकिन क्योंकि यह प्रत्येक प्लेसहोल्डर को ठीक से स्वरूपित डेटा के साथ प्रतिस्थापित करता है, कुछ भी बुरा नहीं हो सकता।

लेकिन आप पीडीओ को सीधे तैयार करने के लिए बताना चाहते हैं, असली तैयार बयानों का उपयोग करने के लिए, आपको यह सेटिंग सेट करना है:

 $dbh->setAttribute( PDO::ATTR_EMULATE_PREPARES, false ); 

कृपया यह भी ध्यान रखें कि बचने के साथ फ़ॉर्मेटिंग को भ्रमित नहीं करना है । प्रारूपण में मूर्खता से बचने के अलावा बहुत अधिक क्रियाएं शामिल हैं I इसलिए, घर पर बचने के लिए मैन्युअल रूप से प्रयास न करें, कम से कम जब तक आपको प्रत्येक अलग क्वेरी भाग के लिए प्रत्येक फ़ॉर्मेटिंग नियम को पता न हो।

मुझे केवल एक ही चीज़ जोड़नी है, हर मैनुअल में हमेशा छोड़ी गई है:

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

एक उदाहरण स्थापित करने के लिए यहां एसक्यूएल है:

 CREATE TABLE employee(name varchar, paymentType varchar, amount bigint); INSERT INTO employee VALUES('Aaron', 'salary', 100); INSERT INTO employee VALUES('Aaron', 'bonus', 50); INSERT INTO employee VALUES('Bob', 'salary', 50); INSERT INTO employee VALUES('Bob', 'bonus', 0); 

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

 import java.sql.*; public class Inject { public static void main(String[] args) throws SQLException { String url = "jdbc:postgresql://localhost/postgres?user=user&password=pwd"; Connection conn = DriverManager.getConnection(url); Statement stmt = conn.createStatement(); String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='" + args[0] + "'"; System.out.println(sql); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount")); } } } 

इसे चलाना, पहला मामला सामान्य उपयोग के साथ होता है, और दूसरा दुर्भावनापूर्ण इंजेक्शन के साथ होता है:

 c:\temp>java Inject salary SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary' salary 50 c:\temp>java Inject "salary' OR 'a'!='b" SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType='salary' OR 'a'!='b' salary 100 bonus 50 salary 50 bonus 0 

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

इस तरह के इंजेक्शन से बचने के लिए बाइंडिंग का एक उदाहरण यहां दिया गया है:

 import java.sql.*; public class Bind { public static void main(String[] args) throws SQLException { String url = "jdbc:postgresql://localhost/postgres?user=postgres&password=postgres"; Connection conn = DriverManager.getConnection(url); String sql = "SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=?"; System.out.println(sql); PreparedStatement stmt = conn.prepareStatement(sql); stmt.setString(1, args[0]); ResultSet rs = stmt.executeQuery(); while (rs.next()) { System.out.println(rs.getString("paymentType") + " " + rs.getLong("amount")); } } } 

पिछले उदाहरण के रूप में एक ही इनपुट के साथ चल रहा है यह दिखाता है कि दुर्भावनापूर्ण कोड काम नहीं करता क्योंकि कोई भुगतान नहीं है, उस स्ट्रिंग से मेल खाती है:

 c:\temp>java Bind salary SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=? salary 50 c:\temp>java Bind "salary' OR 'a'!='b" SELECT paymentType, amount FROM employee WHERE name = 'bob' AND paymentType=? 

असल में, तैयार बयान के साथ संभावित हैकर से आने वाले डेटा को डेटा के रूप में माना जाता है – और इसका कोई तरीका नहीं है कि इसे आपके एसक्यूएल और / या एसक्यूएल के रूप में समझाया जा सकता है (जो तब हो सकता है जब डेटा पारित किया जाता है आवेदन एसक्यूएल)

इसका कारण यह है कि तैयार कतारों को एक कुशल क्वेरी प्लान ढूंढने के लिए एसक्यूएल क्वेरी पहले "तैयार" करता है, और वास्तविक मान भेजता है जो संभवतया बाद में एक फार्म से प्राप्त होता है – उस समय क्वेरी वास्तव में निष्पादित होती है।

यहां अधिक महान जानकारी:

तैयार बयान और एसक्यूएल इंजेक्शन

SQL सर्वर में , एक तैयार कथन का उपयोग निश्चित रूप से इंजेक्शन-सबूत है क्योंकि इनपुट पैरामीटर क्वेरी का निर्माण नहीं करता है। इसका मतलब है कि क्रियान्वित क्वेरी एक गतिशील क्वेरी नहीं है। एक एसक्यूएल इंजेक्शन कमजोर बयान का उदाहरण

 string sqlquery = "select * from table where username='" + inputusername +"' and password='" + pass + "'"; 

अब यदि इनउटस उपयोगकर्ता नाम में वैल्यू एक 'या 1 = 1 जैसा कुछ है, तो यह प्रश्न अब हो जाती है:

 select * from table where username='a' or 1=1 -- and password=asda 

और बाकी के बाद टिप्पणी की जाती है, इसलिए इसे कभी भी निष्पादित नहीं किया जाता है और नीचे दिए गए उदाहरण के लिए तैयार बयान उदाहरण का उपयोग करने के रूप में नजरअंदाज नहीं किया जाता है।

 Sqlcommand command = new sqlcommand("select * from table where username = @userinput and password=@pass"); command.Parameters.Add(new SqlParameter("@userinput", 100)); command.Parameters.Add(new SqlParameter("@pass", 100)); command.prepare(); 

इसलिए आप दूसरे पैरामीटर को नहीं भेज सकते, इस प्रकार एसक्यूएल इंजेक्शन से बचें …

महत्वपूर्ण वाक्यांश को need not be correctly escaped । इसका मतलब है कि आप डैश, एपॉस्ट्रॉप्स, उद्धरण आदि में फेंकने की कोशिश कर रहे लोगों के बारे में चिंता न करें …

यह सब आपके लिए संभाला है

 ResultSet rs = statement.executeQuery("select * from foo where value = " + httpRequest.getParameter("filter"); 

मान लीजिए आपके पास यह है कि एक सर्विस में आप सही हैं यदि एक अभद्र व्यक्ति ने 'फिल्टर' के लिए एक खराब मूल्य पारित किया है, तो आप अपने डेटाबेस को हैक कर सकते हैं।

जब आप डीबीएमएस में एक तैयार कथन बनाते हैं और भेजते हैं, तो इसे एसक्यूएल क्वेरी के रूप में निष्पादन के रूप में संग्रहीत किया जाता है।

बाद में आप अपने डेटा को क्वेरी में बाँध सकते हैं, जैसे कि डीबीएमएस उस डेटा को निष्पादन (पैरामीटरजेशन) के लिए क्वेरी पैरामीटर के रूप में उपयोग करता है। डीबीएमएस आपके द्वारा पहले से संकलित एसक्यूएल क्वेरी के पूरक के रूप में बाइंड किए गए डेटा का उपयोग नहीं करता है; यह बस डेटा है

इसका मतलब यह है कि तैयार कथनों का उपयोग करने के लिए एसक्यूएल इंजेक्शन निष्पादित करना मौलिक रूप से असंभव है। तैयार बयान की प्रकृति और डीबीएमएस के साथ उनके रिश्ते इस को रोकते हैं।

रूट कारण # 1 – डिलिमिटर समस्या

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

रूट का कारण # 2 – मानव प्रकृति, लोग चालाक हैं और कुछ चालाक लोग दुर्भावनापूर्ण हैं और सभी लोग गलतियां करते हैं

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

कैसे स्ट्रक्चर्ड क्वेरीज़ SQL इंजेक्शन के रूट कारणों को हल करें

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

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

इसलिए, आपके पास यह है, एसक्यूएल इंजेक्शन और प्रकृति की रचनात्मक प्रश्नों के कारण ये है कि जब उनका उपयोग किया जाता है तब उन्हें असंभव बना देता है।