Φαντάσου κάποιον να ξεγελά έναν επισκέπτη να πατήσει ένα link ενώ είναι συνδεδεμένος στον λογαριασμό της τράπεζάς του. Το link οδηγεί σε μια κρυφή φόρμα που, χωρίς να το ξέρει ο επισκέπτης, στέλνει στην τράπεζα αίτημα για μεταφορά χρημάτων. Η τράπεζα βλέπει ένα νόμιμο αίτημα από πιστοποιημένο χρήστη και το εκτελεί. Ο επιτιθέμενος μετακίνησε χρήματα από τον λογαριασμό του θύματος χωρίς να μάθει ποτέ τον κωδικό του.
Αυτό είναι το CSRF (Cross-Site Request Forgery): μια επίθεση όπου ο επιτιθέμενος ξεγελά το θύμα ώστε να στείλει άθελά του μια φόρμα ή ένα αίτημα σε άλλη ιστοσελίδα, όπου το θύμα είναι ήδη συνδεδεμένο.
Τι θα μάθεις: τι είναι οι επιθέσεις CSRF και πώς δουλεύουν, γιατί είναι τόσο επικίνδυνες ακόμα κι όταν υπάρχουν άλλα μέτρα ασφαλείας, πώς τα token CSRF τις εμποδίζουν και πώς να προστατέψεις τις φόρμες σου.
Τι είναι το CSRF;
Το CSRF (προφέρεται «σι-σερφ») σημαίνει Cross-Site Request Forgery. Είναι μια επίθεση που εκμεταλλεύεται το εξής: αν είσαι συνδεδεμένος σε μια ιστοσελίδα, ο browser σου εμπιστεύεται αυτόματα τη συνεδρία σου και την περιλαμβάνει σε κάθε αίτημα προς αυτή την ιστοσελίδα, ακόμα κι αν το αίτημα έρχεται από άλλη ιστοσελίδα.
Η επίθεση δουλεύει ξεγελώντας έναν συνδεδεμένο επισκέπτη να στείλει άθελά του μια φόρμα σε ιστοσελίδα όπου έχει λογαριασμό. Ο επιτιθέμενος δεν βλέπει τον κωδικό του θύματος. Δεν το χρειάζεται. Χρειάζεται μόνο το θύμα να είναι ήδη συνδεδεμένο, και μετά το ξεγελά να κάνει ένα αίτημα (όπως η αποστολή μιας κρυφής φόρμας) που κάνει κάτι που θέλει ο επιτιθέμενος.
Το CSRF διαφέρει από άλλες επιθέσεις, γιατί δεν χρειάζεται κλοπή διαπιστευτηρίων ή σπάσιμο κρυπτογράφησης. Εκμεταλλεύεται την εμπιστοσύνη του θύματος στην ιστοσελίδα. Το θύμα είναι ήδη πιστοποιημένο, οπότε η ιστοσελίδα εμπιστεύεται τα αιτήματα που φαίνεται να έρχονται από αυτό.
Πώς δουλεύουν οι επιθέσεις CSRF
Μια επίθεση CSRF γίνεται σε τρία βήματα.
Βήμα 1: Το θύμα είναι συνδεδεμένο στην ιστοσελίδα σου
Κάποιος επισκέπτεται την ιστοσελίδα σου και συνδέεται στον λογαριασμό του. Ο browser του έχει τώρα ένα ενεργό cookie συνεδρίας που αποδεικνύει ότι είναι πιστοποιημένος. Η συνεδρία μένει ενεργή όσο συνεχίζει να χρησιμοποιεί την ιστοσελίδα.
Βήμα 2: Ο επιτιθέμενος τον ξεγελά να μπει σε κακόβουλη σελίδα
Ενώ είναι ακόμα συνδεδεμένος στην ιστοσελίδα σου, το θύμα επισκέπτεται μια σελίδα που ελέγχει ο επιτιθέμενος (ίσως από ένα link στα social media, μια παραπλανητική διαφήμιση ή μια ιστοσελίδα που μοιάζει αξιόπιστη). Στη σελίδα υπάρχει κρυφός κώδικας που στέλνει μια φόρμα πίσω στην ιστοσελίδα σου.
Βήμα 3: Η φόρμα στέλνεται αυτόματα με τη συνεδρία του θύματος
Η κρυφή φόρμα στέλνεται στην ιστοσελίδα σου. Επειδή το θύμα είναι ήδη συνδεδεμένο, ο browser του περιλαμβάνει αυτόματα το cookie συνεδρίας στο αίτημα. Από τη δική σου φόρμα, αυτό είναι ένα νόμιμο αίτημα από πιστοποιημένο χρήστη. Η φόρμα το επεξεργάζεται σαν να το έστειλε σκόπιμα το θύμα.
Ο επιτιθέμενος έκανε τώρα κάτι στην ιστοσελίδα σου με τον λογαριασμό του θύματος, χωρίς να το ξέρει το θύμα. Μπορεί να άλλαξε τον κωδικό του, να μετέφερε χρήματα, να άλλαξε το προφίλ του ή να έστειλε στοιχεία.
Γιατί δουλεύει ακόμα κι όταν υπάρχουν άλλα μέτρα ασφαλείας
Οι επιθέσεις CSRF παρακάμπτουν αρκετά συνηθισμένα μέτρα ασφαλείας:
Το HTTPS δεν σταματά το CSRF. Τα δεδομένα κρυπτογραφούνται στη διαδρομή, αλλά ο επιτιθέμενος δεν χρειάζεται να τα υποκλέψει. Στέλνει απλώς το αίτημα από τον browser του θύματος, που ήδη τον εμπιστεύεται.
Η προστασία με κωδικό δεν σταματά το CSRF. Ο επιτιθέμενος δεν χρειάζεται ποτέ τον κωδικό του θύματος. Εκμεταλλεύεται απλώς το ότι το θύμα είναι ήδη συνδεδεμένο.
Ένα ισχυρό σύστημα σύνδεσης δεν σταματά το CSRF. Ακόμα κι αν η πιστοποίηση είναι τέλεια, αν το θύμα είναι συνδεδεμένο, η επίθεση δουλεύει.
Γι' αυτό η προστασία CSRF είναι ξεχωριστό επίπεδο. Δεν καλύπτεται από άλλα μέτρα ασφαλείας. Πρέπει να σχεδιάσεις τις φόρμες ειδικά ώστε να αντέχουν στις επιθέσεις CSRF.
Token CSRF: πώς σταματούν την επίθεση
Η λύση είναι ένα token CSRF. Είναι ένα μοναδικό, απρόβλεπτο κείμενο που δημιουργεί ο server σου για κάθε φόρμα. Να πώς δουλεύει:
Ο server σου δημιουργεί ένα μοναδικό token για κάθε επισκέπτη
Όταν κάποιος φορτώνει μια σελίδα με φόρμα, ο server σου δημιουργεί ένα τυχαίο token και το συνδέει με τη συνεδρία αυτού του χρήστη. Το token είναι διαφορετικό κάθε φορά και μοναδικό για τον συγκεκριμένο χρήστη.
Το token μπαίνει μέσα στη φόρμα
Το token περιλαμβάνεται ως κρυφό πεδίο στη φόρμα HTML. Όταν ο επισκέπτης στέλνει τη φόρμα, το token ταξιδεύει μαζί της.
Ο server σου επαληθεύει το token πριν επεξεργαστεί την υποβολή
Όταν στέλνεται η φόρμα, ο server σου ελέγχει αν το token της υποβολής ταιριάζει με το token που δημιούργησες για τη συνεδρία αυτού του χρήστη. Αν ναι, η φόρμα επεξεργάζεται. Αν όχι (ή αν δεν υπάρχει token), η φόρμα απορρίπτεται.
Η κρυφή φόρμα του επιτιθέμενου δεν μπορεί να περιέχει έγκυρο token, γιατί τα token είναι απρόβλεπτα και μοναδικά για κάθε συνεδρία. Ένας επιτιθέμενος σε άλλο domain δεν μπορεί να δει ούτε να μαντέψει το token. Έτσι η επίθεσή του αποτυγχάνει. Η κρυφή φόρμα στέλνεται, αλλά ο server σου την απορρίπτει επειδή το token δεν ταιριάζει.
Πώς μοιάζει ένα token CSRF στην πράξη
Σε HTML, μια φόρμα με προστασία CSRF μοιάζει έτσι:
<form method="POST" action="/submit-form"> <input type="hidden" name="csrf_token" value="a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"> <input type="email" name="email" placeholder="Το email σου"> <button type="submit">Υποβολή</button> </form> Το πεδίο `csrf_token` είναι κρυφό. Ο επισκέπτης δεν το βλέπει, αλλά στέλνεται μαζί με τα στοιχεία της φόρμας. Ο server σου το ελέγχει πριν επεξεργαστεί το email ή οποιοδήποτε άλλο στοιχείο.
Προστασία CSRF για διαφορετικούς τύπους φόρμας
Παραδοσιακές φόρμες HTML
Οι κλασικές φόρμες HTML (αυτές που στέλνουν δεδομένα με POST στον server σου) χρειάζονται token CSRF. Εδώ μπαίνουν οι φόρμες επικοινωνίας, οι φόρμες σύνδεσης, οι φόρμες επαναφοράς κωδικού και κάθε φόρμα που αλλάζει δεδομένα στον server σου.
Φόρμες AJAX και JavaScript
Οι φόρμες που στέλνονται με JavaScript σε ένα endpoint API χρειάζονται κι αυτές προστασία CSRF. Το token μπορεί να μπει μέσα στη φόρμα, να αποθηκευτεί σε cookie ή να διαβαστεί από ένα meta tag πριν σταλεί το αίτημα.
Αιτήματα API χωρίς κατάσταση
Αν το API σου χρησιμοποιεί πιστοποίηση με token (όπως το JWT), η προστασία CSRF δουλεύει διαφορετικά. Ο browser δεν μπορεί να επισυνάψει αυτόματα ένα token JWT όπως επισυνάπτει ένα cookie συνεδρίας, οπότε το κλασικό CSRF είναι μικρότερη απειλή. Η καλή πρακτική όμως είναι να προσθέτεις και ένα token CSRF για επιπλέον προστασία.
Άλλες προστασίες που δουλεύουν μαζί με τα token CSRF
Τα token CSRF είναι η βασική άμυνα, αλλά δουλεύουν καλύτερα μαζί με άλλες πρακτικές ασφαλείας.
Cookies SameSite
Όταν ορίζεις ένα cookie συνεδρίας, μπορείς να προσθέσεις το χαρακτηριστικό `SameSite`, που λέει στον browser να μην περιλαμβάνει το cookie όταν το αίτημα έρχεται από άλλο domain. Έτσι η κρυφή φόρμα του επιτιθέμενου δεν μπορεί να χρησιμοποιήσει καθόλου τη συνεδρία του θύματος.
Έλεγχοι της κεφαλίδας Referer
Ο server σου μπορεί να ελέγξει την κεφαλίδα Referer για να δει από πού ήρθε το αίτημα. Αν μια υποβολή φόρμας δηλώνει ότι έρχεται από το domain σου, αλλά το Referer δείχνει άλλο domain, μάλλον πρόκειται για επίθεση. (Οι κεφαλίδες Referer όμως μπορούν να πλαστογραφηθούν, οπότε δεν είναι πλήρης άμυνα.)
Μοτίβο double-submit cookie
Σε αυτή την προσέγγιση, το token CSRF αποθηκεύεται και σε cookie και σε πεδίο φόρμας. Ο server σου ελέγχει ότι ταιριάζουν πριν επεξεργαστεί το αίτημα. Είναι λιγότερο συνηθισμένο από τα κλασικά token, αλλά δουλεύει καλά σε εφαρμογές χωρίς κατάσταση.
Πώς να υλοποιήσεις προστασία CSRF
Οι λεπτομέρειες εξαρτώνται από την τεχνολογία σου, αλλά το μοτίβο είναι το ίδιο:
- Δημιούργησε ένα μοναδικό token ανά συνεδρία. Όταν ένας χρήστης ξεκινά συνεδρία ή φορτώνει σελίδα με φόρμα, το backend σου δημιουργεί νέο token.
- Αποθήκευσε το token στον server. Κράτα το συνδεδεμένο με τη συνεδρία αυτού του χρήστη.
- Βάλε το token στη φόρμα. Πρόσθεσέ το ως κρυφό πεδίο στο HTML ή ως meta tag που μπορεί να διαβάσει η JavaScript.
- Επαλήθευσε κατά την υποβολή. Πριν επεξεργαστείς οποιοδήποτε στοιχείο της φόρμας, έλεγξε ότι το token που στάλθηκε ταιριάζει με το αποθηκευμένο token της συνεδρίας.
- Δημιούργησε νέο token μετά από ευαίσθητες ενέργειες. Αφού ο χρήστης αλλάξει κωδικό ή κάνει κάτι κρίσιμο, δημιούργησε καινούργιο token.
Τα περισσότερα σύγχρονα frameworks (Django, Rails, Laravel, ASP.NET) διαχειρίζονται αυτόματα τη δημιουργία και την επαλήθευση των token CSRF. Αν χρησιμοποιείς framework, η προστασία CSRF συνήθως είναι ενεργή από προεπιλογή. Απλώς φρόντισε να μην την απενεργοποιήσεις κατά λάθος.
Συνηθισμένα λάθη που αφήνουν τις φόρμες ευάλωτες
Απενεργοποίηση της προστασίας CSRF για ευκολία. Κάποιοι προγραμματιστές κλείνουν τους ελέγχους CSRF για να κάνουν πιο εύκολες τις δοκιμές API ή για να απλοποιήσουν τον κώδικα. Μην το κάνεις. Δημιουργεί πραγματική ευπάθεια.
Στατικό token για όλους τους χρήστες. Το token πρέπει να είναι μοναδικό για τη συνεδρία κάθε χρήστη. Ένα token που είναι ίδιο για όλους (ή ίδιο για όλες τις μέρες) δεν προστατεύει από CSRF.
Δεν ανανεώνεις τα token. Αν χρησιμοποιείς το ίδιο token για εβδομάδες, ο επιτιθέμενος έχει περισσότερο χρόνο να το εκμεταλλευτεί. Ανανέωνε τα token τακτικά και πάντα μετά από ευαίσθητες λειτουργίες.
Βασίζεσαι μόνο σε cookies SameSite. Το SameSite βοηθά, αλλά δεν αρκεί. Χρησιμοποίησε τα token CSRF ως βασική άμυνα και το SameSite ως εφεδρική.
Ξεχνάς τα token σε κάποιες φόρμες. Αν προστατεύεις κάποιες φόρμες με token και άλλες όχι, οι επιτιθέμενοι θα χρησιμοποιήσουν τις απροστάτευτες. Κάθε φόρμα που αλλάζει δεδομένα χρειάζεται προστασία.
Φόρμες στον δημιουργό ιστοσελίδων του WEMASY
Ο δημιουργός ιστοσελίδων του WEMASY σου επιτρέπει να φτιάξεις δικές σου σελίδες στην ιστοσελίδα σου, και μπορείς να προσθέσεις μια φόρμα στον δημιουργό ιστοσελίδων. Όσα διάβασες σε αυτόν τον οδηγό ισχύουν για κάθε φόρμα που φτιάχνεις.
Δες τα πακέτα στη σελίδα τιμών.