Στην ανάπτυξη λογισμικού, οι συνθήκες ανταγωνισμού είναι ένα σφάλμα που προκαλείται εάν η κατάσταση ενός συστήματος τροποποιηθεί μεταξύ της χρονικής στιγμής κατά την οποία μία συνθήκη ελέγχεται από μία διεργασία και της χρονικής στιγμής πραγματοποίησης μίας ενέργειας από την ίδια διεργασία βάσει του ελέγχου που προηγήθηκε.[1]
Οι συνθήκες ανταγωνισμού είναι συνήθεις στην οικογένεια λειτουργικών συστημάτων Unix σε διεργασίες που αφορούν το σύστημα αρχείων, αλλά μπορούν να προκύψουν και σε άλλα πλαίσια, όπως για παράδειγμα, κατά τη διάρκεια συναλλαγών με μία βάση δεδομένων. Σύγχρονο παράδειγμα αποτελεί μία συνθήκη ανταγωνισμού που είναι παρούσα από το 2019 στην πλατφόρμα λογισμικού Docker και επιτρέπει σε έναν επιτιθέμενο να αποκτήσει προνόμια διαχειριστή στο σύστημα αρχείων της κεντρικής πλατφόρμας φιλοξενίας.[2]
Στο Unix, ο ακόλουθος κώδικας C εμπεριέχει μία συνθήκη ανταγωνισμού όταν εκτελείται από ένα setuid
πρόγραμμα:
if (access("file", W_OK) != 0) {
exit(1);
}
fd = open("file", O_WRONLY);
write(fd, buffer, sizeof(buffer));
Η συνάρτηση access
ελέγχει εάν ο χρήστης που εκτέλεσε το εν λόγω πρόγραμμα έχει δικαιώματα γραφής στο αρχείο ονόματι file.
if (access("file", W_OK) != 0) {
exit(1);
}
fd = open("file", O_WRONLY);
// Στην πραγματικότητα γράφουμε στο αρχείο /etc/passwd
write(fd, buffer, sizeof(buffer));
|
//
//
// Μετά τον έλεγχο πρόσβασης
//symlink("/etc/passwd", "file");
// Πρίν το άνοιγμα του αρχείου, το "file"
// δείχνει στο αρχείο "etc/passwd"
//
|
Εδώ, ο επιτιθέμενος δύναται να εκμεταλλευτεί την συνθήκη ανταγωνισμού που εμφανίζεται ανάμεσα στον χρόνο ελέγχου (συνάρτηση access
) και τον χρόνο εκτέλεσης (συνάρτηση open
), ούτως ώστε να εξαπατήσει το θύμα και εκείνος να αντικαταστήσει μία εγγραφή στο αρχείο κωδικών του συστήματος. Οι συνθήκες ανταγωνισμού μπορούν να χρησιμοποιηθούν για την απόκτηση δικαιωμάτων διαχειριστή στο σύστημα.
Η εκμετάλλευση μίας συνθήκης ανταγωνισμού απαιτεί χρονική ακρίβεια, ούτως ώστε οι ενέργειες του επιτιθέμενου να παρεμβληθούν ανάμεσα σε εκείνες του θύματος. Στο παραπάνω παράδειγμα, ο επιτιθέμενος οφείλει να εκτελέσει την κλήση συστήματος symlink
ανάμεσα στην κλήση των συναρτήσεων access
και open
. Το πλαίσιο της γενικότερης επίθεσης επιβάλλει εκτέλεση των ενεργειών του επιτιθέμενου μετά το πέρας εκτέλεσης κάθε ενέργειας του θύματος.
Αυτό επιτυγχάνεται μέσω συγκεκριμένων τεχνικών όπως ο λαβύρινθος συστήματος αρχείων (file system maze) και οι επιθέσεις αλγοριθμικής πολυπλοκότητας.
Ο λαβύρινθος συστήματος αρχείων είναι μία κακόβουλη δομή φακέλων που στοχεύει στην επιβράδυνση των διεργασιών που εκτελούνται σε κάποιο αρχείο.[3] Οι επιθέσεις αλγοριθμικής πολυπλοκότητας βασίζονται στο γεγονός ότι ο πυρήνας του συστήματος Unix διατηρεί μία κρυφή μνήμη με τα ονόματα των αρχείων και των φακέλων που χρησιμοποιήθηκαν πρόσφατα, προκειμένου να επιταχύνονται τυχόν μελλοντικές ενέργειες ανάλυσης ονόματος. Η ιδέα λοιπόν, είναι η επιβράδυνση αυτών των αναζητήσεων στον πίνακα κατακερματισμού των ονομάτων που διατηρούνται στην κρυφή μνήμη του πυρήνα. Αυτό επιτυγχάνεται μέσω της δημιουργίας πλήθους φακέλων με ονόματα που διαθέτουν το ίδιο αποτύπωμα με το όνομα του φακέλου που θα αναζητήσει ο χρήστης.[4]
Παρά την νοητική απλότητα των συνθηκών ανταγωνισμού, είναι δύσκολη η αποφυγή και εξάλειψή τους. Μία γενική πρακτική είναι η χρήση εξαιρέσεων αντί ελέγχων, όπου δεν υφίσταται αρχικός έλεγχος και σε περίπτωση σφάλματος, αυτό εντοπίζεται κατά την διάρκεια εκτέλεσης του προγράμματος, γεννώντας μία εξαίρεση.
Στο πλαίσιο των συνθηκών ανταγωνισμού σε ένα σύστημα αρχείων, η θεμελιώδης πρόκληση είναι η διασφάλιση ότι το σύστημα αρχείων δεν τροποποιείται ανάμεσα σε δύο κλήσεις συστήματος. Το 2004, ωστόσο, αποδείχθηκε πως δεν υπάρχει κάποια φορητή, ντετερμινιστική τεχνική για την αποφυγή των συνθηκών ανταγωνισμού.[5]
Έκτοτε, οι ερευνητές έχουν προτείνει βιβλιοθήκες παρακολούθησης των περιγραφέων αρχείου και διασφάλισης ορθότητας.[6]
Μία εναλλακτική λύση που προτάθηκε από την ερευνητική κοινότητα αφορά την υιοθέτηση συναλλαγών στο σύστημα αρχείων ή στον πυρήνα του λειτουργικού συστήματος και προορίζεται για συστήματα Unix. Οι συναλλαγές παρέχουν μία αφαίρεση ελέγχου ταυτοχρονισμού για το λειτουργικό σύστημα και μπορούν να χρησιμοποιηθούν για την πρόληψη των συνθηκών ανταγωνισμού. Μάλιστα, έχουν αναπτυχθεί ερευνητικά πρωτότυπα για το Linux ως απόδειξη της παραπάνω έννοιας και περιλαμβάνουν το σύστημα αρχείων Valor[7] και τον TxOS πυρήνα[8]. Ακόμη, τα Windows έχουν προσθέσει τις συναλλαγές ως μέρος του συστήματος αρχείων NTFS[9], αν και η χρήση τους δεν συνίσταται από την Microsoft.