Αυτό το άρθρο είναι το πρώτο σε μια σειρά αναρτήσεων που γράφω σχετικά με τη λειτουργία διαφόρων προϊόντων και ιστότοπων SaaS τα τελευταία 8 χρόνια. Θα μοιραστώ μερικά από τα θέματα που έχω αντιμετωπίσει, τα μαθήματα που έχω μάθει, τα λάθη που έχω κάνει και ίσως μερικά πράγματα που πήγαν σωστά. Επιτρέψτε μου να ξέρω τι νομίζεις!
Πίσω το 2019 ή το 2020, είχα αποφασίσει να ξαναγράψω ολόκληρο το backend για Αποκλεισμός αποστολέα, μια εφαρμογή SaaS που βοηθά τους χρήστες να δημιουργήσουν καλύτερα μπλοκ email, μεταξύ άλλων λειτουργιών. Στη διαδικασία, πρόσθεσα μερικές νέες δυνατότητες και αναβάθμισα σε πολύ πιο σύγχρονες τεχνολογίες. Έκανα τις δοκιμές, ανέπτυξα τον κώδικα, δοκίμασα με μη αυτόματο τρόπο τα πάντα στην παραγωγή και εκτός από μερικές τυχαίες πιθανότητες και τελικά, όλα φαινόταν να λειτουργούν τέλεια. Μακάρι να ήταν αυτό το τέλος της ιστορίας, αλλά…
Λίγες εβδομάδες αργότερα, ειδοποιήθηκα από έναν πελάτη (κάτι που είναι από μόνο του ντροπιαστικό) ότι η υπηρεσία δεν λειτουργούσε και λάμβαναν πολλά μηνύματα ηλεκτρονικού ταχυδρομείου που έπρεπε να αποκλειστούν στα εισερχόμενά τους, γι' αυτό το ερεύνησα. Πολλές φορές αυτό το πρόβλημα οφείλεται στο ότι η Google αφαιρεί τη σύνδεση από την υπηρεσία μας στον λογαριασμό του χρήστη, την οποία το σύστημα χειρίζεται ειδοποιώντας τον χρήστη μέσω email και ζητώντας του να επανασυνδεθεί, αλλά αυτή τη φορά ήταν κάτι άλλο.
Φαινόταν ότι ο εργάτης υποστήριξης που χειρίζεται τον έλεγχο των μηνυμάτων ηλεκτρονικού ταχυδρομείου έναντι των μπλοκ χρηστών συνέχιζε να συντρίβεται κάθε 5-10 λεπτά. Το πιο περίεργο μέρος - δεν υπήρχαν σφάλματα στα αρχεία καταγραφής, η μνήμη ήταν καλή, αλλά η CPU περιστασιακά αυξανόταν σε φαινομενικά τυχαίες στιγμές. Έτσι, για τις επόμενες 24 ώρες (με ένα διάλειμμα 3 ωρών για ύπνο - συγγνώμη πελάτες 😬), έπρεπε να επανεκκινήσω χειροκίνητα τον εργαζόμενο κάθε φορά που κολλούσε. Για κάποιο λόγο, η υπηρεσία Elastic Beanstalk περίμενε πάρα πολύ για επανεκκίνηση, γι' αυτό έπρεπε να το κάνω χειροκίνητα.
Ο εντοπισμός σφαλμάτων στην παραγωγή είναι πάντα ένας πόνος, ειδικά επειδή δεν μπορούσα να αναπαράγω το ζήτημα τοπικά, πόσο μάλλον να καταλάβω τι το προκάλεσε. Έτσι, όπως κάθε «καλός» προγραμματιστής, μόλις άρχισα να καταγράφω πάντα και περίμενε να χτυπήσει ξανά ο διακομιστής. Δεδομένου ότι η CPU ανέβαινε περιοδικά, κατάλαβα ότι δεν ήταν πρόβλημα μακροεντολής (όπως όταν εξαντληθεί η μνήμη) και πιθανότατα προκλήθηκε από ένα συγκεκριμένο email ή χρήστη. Προσπάθησα λοιπόν να το περιορίσω:
- Έσπασε σε ένα συγκεκριμένο αναγνωριστικό ή τύπο email;
- Ήταν συντριβή για έναν δεδομένο πελάτη;
- Συντριβή σε κάποιο τακτικό διάστημα;
Μετά από ώρες από αυτό, και κοιτάζοντας κούτσουρα περισσότερο από όσο θα ήθελα, τελικά, το περιόρισα σε έναν συγκεκριμένο πελάτη. Από εκεί, ο χώρος αναζήτησης μειώθηκε αρκετά – πιθανότατα ήταν ένας κανόνας αποκλεισμού ή ένα συγκεκριμένο email που ο διακομιστής μας συνέχιζε να προσπαθεί ξανά. Ευτυχώς για μένα, ήταν το πρώτο, το οποίο είναι ένα πολύ πιο εύκολο πρόβλημα στον εντοπισμό σφαλμάτων, δεδομένου ότι είμαστε μια εταιρεία που εστιάζει πολύ στο απόρρητο και δεν αποθηκεύουμε ή προβάλλουμε δεδομένα email.
Πριν μπούμε στο ακριβές πρόβλημα, ας μιλήσουμε πρώτα για μια από τις δυνατότητες του Block Sender. Εκείνη την εποχή είχα πολλούς πελάτες που ζητούσαν αποκλεισμό με χαρακτήρες μπαλαντέρ, κάτι που θα τους επέτρεπε να αποκλείσουν ορισμένους τύπους διευθύνσεων email που ακολουθούσαν το ίδιο μοτίβο. Για παράδειγμα, εάν θέλετε να αποκλείσετε όλα τα μηνύματα ηλεκτρονικού ταχυδρομείου από διευθύνσεις ηλεκτρονικού ταχυδρομείου μάρκετινγκ, θα μπορούσατε να χρησιμοποιήσετε τον χαρακτήρα μπαλαντέρ marketing@*
και θα μπλοκάρει όλα τα email από οποιαδήποτε διεύθυνση που ξεκίνησε με marketing@
.
Ένα πράγμα που δεν σκέφτηκα είναι ότι δεν καταλαβαίνουν όλοι πώς λειτουργούν οι μπαλαντέρ. Υπέθεσα ότι οι περισσότεροι άνθρωποι θα τα χρησιμοποιούσαν με τον ίδιο τρόπο που κάνω εγώ ως προγραμματιστής, χρησιμοποιώντας έναν *
να αντιπροσωπεύει οποιονδήποτε αριθμό χαρακτήρων. Δυστυχώς, ο συγκεκριμένος χρήστης είχε υποθέσει ότι έπρεπε να το χρησιμοποιήσετε ένας χαρακτήρας μπαλαντέρ για κάθε χαρακτήρα που θέλετε να ταιριάξετε. Στην περίπτωσή τους, ήθελαν να αποκλείσουν όλα τα μηνύματα ηλεκτρονικού ταχυδρομείου από έναν συγκεκριμένο τομέα (η οποία είναι μια εγγενής δυνατότητα που έχει το Block Sender, αλλά δεν πρέπει να το έχουν συνειδητοποιήσει, κάτι που είναι από μόνο του ένα ολόκληρο πρόβλημα). Αντί λοιπόν να χρησιμοποιήσετε *@example.com
, χρησιμοποίησαν **********@example.com
.
POV: Παρακολουθώντας τους χρήστες σας να χρησιμοποιούν την εφαρμογή σας…
Για να χειριστούμε χαρακτήρες μπαλαντέρ στον διακομιστή εργαζομένων μας, χρησιμοποιούμε τη βιβλιοθήκη Node.js ταιριαστή, που βοηθά στην αντιστοίχιση σφαιρών μετατρέποντάς την σε κανονική έκφραση. Αυτή η βιβλιοθήκη θα γύριζε τότε **********@example.com
σε κάτι σαν το ακόλουθο regex:
/[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*[sS]*@example.com/i
Εάν έχετε κάποια εμπειρία με το regex, γνωρίζετε ότι μπορεί να γίνουν πολύ περίπλοκα πολύ γρήγορα, ειδικά σε υπολογιστικό επίπεδο. Η αντιστοίχιση της παραπάνω έκφρασης σε οποιοδήποτε εύλογο μήκος κειμένου γίνεται πολύ υπολογιστικά ακριβή, γεγονός που κατέληξε να συνδέει τη CPU στον διακομιστή εργαζομένων μας. Αυτός είναι ο λόγος για τον οποίο ο διακομιστής θα κολλούσε κάθε λίγα λεπτά. θα κολλούσε προσπαθώντας να αντιστοιχίσει μια σύνθετη τυπική έκφραση με μια διεύθυνση email. Έτσι, κάθε φορά που αυτός ο χρήστης λάμβανε ένα μήνυμα ηλεκτρονικού ταχυδρομείου, εκτός από όλες τις επαναλήψεις που ενσωματώσαμε για να χειριστούμε προσωρινές αποτυχίες, θα κατέρρεε τον διακομιστή μας.
Λοιπόν, πώς το διόρθωσα αυτό; Προφανώς, η γρήγορη λύση ήταν να βρείτε όλα τα μπλοκ με πολλαπλούς χαρακτήρες μπαλαντέρ διαδοχικά και να τα διορθώσετε. Αλλά χρειαζόταν επίσης να κάνω καλύτερη δουλειά για την απολύμανση των εισροών των χρηστών. Οποιοσδήποτε χρήστης θα μπορούσε να εισαγάγει ένα regex και να καταργήσει ολόκληρο το σύστημα με ένα Επίθεση ReDoS.
Ρίξτε μια ματιά στον πρακτικό μας οδηγό για την εκμάθηση του Git, με βέλτιστες πρακτικές, πρότυπα αποδεκτά από τον κλάδο και συμπεριλαμβανόμενο φύλλο εξαπάτησης. Σταματήστε τις εντολές του Git στο Google και πραγματικά μαθαίνουν το!
Ο χειρισμός αυτής της συγκεκριμένης περίπτωσης ήταν αρκετά απλός - αφαιρέστε διαδοχικούς χαρακτήρες μπαλαντέρ:
block = block.replace(/*+/g, '*')
Αλλά αυτό εξακολουθεί να αφήνει την εφαρμογή ανοιχτή σε άλλους τύπους επιθέσεων ReDoS. Ευτυχώς, υπάρχουν πολλά πακέτα/βιβλιοθήκες που μας βοηθούν και με αυτούς τους τύπους:
Χρησιμοποιώντας έναν συνδυασμό των παραπάνω λύσεων και άλλων διασφαλίσεων, μπόρεσα να αποτρέψω αυτό να συμβεί ξανά. Αλλά ήταν μια καλή υπενθύμιση ότι δεν μπορείτε ποτέ να εμπιστευτείτε τα στοιχεία των χρηστών και θα πρέπει πάντα να τα απολυμαίνετε πριν τα χρησιμοποιήσετε στην εφαρμογή σας. Δεν ήξερα καν ότι αυτό ήταν ένα πιθανό ζήτημα έως ότου συνέβη σε μένα, οπότε ελπίζω ότι αυτό θα βοηθήσει κάποιον άλλο να αποφύγει το ίδιο πρόβλημα.
Έχετε ερωτήσεις, σχόλια ή θέλετε να μοιραστείτε μια δική σας ιστορία; Απλώστε το χέρι σας Twitter!
- SEO Powered Content & PR Distribution. Ενισχύστε σήμερα.
- PlatoData.Network Vertical Generative Ai. Ενδυναμώστε τον εαυτό σας. Πρόσβαση εδώ.
- PlatoAiStream. Web3 Intelligence. Ενισχύθηκε η γνώση. Πρόσβαση εδώ.
- PlatoESG. Ανθρακας, Cleantech, Ενέργεια, Περιβάλλον, Ηλιακός, Διαχείριση των αποβλήτων. Πρόσβαση εδώ.
- PlatoHealth. Ευφυΐα βιοτεχνολογίας και κλινικών δοκιμών. Πρόσβαση εδώ.
- πηγή: https://stackabuse.com/behind-the-scenes-never-trust-user-input/
- :έχει
- :είναι
- :δεν
- $UP
- 1
- 20
- 2019
- 2020
- 24
- 8
- a
- Ικανός
- Σχετικα
- πάνω από
- Λογαριασμός
- πραγματικά
- προστιθέμενη
- Επιπλέον
- διεύθυνση
- διευθύνσεις
- πάλι
- κατά
- Όλα
- επιτρέπουν
- alone
- Επίσης
- πάντοτε
- μεταξύ των
- an
- και
- κάθε
- app
- Εφαρμογή
- ΕΙΝΑΙ
- άρθρο
- AS
- ζητώντας
- υποτίθεται
- At
- Επιθέσεις
- αποφύγετε
- επίγνωση
- Backend
- BE
- Beanstalk
- γίνεται
- ήταν
- πριν
- πίσω
- στα παρασκήνια
- είναι
- Καλύτερα
- Κομμάτι
- Αποκλεισμός
- κλείδωμα
- Μπλοκ
- σύνορο
- Διακοπή
- χτισμένο
- αλλά
- by
- CAN
- Μπορεί να πάρει
- ο οποίος
- περίπτωση
- προκαλούνται
- προκαλώντας
- ορισμένες
- χαρακτήρας
- χαρακτήρες
- έλεγχος
- κωδικός
- συνδυασμός
- σχόλια
- εταίρα
- συγκρότημα
- περίπλοκος
- υπολογιστική
- σύνδεση
- διορθώσει
- θα μπορούσε να
- δεν μπορούσα
- Crash
- Συντρίφτηκε
- Συντριβή
- δημιουργία
- πελάτης
- Πελάτες
- ημερομηνία
- μοιράστηκε
- αποφάσισε
- αναπτυχθεί
- Εργολάβος
- DID
- didn
- do
- τομέα
- Don
- κάτω
- δυο
- κάθε
- ευκολότερη
- αλλιώς
- ΗΛΕΚΤΡΟΝΙΚΗ ΔΙΕΥΘΥΝΣΗ
- τέλος
- έληξε
- τελειώνει
- εισάγετε
- Ολόκληρος
- λάθη
- ειδικά
- Even
- τελικά
- Κάθε
- όλοι
- πάντα
- παράδειγμα
- ακριβά
- εμπειρία
- έκφραση
- αποτυχίες
- αρκετά
- μακριά
- Χαρακτηριστικό
- Χαρακτηριστικά
- λίγοι
- Εικόνα
- σχηματικός
- Εύρεση
- τέλος
- Όνομα
- σταθερός
- Συγκέντρωση
- ακολουθείται
- Εξής
- Για
- Πρώην
- από
- παίρνω
- να πάρει
- gif
- Git
- δεδομένου
- καλός
- εξαιρετική
- καθοδηγήσει
- είχε
- λαβή
- Handles
- hands-on
- συνέβη
- Συμβαίνει
- Έχω
- βοήθεια
- βοηθά
- Ας ελπίσουμε ότι
- ΩΡΕΣ
- φτερουγίζω
- Πως
- HTTPS
- i
- ID
- if
- in
- περιλαμβάνονται
- εισαγωγή
- αντί
- σε
- ζήτημα
- θέματα
- IT
- εαυτό
- Δουλειά
- μόλις
- διατηρούνται
- Ξέρω
- Επίθετο
- αργότερα
- μάθει
- μάθηση
- Μήκος
- Μαθήματα
- ας
- Επίπεδο
- LG
- Βιβλιοθήκη
- Μου αρέσει
- Πιθανός
- ll
- τοπικά
- ξύλευση
- Μακριά
- πλέον
- κοίταξε
- πλήθος
- Macro
- που
- χειροκίνητα
- πολοί
- Μάρκετινγκ
- Ταίριασμα
- ταιριάζουν
- μπορεί
- me
- Μνήμη
- Λεπτ.
- λάθη
- ΜΟΝΤΕΡΝΑ
- σύγχρονες τεχνολογίες
- περισσότερο
- πλέον
- πολύ
- πολλαπλούς
- πρέπει
- στενός
- ντόπιος
- που απαιτούνται
- ποτέ
- Νέα
- Νέες δυνατότητες
- επόμενη
- Όχι.
- κόμβος
- Node.js
- κοινοποιώντας
- αριθμός
- Πιθανότητα
- of
- on
- ONE
- ανοίξτε
- or
- ΑΛΛΑ
- δικός μας
- έξω
- δική
- Πόνος
- μέρος
- Ειδικότερα
- πρότυπο
- People
- Πλάτων
- Πληροφορία δεδομένων Plato
- Πλάτωνα δεδομένα
- Δημοσιεύσεις
- δυναμικού
- Πρακτικός
- πρόληψη
- πιθανώς
- Πρόβλημα
- διαδικασια μας
- παραγωγή
- Προϊόντα
- Ερωτήσεις
- Γρήγορα
- γρήγορα
- αρκετά
- τυχαίος
- RE
- φθάσουν
- συνειδητοποίησα
- λόγος
- λογικός
- έλαβε
- επανασύνδεση
- ρεγεξ
- τακτικός
- υπενθύμιση
- αφαιρέστε
- αφαίρεση
- εκπροσωπώ
- δεξιά
- Δαχτυλίδι
- Άρθρο
- τρέξιμο
- τρέξιμο
- s
- SaaS
- διασφαλίσεις
- ίδιο
- Σκηνές
- Αναζήτηση
- φαινόταν
- φαινομενικώς
- αποστέλλει
- Σειρές
- διακομιστής
- υπηρεσία
- σκιά
- Κοινοποίηση
- μοιράζονται
- σεντόνι
- θα πρέπει να
- Απλούς
- αφού
- ύπνος
- So
- Λύσεις
- μερικοί
- Κάποιος
- κάτι
- Χώρος
- συγκεκριμένες
- ακίδα
- Stackabuse
- πρότυπα
- ξεκίνησε
- Ακόμη
- στάση
- κατάστημα
- Ιστορία
- σύστημα
- Πάρτε
- Συζήτηση
- Τεχνολογίες
- προσωρινή
- δοκιμαστεί
- δοκιμές
- κείμενο
- από
- ότι
- Η
- τους
- Τους
- τότε
- Εκεί.
- Αυτοί
- αυτοί
- πράγμα
- πράγματα
- νομίζω
- αυτό
- ώρα
- φορές
- προς την
- πολύ
- μετάβαση
- Προσπάθησα
- Εμπιστευθείτε
- προσπαθώντας
- ΣΤΡΟΦΗ
- Στροφή
- τύπος
- τύποι
- καταλαβαίνει
- Δυστυχώς
- μέχρι
- αναβαθμιστεί
- us
- χρήση
- μεταχειρισμένος
- Χρήστες
- Χρήστες
- χρησιμοποιώντας
- διάφορα
- Ve
- πολύ
- μέσω
- Δες
- Αναμονή
- θέλω
- ήθελε
- ήταν
- δεν ήταν
- παρακολουθείτε
- Τρόπος..
- we
- ιστοσελίδες
- Εβδ.
- ΛΟΙΠΌΝ
- πήγε
- ήταν
- Τι
- πότε
- Ποιό
- ολόκληρο
- WHY
- Wikipedia
- επιθυμώ
- με
- Εργασία
- εργάτης
- εργαζόμενος
- θα
- γραφή
- χρόνια
- Εσείς
- Σας
- zephyrnet