Το SQL Injection (SQLi) παραμένει, δεκαετίες μετά την πρώτη τεκμηρίωσή του, μία από τις πιο επικίνδυνες ευπάθειες σε εφαρμογές web. Σε αυτό το intermediate lab της Audax Cybersecurity αναλύουμε πώς λειτουργεί, ποιοι είναι οι βασικοί του τύποι (in-band, blind, out-of-band) και δουλεύουμε βήμα-βήμα ένα walkthrough εκμετάλλευσης — manual και με sqlmap — σε απομονωμένο εργαστήριο (DVWA), κλείνοντας με ανίχνευση και άμυνα. Όλα τα παραδείγματα προϋποθέτουν authorized testing σε isolated lab· κανένα πραγματικό target.
Εισαγωγή — γιατί το SQLi παραμένει κρίσιμο
Παρότι σήμερα υπάρχουν ώριμοι μηχανισμοί άμυνας, το SQL Injection εξακολουθεί να καταλαμβάνει σταθερά θέση στο OWASP Top 10 (στην κατηγορία Injection) και να αποτελεί βασικό διάνυσμα σε πραγματικά περιστατικά διαρροής δεδομένων. Ο λόγος είναι απλός: αρκεί ένα μεμονωμένο σημείο εισόδου (input) που καταλήγει χωρίς σωστό χειρισμό μέσα σε ένα SQL query, ώστε ένας επιτιθέμενος να αλλάξει τη λογική του ερωτήματος και να αποκτήσει πρόσβαση σε δεδομένα που δεν του ανήκουν — από ολόκληρους πίνακες χρηστών μέχρι, σε δυσμενείς περιπτώσεις, πρόσβαση στο ίδιο το λειτουργικό σύστημα του database server.
Το SQLi είναι επίσης ιδανικό εκπαιδευτικό θέμα: συνδυάζει κατανόηση του τρόπου που «σκέφτεται» μια βάση δεδομένων, με πρακτική μεθοδολογία επίθεσης και σαφείς, εφαρμόσιμες άμυνες. Σε αυτό το άρθρο του ethical hacking learning track θα δεις όλη τη διαδρομή. Όλα τα παραδείγματα εκτελούνται σε απομονωμένο εργαστήριο (isolated lab) όπως το DVWA ή τα sqli-labs, με ουδέτερα IP της μορφής 10.10.10.x. Δεν εκτελείς ποτέ αυτές τις τεχνικές εναντίον συστημάτων για τα οποία δεν έχεις ρητή, γραπτή άδεια.
Πώς δουλεύει το SQL Injection
Η ρίζα του προβλήματος είναι η ανάμειξη κώδικα και δεδομένων (mixing code & data). Όταν μια εφαρμογή χτίζει το SQL query συνενώνοντας (concatenation) απευθείας την είσοδο του χρήστη μέσα στο κείμενο του ερωτήματος, η βάση δεν μπορεί πλέον να ξεχωρίσει τι είναι εντολή και τι είναι δεδομένο.
Ας δούμε ένα κλασικό ευάλωτο παράδειγμα σε PHP:
// Ευάλωτος κώδικας — ΜΟΝΟ για εκπαιδευτική επίδειξη
$id = $_GET['id'];
$sql = "SELECT first_name, last_name FROM users WHERE id = '$id'";
$result = mysqli_query($conn, $sql);
Αν ο χρήστης στείλει id=1, το query γίνεται ... WHERE id = '1'. Αν όμως στείλει id=1' OR '1'='1, τότε μετατρέπεται σε:
SELECT first_name, last_name FROM users WHERE id = '1' OR '1'='1'
Η συνθήκη '1'='1' είναι πάντα αληθής (always true), οπότε η βάση επιστρέφει όλες τις εγγραφές του πίνακα αντί για μία. Αυτή η απλή αλλαγή στη λογική του ερωτήματος είναι η ουσία κάθε SQL Injection: ο επιτιθέμενος «σπάει» το context της συμβολοσειράς (με το ') και προσθέτει δικό του SQL.
Το πρώτο διαγνωστικό βήμα σε lab είναι το λεγόμενο break-and-repair: στέλνεις έναν χαρακτήρα που σπάει το query (ένα μονό εισαγωγικό ') και παρατηρείς αν προκύπτει σφάλμα ή αλλαγή συμπεριφοράς. Αν η βάση επιστρέψει μήνυμα λάθους MySQL, τότε το input φτάνει «ακατέργαστο» στη βάση — και το επόμενο βήμα είναι να «επιδιορθώσεις» το query με ένα payload που παραμένει έγκυρο συντακτικά. Παρακάτω βλέπουμε ακριβώς αυτό σε ελεγχόμενο DVWA lab: πρώτα το syntax error που επιβεβαιώνει την ευπάθεια, και έπειτα το ' OR '1'='1 που επιστρέφει όλους τους χρήστες.
Οι τύποι του SQL Injection
Το SQLi κατηγοριοποιείται με βάση το πώς ο επιτιθέμενος λαμβάνει πίσω τα αποτελέσματα (το exfiltration channel). Οι τρεις μεγάλες οικογένειες είναι: in-band, blind (inferential) και out-of-band.
In-band SQLi (error-based & union-based)
Στο in-band, τα αποτελέσματα επιστρέφονται μέσα στην ίδια απόκριση (response) της εφαρμογής. Είναι ο ευκολότερος και ταχύτερος τύπος για εκμετάλλευση, και χωρίζεται σε δύο υποκατηγορίες.
Error-based: Εκμεταλλεύεται τα μηνύματα σφάλματος της βάσης, τα οποία «διαρρέουν» πληροφορία (π.χ. ονόματα πινάκων ή τιμές). Σε MySQL, μια κλασική τεχνική είναι μέσω της συνάρτησης extractvalue:
1' AND extractvalue(1, concat(0x7e, (SELECT version()))) -- -
Το σύστημα επιστρέφει σφάλμα τύπου XPATH syntax error που περιέχει την έκδοση της βάσης. Το error-based είναι πολύτιμο όταν η εφαρμογή εμφανίζει verbose μηνύματα σφάλματος.
Union-based: Χρησιμοποιεί τον τελεστή UNION SELECT για να προσαρτήσει (append) τα αποτελέσματα ενός δικού μας ερωτήματος στα αποτελέσματα του αρχικού. Προϋπόθεση είναι να ταιριάζει ο αριθμός των στηλών (columns) και οι τύποι δεδομένων. Πρώτα βρίσκουμε τον αριθμό στηλών με ORDER BY:
1' ORDER BY 1 -- -
1' ORDER BY 2 -- -
1' ORDER BY 3 -- - (σφάλμα => υπάρχουν 2 στήλες)
Έπειτα εξάγουμε δεδομένα, π.χ. τα ονόματα χρηστών και τα password hashes, ή αντλούμε metadata από το information_schema για να χαρτογραφήσουμε τη δομή της βάσης:
1' UNION SELECT user, password FROM users -- -
1' UNION SELECT table_name, column_name FROM information_schema.columns -- -
Blind (Inferential) SQLi — boolean-based & time-based
Στο blind SQLi η εφαρμογή δεν επιστρέφει δεδομένα ή σφάλματα απευθείας. Ο επιτιθέμενος συνάγει (infers) την πληροφορία θέτοντας ερωτήσεις true/false και παρατηρώντας έμμεσα σημάδια. Είναι πιο αργό αλλά εξίσου αποτελεσματικό.
Boolean-based: Στέλνουμε συνθήκες που είναι αληθείς ή ψευδείς και παρατηρούμε αν αλλάζει η απόκριση (π.χ. εμφανίζεται ή όχι κάποιο περιεχόμενο).
1' AND 1=1 -- - (αληθές => κανονική σελίδα)
1' AND 1=2 -- - (ψευδές => διαφορετική σελίδα)
Πάνω σε αυτό, εξάγουμε δεδομένα χαρακτήρα-χαρακτήρα με συναρτήσεις όπως substring και ascii, χρησιμοποιώντας δυαδική αναζήτηση (binary search) για να βρούμε την ακριβή τιμή κάθε χαρακτήρα:
1' AND ascii(substring((SELECT database()),1,1)) > 100 -- -
Time-based: Όταν δεν υπάρχει καμία ορατή διαφορά στην απόκριση, χρησιμοποιούμε τον χρόνο ως κανάλι. Με τη SLEEP() (MySQL) κάνουμε τη βάση να καθυστερήσει όταν η συνθήκη είναι αληθής:
1' AND IF(ascii(substring((SELECT database()),1,1)) > 99, SLEEP(3), 0) -- -
Αν η απόκριση αργήσει ~3 δευτερόλεπτα, η συνθήκη ήταν αληθής. Παρακάτω βλέπουμε το time-based blind στην πράξη σε lab: μια baseline γρήγορη απόκριση, μια «αληθής» συνθήκη που ενεργοποιεί το SLEEP(3), και μια «ψευδής» που επιστρέφει άμεσα — αρκετά για να συμπεράνουμε τον πρώτο χαρακτήρα του ονόματος της βάσης.
Out-of-band (OOB) SQLi
Στο out-of-band, τα δεδομένα εξάγονται μέσω διαφορετικού καναλιού από αυτό της αίτησης — τυπικά μέσω DNS ή HTTP requests που ξεκινά η ίδια η βάση προς έναν server που ελέγχει ο tester. Χρησιμοποιείται όταν το κανάλι απόκρισης είναι εντελώς κλειστό αλλά η βάση επιτρέπει εξερχόμενη επικοινωνία. Σε SQL Server, για παράδειγμα, αυτό μπορεί να γίνει μέσω μηχανισμών όπως xp_dirtree προς ένα ελεγχόμενο (στο lab) DNS endpoint. Στην πράξη το OOB απαιτεί ειδικές συνθήκες και ελεγχόμενη υποδομή· γι’ αυτό στα εκπαιδευτικά labs επικεντρωνόμαστε κυρίως στα in-band και blind. Αξίζει ωστόσο να το γνωρίζεις, γιατί σε εξειδικευμένες αξιολογήσεις (σε εξουσιοδοτημένο πλαίσιο) το OOB είναι συχνά ο μόνος τρόπος να αποδείξεις την ύπαρξη ευπάθειας όταν κάθε άλλο κανάλι είναι φιμωμένο.
Μια χρήσιμη νοητική εικόνα: in-band = «σου απαντώ κατευθείαν», blind = «σου απαντώ με νεύματα ναι/όχι», out-of-band = «στέλνω την απάντηση από άλλη πόρτα». Η επιλογή τεχνικής εξαρτάται πάντα από το τι σου επιτρέπει να «δεις» η εφαρμογή-στόχος.
Προαπαιτούμενα & στήσιμο lab
Πριν ξεκινήσεις, χρειάζεσαι: βασική γνώση SQL (SELECT, WHERE, UNION), εξοικείωση με HTTP requests και ένα Kali (ή οποιοδήποτε Linux) με curl και sqlmap εγκατεστημένα. Στήνουμε ένα απομονωμένο εργαστήριο. Ο πιο απλός τρόπος είναι μέσω Docker, σε τοπικό μηχάνημα χωρίς η εφαρμογή-στόχος να είναι εκτεθειμένη στο διαδίκτυο:
docker run --rm -it -p 80:80 vulnerables/web-dvwa
# προσβάσιμο τοπικά στο lab ως http://10.10.10.50/
Στο DVWA ρυθμίζουμε το Security Level σε low για την πρώτη εξοικείωση και ανεβαίνουμε σταδιακά σε medium/high, όπου προστίθενται φίλτρα και token που κάνουν την εκμετάλλευση πιο ρεαλιστική. Πηγαίνουμε στη σελίδα SQL Injection, όπου υπάρχει ένα πεδίο User ID, και κρατάμε το session cookie (PHPSESSID + security=low) για τα requests μας. Τα sqli-labs είναι μια εξαιρετική συμπληρωματική επιλογή: μια σειρά από προοδευτικά challenges που καλύπτουν string/numeric contexts, GET/POST, error-based και blind σενάρια.
Πρακτική εκμετάλλευση βήμα-βήμα
Manual προσέγγιση
Ξεκινάμε πάντα με τον έλεγχο break-and-repair στέλνοντας ' — αν προκύψει σφάλμα, επιβεβαιώνουμε την ευπάθεια (το είδαμε ήδη στο πρώτο terminal shot). Στη συνέχεια εντοπίζουμε τον αριθμό στηλών με ORDER BY και, μόλις τον ξέρουμε, χτίζουμε το UNION payload για να εξάγουμε την έκδοση, το τρέχον database και τελικά τα credentials:
1' ORDER BY 3 -- - (=> 2 στήλες)
1' UNION SELECT version(), database() -- -
1' UNION SELECT user, password FROM users -- -
Παρακάτω βλέπουμε την πλήρη union-based αλυσίδα σε lab: τον προσδιορισμό στηλών, την εξαγωγή έκδοσης/βάσης, και τελικά το dump ονομάτων χρηστών με τα MD5 password hashes τους — όλα μέσα στην κανονική απόκριση της σελίδας.
Η manual εξάσκηση είναι κρίσιμη: σε καταλαβαίνει το «γιατί» πίσω από κάθε payload και σε προετοιμάζει για περιπτώσεις όπου τα αυτοματοποιημένα εργαλεία αποτυγχάνουν (π.χ. λόγω WAF ή ασυνήθιστου context).
Αυτοματοποίηση με sqlmap
Το sqlmap είναι το de facto εργαλείο για ανίχνευση και εκμετάλλευση SQLi. Σε lab περιβάλλον, με το session cookie του DVWA, ένα βασικό enumeration βάσεων μοιάζει έτσι:
sqlmap -u "http://10.10.10.50/vulnerabilities/sqli/?id=1&Submit=Submit" \
--cookie="PHPSESSID=8f2a...; security=low" \
--batch --dbs
Το sqlmap εντοπίζει αυτόματα ότι η παράμετρος id είναι injectable (error-based και UNION), αναγνωρίζει το DBMS και απαριθμεί τις διαθέσιμες βάσεις:
Αφού εντοπίσει τις βάσεις, στοχεύουμε συγκεκριμένο πίνακα και εξάγουμε (dump) τα δεδομένα. Το sqlmap αναγνωρίζει και «σπάει» αυτόματα γνωστά hashes με λεξικό:
sqlmap -u "http://10.10.10.50/vulnerabilities/sqli/?id=1&Submit=Submit" \
--cookie="PHPSESSID=8f2a...; security=low" \
-D dvwa -T users --dump --batch
Χρήσιμα flags για βαθύτερη ανάλυση σε lab: --technique=BEUST (επιλογή τεχνικών), --level και --risk (ένταση δοκιμών), και --tamper για δοκιμή bypass απλών φίλτρων. Θυμήσου: το sqlmap είναι θορυβώδες και μόνο για εξουσιοδοτημένους στόχους.
Ανίχνευση & Άμυνα
Η κατανόηση της επίθεσης έχει νόημα μόνο αν οδηγεί σε ισχυρή άμυνα. Η καλή είδηση είναι ότι το SQLi είναι μία από τις πιο προλήψιμες ευπάθειες.
Parameterized queries / Prepared statements
Η μοναδική πραγματικά αξιόπιστη άμυνα είναι ο διαχωρισμός κώδικα και δεδομένων μέσω parameterized queries (γνωστά και ως prepared statements). Η είσοδος του χρήστη περνά ως παράμετρος και δεν συνενώνεται ποτέ στο κείμενο του query:
// Ασφαλής εκδοχή σε PHP (PDO)
$stmt = $pdo->prepare("SELECT first_name, last_name FROM users WHERE id = ?");
$stmt->execute([$id]);
$rows = $stmt->fetchAll();
Εδώ, ό,τι κι αν στείλει ο χρήστης, αντιμετωπίζεται πάντα ως τιμή — ποτέ ως εκτελέσιμο SQL. Οι σύγχρονες βιβλιοθήκες και ORMs (π.χ. Hibernate, Entity Framework, Django ORM) το κάνουν αυτό εξ ορισμού, αρκεί να μην παρακάμπτεις τη λογική τους με raw queries.
Input validation & least privilege
Η επικύρωση εισόδου (input validation) με λευκές λίστες (allow-lists) — π.χ. να δέχεσαι μόνο ακέραιους εκεί που περιμένεις ID — μειώνει την επιφάνεια επίθεσης, αλλά είναι συμπληρωματική, όχι υποκατάστατο των prepared statements.
Παράλληλα, εφάρμοσε την αρχή του ελάχιστου προνομίου (least privilege): ο database user της εφαρμογής δεν πρέπει να έχει δικαιώματα DROP, FILE ή πρόσβαση σε άλλες βάσεις. Έτσι, ακόμη κι αν υπάρξει injection, ο αντίκτυπος περιορίζεται δραστικά.
WAF, error handling & monitoring
Ένα Web Application Firewall (WAF) (π.χ. ModSecurity με το OWASP CRS) προσφέρει ένα επιπλέον στρώμα (defense in depth) μπλοκάροντας γνωστά μοτίβα SQLi. Δεν είναι όμως πανάκεια — τα WAFs παρακάμπτονται με τεχνικές encoding/obfuscation, γι’ αυτό δεν αντικαθιστούν ποτέ τον ασφαλή κώδικα. Τέλος:
- Απενεργοποίησε τα verbose error messages στο production ώστε να μη διαρρέει πληροφορία (κόβει τα error-based).
- Κατέγραφε και παρακολούθησε (logging & monitoring) ασυνήθιστα queries και απότομες αυξήσεις σε σφάλματα βάσης — ένα time-based blind attack, για παράδειγμα, αφήνει χαρακτηριστικό αποτύπωμα σε καθυστερήσεις.
- Εκτέλεσε τακτικά authorized penetration testing και code review για να πιάνεις regressions πριν φτάσουν στην παραγωγή.
Βασικά συμπεράσματα
- Η ρίζα του SQLi είναι η ανάμειξη κώδικα και δεδομένων μέσω string concatenation στο query.
- In-band (error/union-based): γρήγορη εξαγωγή δεδομένων μέσα στην ίδια απόκριση.
- Blind (boolean/time-based): συμπερασματική εξαγωγή όταν δεν υπάρχει ορατή έξοδος· πιο αργή αλλά αποτελεσματική.
- Out-of-band: εξαγωγή μέσω εναλλακτικού καναλιού (DNS/HTTP) όταν όλα τα υπόλοιπα είναι κλειστά.
- Manual + sqlmap: η χειροκίνητη κατανόηση σε κάνει ικανό· το sqlmap επιταχύνει, αλλά μόνο σε εξουσιοδοτημένους στόχους.
- Prepared statements είναι η θεμελιώδης άμυνα· input validation, least privilege και WAF είναι συμπληρωματικά στρώματα.
- Πάντα σε isolated lab (DVWA/sqli-labs) και μόνο υπό authorized testing — τα payloads εδώ είναι εκπαιδευτικά, όχι για πραγματικό στόχο.
Από τη θεωρία στην πράξη. Η Audax Cybersecurity προσφέρει επαγγελματικές υπηρεσίες offensive security — penetration testing & offensive validation — ενώ για όσους ξεκινούν το ταξίδι τους στο ethical hacking, το #1 ελληνικό βιβλίο «Ethical Hacking — Η Κρυφή Γνώση» είναι ο ιδανικός οδηγός.
Θέλετε να επικυρώσετε την ασφάλειά σας στην πράξη;
Η Audax αποδεικνύει το ρίσκο με πραγματικά σενάρια επίθεσης — όχι απλώς λίστες ελέγχου.
Ζητήστε δωρεάν αξιολόγηση →




