security "बॉबी टेबल्स" एक्सकेसीडी कॉमिक काम से एसक्यूएल इंजेक्शन कैसे करता है?




validation sql-injection (10)

बस देख रहे हैं:

(स्रोत: https://xkcd.com/327/ )

यह एसक्यूएल क्या करता है:

Robert'); DROP TABLE STUDENTS; --

मैं दोनों ' और -- टिप्पणियों के लिए जानता हूं, लेकिन क्या DROP शब्द भी टिप्पणी नहीं करता है क्योंकि यह एक ही पंक्ति का हिस्सा है?


मान लें कि नाम एक चर, $Name में प्रयोग किया गया था। फिर आप यह क्वेरी चलाते हैं:

INSERT INTO Students VALUES ( '$Name' )

आपको क्या मिलता है:

INSERT INTO Students VALUES ( 'Robert' );  DROP TABLE STUDENTS; --' )

-- केवल पंक्ति के शेष टिप्पणी करता है।


डेटाबेस के लेखक ने शायद किया था

sql = "SELECT * FROM STUDENTS WHERE (STUDENT_NAME = '" + student_name + "') AND other stuff";
execute(sql);

यदि छात्र_नाम दिया गया है, तो वह "रॉबर्ट" नाम के साथ चयन करता है और फिर तालिका को छोड़ देता है। "-" भाग शेष दिए गए प्रश्न को एक टिप्पणी में बदल देता है।


एसक्यूएल में वर्ण स्ट्रिंग स्थिरांक के लिए प्रयोग किया जाता है। इस मामले में यह स्ट्रिंग निरंतर समाप्त करने के लिए प्रयोग किया जाता है, न कि टिप्पणी के लिए।


नहीं, ' एसक्यूएल में कोई टिप्पणी नहीं है, लेकिन एक डिलीमीटर है।

माँ को लगता है कि डेटाबेस प्रोग्रामर ने एक अनुरोध किया है:

INSERT INTO 'students' ('first_name', 'last_name') VALUES ('$firstName', '$lastName');

(उदाहरण के लिए) नया छात्र जोड़ने के लिए, जहां $xxx परिवर्तनीय सामग्री सीधे एचटीएमएल फॉर्म से बाहर ले ली गई थी, प्रारूप की जांच किए बिना और विशेष वर्णों से बचने के बिना।

तो अगर $firstName Robert'); DROP TABLE students; -- Robert'); DROP TABLE students; -- Robert'); DROP TABLE students; -- डेटाबेस प्रोग्राम डीबी पर सीधे निम्नलिखित अनुरोध निष्पादित करेगा:

INSERT INTO 'students' ('first_name', 'last_name') VALUES ('Robert'); DROP TABLE students; --', 'XKCD');

अर्थात। यह सम्मिलित कथन के प्रारंभ में समाप्त हो जाएगा, क्रैकर चाहता है कि जो भी दुर्भावनापूर्ण कोड निष्पादित करें, फिर टिप्पणी करें कि कोड के शेष शेष क्या हो सकते हैं।

श्रीमान, मैं बहुत धीमी हूं, मुझे नारंगी बैंड में मेरे सामने पहले से ही 8 उत्तरों दिखाई दे रहे हैं ... :-) एक लोकप्रिय विषय, ऐसा लगता है।


टी एल; डॉ

-- The application accepts input, in this case 'Nancy', without attempting to
-- sanitize the input, such as by escaping special characters
school=> INSERT INTO students VALUES ('Nancy');
INSERT 0 1

-- SQL injection occurs when input into a database command is manipulated to
-- cause the database server to execute arbitrary SQL
school=> INSERT INTO students VALUES ('Robert'); DROP TABLE students; --');
INSERT 0 1
DROP TABLE

-- The student records are now gone - it could have been even worse!
school=> SELECT * FROM students;
ERROR:  relation "students" does not exist
LINE 1: SELECT * FROM students;
                      ^

यह छात्र तालिका छोड़ देता है। यह स्पष्ट करने के लिए कि क्या हो रहा है, आइए इसे एक साधारण तालिका के साथ आज़माएं जिसमें केवल नाम फ़ील्ड है और एक पंक्ति जोड़ें (PostgreSQL 9.1.2 के साथ परीक्षण किया गया है):

school=> CREATE TABLE students (name TEXT PRIMARY KEY);
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "students_pkey" for table "students"
CREATE TABLE
school=> INSERT INTO students VALUES ('John');
INSERT 0 1

आइए मान लें कि एप्लिकेशन तालिका में डेटा डालने के लिए निम्न SQL का उपयोग करता है:

INSERT INTO students VALUES ('foobar');

छात्र के वास्तविक नाम के साथ foobar बदलें। एक सामान्य डालने का ऑपरेशन इस तरह दिखेगा:

--                            Input:   Nancy
school=> INSERT INTO students VALUES ('Nancy');
INSERT 0 1

जब हम टेबल से पूछते हैं, तो हमें यह मिलता है:

school=> SELECT * FROM students;
 name
-------
 John
 Nancy
(2 rows)

क्या होता है जब हम टेबल में लिटिल बॉबी टेबल्स का नाम डालते हैं?

--                            Input:   Robert'); DROP TABLE students; --
school=> INSERT INTO students VALUES ('Robert'); DROP TABLE students; --');
INSERT 0 1
DROP TABLE

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

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

परिणाम?

school=> SELECT * FROM students;
ERROR:  relation "students" does not exist
LINE 1: SELECT * FROM students;
                      ^

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

जैसा कि एक्सकेसीडी कॉमिक द्वारा नोट किया गया है, एसक्यूएल इंजेक्शन हमलों के खिलाफ सुरक्षा का एक तरीका डेटाबेस इनपुट को स्वच्छ करना है, जैसे कि विशेष पात्रों से बचकर, ताकि वे अंतर्निहित SQL कमांड को संशोधित नहीं कर सकें और इसलिए मनमाने ढंग से SQL कोड निष्पादित नहीं कर सकते हैं। यदि आप पैरामीटरयुक्त प्रश्नों का उपयोग करते हैं, जैसे कि ADO.NET में SqlParameter का उपयोग करके, इनपुट स्वचालित रूप से आपके लिए स्वच्छ हो जाएगा।


इस तरह यह काम करता है: मान लीजिए कि व्यवस्थापक छात्र के रिकॉर्ड की तलाश में है

Robert'); DROP TABLE STUDENTS; --

चूंकि व्यवस्थापक खाते में इस खाते से तालिका को हटाने का उच्च विशेषाधिकार संभव है।

अनुरोध से उपयोगकर्ता नाम पुनर्प्राप्त करने के लिए कोड है

अब सवाल ऐसा कुछ होगा (छात्र तालिका खोजने के लिए)

String query="Select * from student where username='"+student_name+"'";

statement.executeQuery(query); //Rest of the code follows

परिणामी क्वेरी बन जाती है

Select * from student where username='Robert'); DROP TABLE STUDENTS; --

चूंकि उपयोगकर्ता इनपुट sanitized नहीं है, उपर्युक्त क्वेरी 2 भागों में छेड़छाड़ की है

Select * from student where username='Robert'); 

DROP TABLE STUDENTS; --

डबल डैश (-) क्वेरी के शेष भाग पर टिप्पणी करेगा।

यह खतरनाक है क्योंकि यह मौजूद होने पर पासवर्ड प्रमाणीकरण को रद्द कर सकता है

पहला सामान्य खोज करेगा।

दूसरा खाता तालिका छात्र को छोड़ देगा यदि खाते में पर्याप्त विशेषाधिकार हैं (आम तौर पर स्कूल व्यवस्थापक खाता ऐसी क्वेरी चलाएगा और विशेषाधिकारों के ऊपर के बारे में बात की जाएगी)।


मान लें कि आपने इस तरह एक छात्र निर्माण विधि को नैतिक रूप से लिखा है:

void createStudent(String name) {
    database.execute("INSERT INTO students (name) VALUES ('" + name + "')");
}

और कोई Robert'); DROP TABLE STUDENTS; -- नाम में प्रवेश करता है Robert'); DROP TABLE STUDENTS; -- Robert'); DROP TABLE STUDENTS; --

डेटाबेस पर क्या चला जाता है यह प्रश्न है:

INSERT INTO students (name) VALUES ('Robert'); DROP TABLE STUDENTS --')

अर्धविराम सम्मिलित करें आदेश समाप्त होता है और दूसरा शुरू होता है; - बाकी पंक्ति के बारे में टिप्पणी करता है। ड्रॉप टेबल कमांड निष्पादित किया गया है ...

यही कारण है कि बाध्य पैरामीटर एक अच्छी बात है।


जैसा कि हर किसी ने पहले ही बताया है, '); मूल कथन बंद कर देता है और फिर दूसरा कथन निम्नानुसार होता है। PHP जैसे भाषाओं सहित अधिकांश ढांचे में अब तक डिफ़ॉल्ट सुरक्षा सेटिंग्स हैं जो एक SQL स्ट्रिंग में एकाधिक कथन की अनुमति नहीं देते हैं। PHP में, उदाहरण के लिए, आप mysqli_multi_query फ़ंक्शन का उपयोग करके केवल एक SQL स्ट्रिंग में एकाधिक कथन चला सकते हैं।

हालांकि, आप दूसरे कथन को जोड़ने के बिना SQL इंजेक्शन के माध्यम से मौजूदा SQL कथन का उपयोग कर सकते हैं। मान लें कि आपके पास एक लॉगिन सिस्टम है जो इस सरल चयन के साथ उपयोगकर्ता नाम और पासवर्ड की जांच करता है:

$query="SELECT * FROM users WHERE username='" . $_REQUEST['user'] . "' and (password='".$_REQUEST['pass']."')";
$result=mysql_query($query);

यदि आप पासवर्ड के रूप में उपयोगकर्ता नाम और secret रूप में peter प्रदान करते हैं, तो परिणामस्वरूप SQL स्ट्रिंग इस तरह दिखेगी:

SELECT * FROM users WHERE username='peter' and (password='secret')

सब कुछ ठीक है। अब कल्पना करें कि आप इस स्ट्रिंग को पासवर्ड के रूप में प्रदान करते हैं:

' OR '1'='1

फिर परिणामी एसक्यूएल स्ट्रिंग यह होगी:

SELECT * FROM users WHERE username='peter' and (password='' OR '1'='1')

इससे आपको पासवर्ड जानने के बिना किसी भी खाते में लॉग इन करने में मदद मिलेगी। इसलिए आपको SQL इंजेक्शन का उपयोग करने के लिए दो कथनों का उपयोग करने में सक्षम होने की आवश्यकता नहीं है, हालांकि यदि आप कई कथन प्रदान करने में सक्षम हैं तो आप अधिक विनाशकारी चीजें कर सकते हैं।


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

$sql = "INSERT INTO `Students` (FirstName, LastName) VALUES ('" . $fname . "', '" . $lname . "')";

तो प्रोग्रामर की अपेक्षा होने से पहले 'चरित्र स्ट्रिंग अक्षरशः समाप्त होता है। के साथ संयुक्त; कथन को समाप्त करने के लिए चरित्र, एक हमलावर अब जो भी एसक्यूएल जोड़ सकता है उसे जोड़ सकता है। अंत में टिप्पणी यह ​​सुनिश्चित करना है कि मूल कथन में कोई शेष एसक्यूएल क्वेरी को सर्वर पर संकलित करने से रोकता नहीं है।

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


एक एकल बोली एक स्ट्रिंग की शुरुआत और अंत है। एक अर्धविराम एक बयान का अंत है। तो अगर वे इस तरह का चयन कर रहे थे:

Select *
From Students
Where (Name = '<NameGetsInsertedHere>')

एसक्यूएल बन जाएगा:

Select *
From Students
Where (Name = 'Robert'); DROP TABLE STUDENTS; --')
--             ^-------------------------------^

कुछ प्रणालियों पर, select पहले drop बयान के बाद भाग जाएगा! संदेश है: अपने एसक्यूएल में मूल्यों को बढ़ाया नहीं है। इसके बजाय पैरामीटर का उपयोग करें!





sql-injection