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

Τι είναι η SQL injection;

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

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

Παράδειγμα SQL injection που δείχνει πώς λειτουργεί μια επίθεση σε βάση δεδομένων

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

Παράδειγμα 1: Πρόσβαση μέσω εισόδου χρήστη με ανεπαρκή διαφυγή

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

uname = request.POST['username']
passwd = request.POST['password']
sql = "SELECT id FROM users WHERE username='" + uname + "' AND password='" + passwd + "'"
database.execute(sql)
python

Ένας εισβολέας μπορεί πλέον να παραποιήσει το πεδίο του κωδικού πρόσβασης χρησιμοποιώντας μια επίθεση SQL injection, για παράδειγμα εισάγοντας password' OR 1='1, κάτι που οδηγεί στην ακόλουθη ερώτηση SQL:

sql = "SELECT id FROM users WHERE username='' AND password='password' OR 1='1'"
python

Αυτό παρέχει στον εισβολέα πλήρη πρόσβαση σε ολόκληρο τον πίνακα χρηστών της βάσης δεδομένων, καθώς η συνθήκη του κωδικού πρόσβασης έχει πάντα την τιμή «true» (1='1'). Εάν ο εισβολέας συνδεθεί ως διαχειριστής, μπορεί να τροποποιήσει ελεύθερα οποιαδήποτε εγγραφή της βάσης δεδομένων. Εναλλακτικά, το πεδίο του ονόματος χρήστη μπορεί να παραποιηθεί με τον ίδιο τρόπο.

Παράδειγμα 2: Εξαγωγή δεδομένων μέσω χειρισμού αναγνωριστικών

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

<?php
    $mysqli = new mysqli("localhost", "username", "password", "database");
    $id = intval($_GET['id']);
    $result = $mysqli->query("SELECT * FROM table WHERE id=$id");
    while ($row = $result->fetch_assoc()) {
        echo print_r($row, true);
    }
?>
php

Η αναμενόμενη διεύθυνση URL ακολουθεί το πρότυπο .../script.php?id=22. Σε αυτή την περίπτωση, θα ανακτηθεί η εγγραφή του πίνακα με το αναγνωριστικό «22». Εάν κάποιο μη εξουσιοδοτημένο άτομο έχει τη δυνατότητα να παραποιήσει αυτή τη διεύθυνση URL και στείλει αντ’ αυτού ένα αίτημα όπως .../script.php?id=22+OR+1=1, η προκύπτουσα ερώτηση θα οδηγήσει στην ανάκτηση όλων των σειρών του πίνακα:

SELECT * FROM table WHERE id=22 OR 1=1;
sql

Πώς εντοπίζουν οι εγκληματίες ευάλωτα συστήματα βάσεων δεδομένων;

Κατ’ αρχήν, κάθε ιστότοπος ή διαδικτυακή εφαρμογή που χρησιμοποιεί βάσεις δεδομένων SQL χωρίς προετοιμασμένες ερωτήσεις (prepared statements) ή άλλα προστατευτικά μέτρα μπορεί να είναι ευάλωτη σε επιθέσεις SQL injection. Οι ευπάθειες που εντοπίζονται δεν παραμένουν κρυφές για πολύ στο Διαδίκτυο. Στην πραγματικότητα, υπάρχουν ιστότοποι που δημοσιεύουν ενημερωμένους καταλόγους γνωστών κενών ασφαλείας — και μάλιστα εξηγούν πώς οι επιτιθέμενοι μπορούν να χρησιμοποιήσουν αναζητήσεις στο Google για να εντοπίσουν αντίστοιχα διαδικτυακά έργα. Εάν ένας ιστότοπος επιστρέφει λεπτομερή μηνύματα σφάλματος SQL, οι εγκληματίες του κυβερνοχώρου μπορούν να χρησιμοποιήσουν αυτά τα μηνύματα για να εντοπίσουν πιθανές ευπάθειες. Για παράδειγμα, η προσθήκη μιας απόστροφου στο τέλος μιας διεύθυνσης URL που περιλαμβάνει μια παράμετρο ID μπορεί ήδη να εκθέσει μια αδυναμία, όπως φαίνεται στο ακόλουθο παράδειγμα:

[DomainName].com/news.php?id=5’

Ένας ευάλωτος ιστότοπος επιστρέφει ένα μήνυμα σφάλματος με την ακόλουθη μορφή:

Query failed: You have an error in your SQL syntax…

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

Πώς να προστατεύσετε τη βάση δεδομένων σας από επιθέσεις SQL injection

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

Βήμα 1: Παρακολούθηση των αυτόματων εισροών από τις εφαρμογές

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

1. Επαλήθευση τύπων δεδομένων

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

if (filter_var($input, FILTER_VALIDATE_INT) === false) {
    throw new InvalidArgumentException("Invalid input");
}
php

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

2. Φιλτράρισμα ειδικών χαρακτήρων

Οι ειδικοί χαρακτήρες μπορούν να δημιουργήσουν κενά ασφαλείας, ειδικά σε περιβάλλοντα SQL ή HTML. Μια ασφαλής προσέγγιση είναι να χρησιμοποιείτε htmlspecialchars() για εισόδους HTML και PDO::quote() για ερωτήματα SQL.

3. Αποφύγετε την εμφάνιση μηνυμάτων σφάλματος

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

echo "An error occurred. Please try again later.";
error_log("Unexpected error encountered. See system log for details.");
php

4. Χρησιμοποιήστε προετοιμασμένες δηλώσεις

Ένας από τους πιο αποτελεσματικούς τρόπους για την πρόληψη των εισβολών SQL είναι η χρήση προετοιμασμένων δηλώσεων. Σε αυτή την προσέγγιση, οι εντολές SQL και οι παράμετροι αποστέλλονται ξεχωριστά, οπότε δεν είναι δυνατή η εκτέλεση κακόβουλου κώδικα. Ακολουθεί ένα παράδειγμα υλοποίησης σε PHP με χρήση PDO (PHP Data Objects):

$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->bindParam(':id', $user_id, PDO::PARAM_INT);
$stmt->execute();
php

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

Βήμα 2: Εξασφαλίστε ολοκληρωμένη προστασία του διακομιστή

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

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

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

  • Συστήματα ανίχνευσης εισβολών (IDS) και συστήματα πρόληψης εισβολών (IPS): Τα συστήματα αυτά χρησιμοποιούν διάφορες μεθόδους ανίχνευσης για τον έγκαιρο εντοπισμό επιθέσεων, την έκδοση ειδοποιήσεων και —στην περίπτωση των IPS— την αυτόματη εφαρμογή αντιμέτρων.
  • Πύλη επιπέδου εφαρμογών (ALG): Μια ALG παρακολουθεί και φιλτράρει την κίνηση μεταξύ εφαρμογών και προγραμμάτων περιήγησης ιστού απευθείας στο επίπεδο της εφαρμογής.
  • Τείχος προστασίας εφαρμογών ιστού (WAF): Ένα WAF προστατεύει συγκεκριμένα τις εφαρμογές ιστού από εισβολές SQL και Cross-Site Scripting (XSS), αποκλείοντας ή καθαρίζοντας ύποπτες αιτήσεις.
  • Προσέγγιση Zero Trust: Αυτό το σύγχρονο μοντέλο ασφάλειας διασφαλίζει ότι κάθε απόπειρα πρόσβασης — ανεξάρτητα από την προέλευσή της — επαληθεύεται και πιστοποιείται πριν χορηγηθεί η πρόσβαση.
  • Κανόνες τείχους προστασίας και τμηματοποίηση δικτύου: Αυτά είναι απαραίτητα για την ελαχιστοποίηση της επιφάνειας επίθεσης μακροπρόθεσμα.
  • Τακτικοί έλεγχοι ασφάλειας IT και δοκιμές διείσδυσης: Αυτά βοηθούν στον εντοπισμό και την επιδιόρθωση τρωτών σημείων σε πρώιμο στάδιο.

Βήμα 3: Ενισχύστε την ασφάλεια της βάσης δεδομένων και χρησιμοποιήστε ασφαλή κώδικα

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

Σύμφωνα με τις αρχές της χρήσης προετοιμασμένων δηλώσεων, συνιστάται ανεπιφύλακτα να μην χρησιμοποιείτε το module mysql της PHP (το οποίο καταργήθηκε στην PHP 7). Αντ’ αυτού, προτιμήστε mysqli ή το PDO για να εξασφαλίσετε καλύτερη ασφάλεια και συμβατότητα. Μια ασφαλής ερώτηση mysqli μπορεί να έχει την εξής μορφή:

$mysqli = new mysqli("localhost", "username", "password", "database");
if ($mysqli->connect_error) die("Connection failed");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$stmt->bind_result($hashedPassword);
if ($stmt->fetch() && password_verify($_POST['password'], $hashedPassword)) {
    echo "Login successful";
} else {
    echo "Invalid login credentials";
}
$stmt->close();
$mysqli->close();
php

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

$mysqli = new mysqli("localhost", "username", "password", "database");
$stmt = $mysqli->prepare("SELECT password FROM users WHERE username = ?");
$stmt->bind_param("s", $_POST['username']);
$stmt->execute();
$result = $stmt->get_result();
$row = $result->fetch_assoc();
if ($row && password_verify($_POST['password'], $row['password'])) {
    echo "Login successful!";
} else {
    echo "Incorrect username or password.";
}
php

Τι σχέση έχουν τα τραπεζάκια με την SQL injection;

Ο ιστότοπος bobby-tables.com χρησιμοποιεί ένα διαδικτυακό κόμικ του xkcd για να απεικονίσει με χιουμοριστικό τρόπο τους κινδύνους που ενέ χει η εισαγωγή μη ασφαλών δεδομένων από τους χρήστες στις βάσεις δεδομένων. Στο κόμικ, μια μητέρα λαμβάνει τηλεφώνημα από το σχολείο του γιου της (γνωστού με το χαϊδευτικό ψευδώνυμο «Little Bobby Tables»). Ο καλών τη ρωτάει αν ο γιος της ονομάζεται πραγματικά Robert'); DROP TABLE Students;--, και εκείνη απαντά ναι. Ο λόγος της κλήσης γίνεται σύντομα σαφής: η προσπάθεια εισαγωγής του ονόματος Robert στη βάση δεδομένων των μαθητών προκάλεσε τη διαγραφή ολόκληρου του πίνακα των μαθητών. Η μητέρα δεν δείχνει ιδιαίτερη συμπάθεια — απλώς ελπίζει ότι το σχολείο έχει πάρει το μάθημά του και θα καθαρίζει τις εισόδους στη βάση δεδομένων στο μέλλον.

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

Go to Main Menu