Το ταξίδι είναι το πάθος μου και είμαι οπαδός του Couchsurfing. Το Couchsurfing είναι μια παγκόσμια κοινότητα ταξιδιωτών, όπου μπορείτε να βρείτε ένα μέρος για να μείνετε ή να μοιραστείτε το σπίτι σας με άλλους ταξιδιώτες. Επιπλέον, το Couchsurfing σας βοηθά να απολαύσετε μια πραγματική ταξιδιωτική εμπειρία ενώ αλληλεπιδράτε με τους ντόπιους. Συμμετέχω στην κοινότητα Couchsurfing για πάνω από 3 χρόνια. Παρακολούθησα συναντήσεις στην αρχή και μετά κατάφερα να φιλοξενήσω ανθρώπους. Τι υπέροχο ταξίδι ήταν! Έχω γνωρίσει τόσα πολλά απίστευτα άτομα από όλο τον κόσμο και έκανα πολλούς φίλους. Όλη αυτή η εμπειρία άλλαξε πραγματικά τη ζωή μου.
Έχω φιλοξενήσει πολλοί ταξιδιώτες εγώ, πολύ περισσότερο από ό, τι έχω κάνει σερφ ακόμα. Ενώ ζούσα σε έναν από τους σημαντικότερους τουριστικούς προορισμούς στη Γαλλική Ριβιέρα, έλαβα ένα τεράστιο ποσό αιτημάτων καναπέ (έως και 10 την ημέρα κατά τη διάρκεια της υψηλής σεζόν). Σαν freelance back-end προγραμματιστής , Παρατήρησα αμέσως ότι το πρόβλημα με τον ιστότοπο couchsurfing.com είναι ότι δεν χειρίζεται σωστά τέτοιες περιπτώσεις 'υψηλού φορτίου'. Δεν υπάρχουν πληροφορίες σχετικά με τη διαθεσιμότητα του καναπέ σας - όταν λαμβάνετε ένα νέο αίτημα για καναπέ, δεν μπορείτε να είστε σίγουροι εάν φιλοξενείτε ήδη κάποιον εκείνη τη στιγμή. Θα πρέπει να υπάρχει μια οπτική αναπαράσταση των αποδεκτών και εκκρεμών αιτημάτων σας, ώστε να μπορείτε να τα διαχειριστείτε καλύτερα. Επίσης, εάν μπορούσατε να κάνετε τη διαθεσιμότητα του καναπέ σας δημόσια, θα μπορούσατε να αποφύγετε περιττά αιτήματα καναπέ. Για να καταλάβω καλύτερα τι έχω στο μυαλό μου ρίξτε μια ματιά στο ημερολόγιο της Airbnb.
Πολλές εταιρείες είναι διαβόητες για το ότι δεν ακούνε τους χρήστες τους. Γνωρίζοντας την ιστορία του Couchsurfing, δεν μπορούσα να βασιστώ σε αυτά να εφαρμόσουν αυτήν τη λειτουργία σύντομα. Από τότε που η ιστοσελίδα έγινε κερδοσκοπική εταιρεία, η κοινότητα επιδεινώθηκε. Για να καταλάβω καλύτερα τι μιλάω, προτείνω να διαβάσετε αυτά τα δύο άρθρα:
Ήξερα ότι πολλά μέλη της κοινότητας θα χαρούσαν να έχουν αυτήν τη λειτουργικότητα. Έτσι, αποφάσισα να δημιουργήσω μια εφαρμογή για να λύσω αυτό το πρόβλημα. Αποδεικνύεται ότι δεν υπάρχει δημόσιο API Couchsurfing. Αυτή είναι η απάντηση που έχω λάβει από την ομάδα υποστήριξής τους:
«Δυστυχώς, πρέπει να σας ενημερώσουμε ότι το API μας δεν είναι στην πραγματικότητα δημόσιο και δεν υπάρχουν σχέδια προς το παρόν για δημοσίευση».
Ήρθε η ώρα να χρησιμοποιήσω μερικές από τις αγαπημένες μου τεχνικές αντίστροφης μηχανικής λογισμικού για να μπω στο Couchsurfing.com. Υποθέτω ότι οι εφαρμογές τους για κινητά πρέπει να χρησιμοποιούν κάποιο είδος API για να ρωτήσουν το backend. Επομένως, έπρεπε να αναχαιτίσω τα αιτήματα HTTP που προέρχονται από μια εφαρμογή για κινητά στο backend. Για το σκοπό αυτό, έχω ρυθμίσει έναν διακομιστή μεσολάβησης στο τοπικό δίκτυο και συνέδεσα το iPhone μου σε αυτό για να παρακολουθούν αιτήματα HTTP. Με αυτόν τον τρόπο, κατάφερα να βρω σημεία πρόσβασης του ιδιωτικού τους API και να καταλάβω τη μορφή ωφέλιμου φορτίου JSON.
Τέλος, δημιούργησα έναν ιστότοπο που εξυπηρετεί το σκοπό να βοηθήσω τους ανθρώπους να διαχειριστούν τα αιτήματα καναπέ τους και να δείξω στους surfers ένα ημερολόγιο διαθεσιμότητας καναπέ. Δημοσίευσα έναν σύνδεσμο σε αυτό στα φόρουμ της κοινότητας (τα οποία είναι επίσης αρκετά τμηματοποιημένα κατά τη γνώμη μου και είναι δύσκολο να βρω πληροφορίες εκεί). Η υποδοχή ήταν ως επί το πλείστον θετική, αν και ορισμένοι δεν άρεσαν την ιδέα ότι ο ιστότοπος απαιτούσε διαπιστευτήρια couchsurfing.com, πράγμα που ήταν θέμα εμπιστοσύνης.
Ο ιστότοπος λειτούργησε έτσι: συνδέεστε στον ιστότοπο με τα διαπιστευτήριά σας couchsurfing.com και μετά από μερικά κλικ λαμβάνετε τον κώδικα HTML που μπορείτε να ενσωματώσετε στο προφίλ σας couchsurfing.com και το voila - έχετε ένα αυτόματα ενημερωμένο ημερολόγιο το προφίλ σου. Ακολουθεί το στιγμιότυπο οθόνης του ημερολογίου και εδώ τα άρθρα σχετικά με το πώς το έφτιαξα:
Έχω δημιουργήσει ένα εξαιρετικό χαρακτηριστικό για το Couchsurfing και φυσικά υποθέτω ότι θα εκτιμούσαν τη δουλειά μου - ίσως ακόμη και να μου προσφέρουν μια θέση στην ομάδα ανάπτυξης τους. Έχω στείλει ένα email στο θέσεις εργασίας (στο) couchsurfing.com με έναν σύνδεσμο προς τον ιστότοπο, το βιογραφικό μου και μια αναφορά. Ένα ευχαριστήριο σημείωμα που άφησε ένας από τους καλεσμένους μου στο couchsurfing:
Λίγες μέρες αργότερα παρακολούθησαν τις προσπάθειές μου αντίστροφης μηχανικής. Στην απάντηση ήταν σαφές ότι το μόνο που τους απασχολούσαν ήταν η δική τους ασφάλεια, οπότε μου ζήτησαν να καταργήσω τις αναρτήσεις ιστολογίου που έχω γράψει για το API και τελικά τον ιστότοπο. Έχω καταργήσει αμέσως τις αναρτήσεις, καθώς η πρόθεσή μου δεν ήταν να παραβιάσω τους όρους χρήσης και να ψάξω για τα διαπιστευτήρια των χρηστών, αλλά να βοηθήσω την κοινότητα του couchsurfing. Είχα την εντύπωση ότι με αντιμετώπιζαν εγκληματίες και η εταιρεία εστίασε αποκλειστικά στο γεγονός ότι ο ιστότοπός μου απαιτεί διαπιστευτήρια χρήστη.
Πρότεινα να τους δώσω την εφαρμογή μου δωρεάν. Θα μπορούσαν να το φιλοξενήσουν στο περιβάλλον τους και να το συνδέσουν μέσω ελέγχου ταυτότητας Facebook. Σε τελική ανάλυση, είναι ένα εξαιρετικό χαρακτηριστικό και η κοινότητα το χρειαζόταν. Εδώ είναι το τελικό ψήφισμα που έλαβα:
«Ερχόμαστε πίσω στην ταλάντευση των πραγμάτων εδώ μετά τις διακοπές και θέλουμε να συνεχίσουμε.
Είχαμε κάποια εσωτερική συζήτηση σχετικά με την αίτησή σας και πώς θα μπορούσαμε να τιμήσουμε τόσο τη δημιουργικότητα όσο και την πρωτοβουλία που δείχνει, χωρίς να διακυβεύουμε ενδεχομένως το απόρρητο και την ασφάλεια των δεδομένων των χρηστών του Couchsurfing όταν εισάγουν τα διαπιστευτήριά τους σε ιστότοπο τρίτων.
Το ημερολόγιο γεμίζει ξεκάθαρα μια τρύπα χαρακτηριστικών στον ιστότοπό μας, ένα χαρακτηριστικό που αποτελεί μέρος ενός μεγαλύτερου έργου στο οποίο εργαζόμαστε τώρα.
Ωστόσο, το ζήτημα της συλλογής ονομάτων χρήστη και κωδικών πρόσβασης παραμένει. Δεν θα μπορούσαμε να βρούμε έναν εύκολο τρόπο να το ρυθμίσουμε έτσι ώστε να μπορούμε να το φιλοξενήσουμε ή να το υποστηρίξουμε χωρίς να σας επιτρέψουμε να αποκτήσετε πρόσβαση σε αυτά τα δεδομένα ή να δείτε τον ιστότοπό σας ως προϊόν εργασίας μας.
Το API που είναι προς το παρόν διαθέσιμο σύντομα θα αντικατασταθεί με μια έκδοση που απαιτεί έλεγχο ταυτότητας / εξουσιοδότηση από εφαρμογές που έχουν πρόσβαση σε αυτό. '
Σήμερα, ενώ γράφω αυτό το σεμινάριο λογισμικού αντίστροφης μηχανικής (ένα χρόνο μετά τα γεγονότα), η δυνατότητα ημερολογίου εξακολουθεί να μην εφαρμόζεται στο Couchsurfing.
Πριν από λίγες εβδομάδες εμπνεύστηκα να γράψω ένα άρθρο σχετικά με τις τεχνικές αναστροφής μηχανικών ιδιωτικών API. Φυσικά, αποφάσισα να συνοψίσω τα προηγούμενα άρθρα που έχω γράψει για αυτό το θέμα και να προσθέσω μερικές ακόμη λεπτομέρειες. Καθώς άρχισα να γράφω το νέο άρθρο, ήθελα να παρουσιάσω τη διαδικασία αντίστροφης μηχανικής με ένα ενημερωμένο API και να κάνω ένα άλλο στέλεχος στο hacking API. Με βάση την προηγούμενη εμπειρία μου και το γεγονός ότι η Couchsurfing ανακοίνωσε πρόσφατα μια εντελώς νέα εφαρμογή wesbite και για κινητά http://blog.couchsurfing.com/the-future-of-couchsurfing-is-on-the-way/ , Αποφάσισα να χαράξω ξανά το API τους.
Γιατί κάνω αυτήν την διαδικασία αντίστροφης μηχανικής; Λοιπόν, πρώτα απ 'όλα είναι πολύ διασκεδαστικό να αναστρέφεις το λογισμικό γενικά. Αυτό που μου αρέσει ιδιαίτερα είναι ότι δεν περιλαμβάνει μόνο την τεχνική σας ικανότητα, αλλά και τη διαίσθησή σας. Μερικές φορές, ο καλύτερος τρόπος για να καταλάβετε τα πράγματα είναι να κάνετε μια εικαστική εκτίμηση - θα σας εξοικονομήσει πολύ χρόνο σε σύγκριση με την ωμή βία. Πρόσφατα άκουσα μια ιστορία από μια εταιρεία που έπρεπε να συνεργαστεί με ιδιόκτητα API και λίγη ή καθόλου τεκμηρίωση. Δυσκολεύονταν να αποκρυπτογραφήσουν το ωφέλιμο φορτίο απόκρισης API σε άγνωστη μορφή για μέρες, και στη συνέχεια κάποιος αποφάσισε να δοκιμάσει ?decode=true
στο τέλος του url και είχαν ένα κατάλληλο JSON. Μερικές φορές, αν είστε τυχεροί, το μόνο που χρειάζεται να κάνετε είναι υποστηρίξτε την απόκριση JSON .
Ένας άλλος λόγος που κάνω αυτό το σεμινάριο είναι ότι χρειάζονται αιώνες για ορισμένες εταιρείες να υιοθετήσουν μια συγκεκριμένη δυνατότητα που ζητήθηκε από τους χρήστες τους. Αντί να περιμένετε να εφαρμοστεί, μπορείτε να εκμεταλλευτείτε τη δύναμη του ιδιωτικού τους API και να το δημιουργήσετε μόνοι σας.
Έτσι, με το νέο API couchsurfing.com, ξεκίνησα με μια παρόμοια προσέγγιση και εγκατέστησα την τελευταία τους εφαρμογή iOS.
Αρχικά, πρέπει να ρυθμίσετε έναν διακομιστή μεσολάβησης στο LAN σας για να σφυρηλατήσετε αιτήματα HTTP που προέρχονται από την εφαρμογή στο API εκτελώντας μια επίθεση man-in-the-middle (MITM).
Για μη κρυπτογραφημένες συνδέσεις η επίθεση είναι αρκετά απλή - ένας πελάτης συνδέεται με τον διακομιστή μεσολάβησης και μεταδίδετε εισερχόμενα αιτήματα στον διακομιστή προορισμού μπρος-πίσω. Θα μπορούσατε ενδεχομένως να τροποποιήσετε το ωφέλιμο φορτίο, εάν είναι απαραίτητο. Σε ένα δημόσιο WLAN, είναι αρκετά εύκολο να το εκτελέσετε με τη μεταμφίεση πλαστοπροσωπώντας τον δρομολογητή WiFi.
Για κρυπτογραφημένες συνδέσεις, υπάρχει μια μικρή διαφορά: όλα τα αιτήματα είναι κρυπτογραφημένα από άκρο σε άκρο. Δεν είναι δυνατόν για τον εισβολέα να αποκρυπτογραφήσει το μήνυμα, εκτός εάν έχει κάποιο τρόπο πρόσβαση στο ιδιωτικό κλειδί (το οποίο φυσικά δεν αποστέλλεται κατά τη διάρκεια αυτών των αλληλεπιδράσεων). Τούτου λεχθέντος, παρόλο που το κανάλι επικοινωνίας API είναι ασφαλές, τα τελικά σημεία - ειδικά ο πελάτης - δεν είναι τόσο ασφαλή.
Πρέπει να πληρούνται οι ακόλουθες προϋποθέσεις για να λειτουργεί σωστά το SSL:
Για να ξεπεραστεί η κρυπτογράφηση σε μια επίθεση MITM, ο διακομιστής μεσολάβησης πρέπει να ενεργεί ως CA (Certificate Authority) και να δημιουργεί πιστοποιητικά εν κινήσει. Για παράδειγμα, εάν ένας πελάτης προσπαθήσει να συνδεθεί στο www.google.com, ο διακομιστής μεσολάβησης δημιουργεί δυναμικά ένα πιστοποιητικό για το www.google.com και το υπογράφει. Τώρα, ο πελάτης πιστεύει ότι ο πληρεξούσιος είναι στην πραγματικότητα www.google.com
Για να εφαρμόσω έναν διακομιστή μεσολάβησης που χρησιμοποιείται για την αντιστροφή του ιδιωτικού API, θα χρησιμοποιήσω το εργαλείο που ονομάζεται mitmproxy . Μπορείτε να χρησιμοποιήσετε οποιονδήποτε άλλο διαφανή διακομιστή μεσολάβησης HTTPS. Ο Charles είναι ένα άλλο παράδειγμα με ένα ωραίο GUI. Για να κάνουμε αυτό το έργο πρέπει να ρυθμίσουμε τα ακόλουθα πράγματα:
Διαμορφώστε την προεπιλεγμένη πύλη σύνδεσης WiFi του τηλεφώνου σας για να είναι ο διακομιστής μεσολάβησης (έτσι ώστε ο διακομιστής μεσολάβησης να βρίσκεται στη μέση και να περνούν όλα τα πακέτα) Εγκαταστήστε το πιστοποιητικό διακομιστή μεσολάβησης στο τηλέφωνο (έτσι ώστε ο πελάτης να έχει το δημόσιο κλειδί του διακομιστή μεσολάβησης στο κατάστημα εμπιστοσύνης του)
Ελέγξτε την τεκμηρίωση του διακομιστή μεσολάβησης σχετικά με την εγκατάσταση του πιστοποιητικού. Εδώ είναι οι οδηγίες για το mitmproxy. Και εδώ είναι το αρχείο PEM πιστοποιητικού για iOS.
Για την παρακολούθηση αιτημάτων HTTP που παρακάμπτονται, απλώς εκκινείτε το mitmproxy και συνδέεστε σε αυτό από το κινητό σας τηλέφωνο (η προεπιλεγμένη θύρα είναι 8080).
Ανοίξτε έναν ιστότοπο στο πρόγραμμα περιήγησής σας για κινητά. Σε αυτό το σημείο θα πρέπει να μπορείτε να δείτε την κίνηση στο mitmproxy.
Μόλις βεβαιωθείτε ότι όλα λειτουργούν όπως έχει προγραμματιστεί, ήρθε η ώρα να ξεκινήσετε την εξερεύνηση του ιδιωτικού API της επιλογής σας. Βασικά, σε αυτό το σημείο μπορείτε απλά να ανοίξετε την εφαρμογή, να παίξετε μαζί της και να πάρετε μια ιδέα για τα τελικά σημεία του API και τη δομή αιτημάτων.
Δεν υπάρχει αυστηρός αλγόριθμος για το πώς να αντιστρέψετε ένα API λογισμικού - τις περισσότερες φορές βασίζεστε στη διαίσθησή σας και κάνετε υποθέσεις.
Η προσέγγισή μου είναι να επαναλάβω τις κλήσεις API και να παίξω με διαφορετικές επιλογές. Ένα καλό ξεκίνημα είναι να επαναλάβετε ένα αίτημα που έχετε πιάσει στο mitmproxy και να δείτε αν λειτουργεί (Πατήστε «r» για αναπαραγωγή ενός αιτήματος). Το πρώτο βήμα είναι να καταλάβουμε ποιες κεφαλίδες είναι υποχρεωτικές. Είναι πολύ βολικό να παίζετε με κεφαλίδες με mitmproxy: πατήστε 'e' για είσοδο στη λειτουργία επεξεργασίας και, στη συνέχεια, 'h' για τροποποίηση κεφαλίδων. Με τις συντομεύσεις που χρησιμοποιούν, οι εθισμένοι στο vim θα νιώθουν σαν στο σπίτι τους. Μπορείτε επίσης να χρησιμοποιήσετε επεκτάσεις προγράμματος περιήγησης όπως το Postman για να δοκιμάσετε το API, αλλά τείνουν να προσθέτουν περιττές κεφαλίδες, γι 'αυτό προτείνω να κολλήσετε στο mitmproxy ή το curl.
Έχω δημιουργήσει ένα σενάριο που διαβάζει το αρχείο dump mitmproxy και δημιουργεί μια συμβολοσειρά curl - https://gist.github.com/nderkach/bdb31b04fb1e69fa5346
Ας ξεκινήσουμε με το αίτημα που αποστέλλεται όταν συνδέεστε.
POST https://hapi.couchsurfing.com/api/v2/sessions ← 200 application/json
Το πρώτο πράγμα που παρατήρησα είναι ότι κάθε αίτημα περιέχει μια υποχρεωτική κεφαλίδα X-CS-Url-Signature
που είναι διαφορετικό κάθε φορά. Προσπάθησα επίσης να επαναλάβω ένα αίτημα μετά από λίγο για να ελέγξω εάν υπάρχει έλεγχος χρονικής σήμανσης στο διακομιστή και δεν υπάρχει. Το επόμενο πράγμα που πρέπει να κάνετε είναι να μάθετε πώς υπολογίζεται αυτή η υπογραφή.
Σε αυτό το σημείο αποφάσισα να αναστρέψω το δυαδικό σύστημα και να βρω τον αλγόριθμο. Φυσικά, έχοντας εμπειρία να αναπτύξω iPhone και να έχω ένα iPhone στη διάθεσή μου, αποφάσισα να ξεκινήσω με το iPhone ipa (iPhone app παραδοτέο). Αποδεικνύεται να αποκρυπτογραφήσω, χρειάζομαι ένα σπασμένο τηλέφωνο. Να σταματήσει! Χρόνος σφυρί.
Τότε, θυμήθηκα ότι έχουν επίσης μια εφαρμογή Android. Ήμουν λίγο διστακτικός να δοκιμάσω αυτήν την προσέγγιση, καθώς δεν γνωρίζω τίποτα για το Android ή το Java. Τότε σκέφτηκα ότι θα ήταν μια καλή ευκαιρία να μάθω κάτι νέο. Αποδείχθηκε ευκολότερο να αποκτήσετε έναν αναγνώσιμο από τον άνθρωπο οιονεί πηγαίο κώδικα με την αποκωδικοποίηση του java bytecode από τον πολύ βελτιστοποιημένο κώδικα μηχανής iphone.
Το Apk (παραδοτέο εφαρμογής Android) είναι βασικά ένα αρχείο zip. Μπορείτε να χρησιμοποιήσετε οποιοδήποτε εξολκέα zip για να αποσυσκευάσετε τα περιεχόμενά του. Θα βρείτε ένα αρχείο με το όνομα class.dex, το οποίο είναι ένα bytecode Dalvik. Το Dalvik είναι μια εικονική μηχανή που χρησιμοποιείται για την εκτέλεση μεταφρασμένου bytecode Java σε Android.
Για να αποσυνθέσω το αρχείο .dex στον πηγαίο κώδικα .java χρησιμοποίησα το εργαλείο που ονομάζεται dex2jar. Η έξοδος αυτού του εργαλείου είναι ένα αρχείο βάζου, το οποίο μπορείτε να αποσυνθέσετε με μια ποικιλία εργαλείων. Μπορείτε ακόμη και να ανοίξετε ένα βάζο στο Eclipse ή στο IntelliJ IDEA και θα κάνει όλη τη δουλειά για εσάς. Τα περισσότερα από αυτά τα εργαλεία παράγουν παρόμοιο αποτέλεσμα. Δεν με νοιάζει αν μπορούμε να το μεταγλωττίσουμε για να το τρέξουμε, απλώς το χρησιμοποιούμε για να αναλύσουμε τον πηγαίο κώδικα.
Ακολουθεί μια λίστα εργαλείων που έχω δοκιμάσει:
Ο CFR και ο FernFlower δούλεψαν το καλύτερο για μένα. Το JD-GUI δεν μπόρεσε να αποσυναρμολογήσει ορισμένα κρίσιμα μέρη του κώδικα και ήταν άχρηστο, ενώ τα υπόλοιπα είχαν την ίδια ποιότητα. Ευτυχώς, φαίνεται ότι ο κώδικας κώδικα Java δεν έχει συγκαλυφθεί, αλλά υπάρχουν εργαλεία όπως το ProGuard http://developer.android.com/tools/help/proguard.html για να σας βοηθήσει να απενεργοποιήσετε τον κωδικό.
Η αποσυμπίεση Java δεν είναι πραγματικά το πεδίο αυτού του σεμιναρίου αντίστροφης μηχανικής - υπάρχουν πολλά γραμμένα σε αυτό το θέμα, οπότε ας υποθέσουμε ότι αποικοδομήσατε με επιτυχία και απενεργοποιήσατε τον κώδικά σας Java.
Έχω συνδυάσει όλους τους σχετικούς κωδικούς που χρησιμοποιούνται για τον υπολογισμό του X-CS-Url-Signature στην ακόλουθη ουσία: https://gist.github.com/nderkach/d11540e9af322f1c1c74
Πρώτον, έχω ψάξει για αναφορές X-CS-Url-Signature
, τις οποίες βρήκα στο RetrofitHttpClient
. Μια συγκεκριμένη κλήση φαινόταν ενδιαφέρουσα - για EncUtils
μονάδα μέτρησης. Ανακαλύπτοντάς το, συνειδητοποίησα ότι χρησιμοποιούν το HMAC SHA1. Το HMAC είναι ένας κωδικός ελέγχου ταυτότητας μηνυμάτων που χρησιμοποιεί μια κρυπτογραφική συνάρτηση (SHA1 σε αυτήν την περίπτωση) για τον υπολογισμό ενός κατακερματισμού ενός μηνύματος. Χρησιμοποιείται για να διασφαλίσει την ακεραιότητα (δηλαδή για να αποτρέψει έναν άντρα στη μέση από την τροποποίηση του αιτήματος) και τον έλεγχο ταυτότητας.
Χρειαζόμαστε δύο πράγματα για να υπολογίσουμε το X-CS-Url-Signature
: το ιδιωτικό κλειδί και το κωδικοποιημένο μήνυμα (πιθανώς κάποια παραλλαγή του ωφέλιμου φορτίου HTTP και του URL).
final String a2 = EncUtils.a(EncUtils.a(a, s)); final ArrayList list = new ArrayList(request.getHeaders()); list.add(new Header('X-CS-Url-Signature', a2));
Στον κωδικό a
είναι ένα μήνυμα και s
είναι το κλειδί που χρησιμοποιείται για τον υπολογισμό της κεφαλίδας a2
(η διπλή κλήση στο EncUtils
υπολογίζει απλώς ένα hex digest HMAC SHA1).
Η εύρεση του κλειδιού δεν ήταν πρόβλημα - αποθηκεύτηκε σε απλό κείμενο στο ApiModule
και χρησιμοποιήθηκε για την προετοιμασία της δεύτερης παραμέτρου του RetrofitHttpClient.
RetrofitHttpClient a(OkHttpClient okHttpClient) { return new RetrofitHttpClient(okHttpClient, 'v3# [email protected] #XreXeGCh'); }
Αν κοιτάξουμε την κλήση προς EncUtils
, μπορούμε να δούμε ότι η κυριολεκτική συμβολοσειρά παραπάνω χρησιμοποιείται κατά λέξη ως κλειδί για τον υπολογισμό του HMAC, εκτός από την περίπτωση που this.b
ορίζεται. Στην τελευταία περίπτωση, this.b
προσαρτάται με μια τελεία.
String s; if (this.b == null) { s = this.a; } else { s = this.a + '.' + this.b; }
Τώρα, απλώς κοιτάζοντας τον κώδικα δεν ήταν σαφές για μένα πού και πώς this.b
έχει αρχικοποιηθεί (το μόνο πράγμα που κατάφερα να ανακαλύψω είναι ότι καλείται σε μια μέθοδο με υπογραφή this.a(String b)
, αλλά δεν μπόρεσα να βρω μια κλήση σε αυτό πουθενά στον κώδικα).
public void a(final String b) { this.b = b; }
Σας ενθαρρύνω να το αποσυνθέσετε και να μάθετε τον εαυτό σας :)
Η εύρεση του μηνύματος ήταν αρκετά ευθεία προς τα εμπρός - στον κώδικα μπορείτε να δείτε ότι είναι μια συνένωση της διαδρομής url, δηλαδή /api/v2/sessions
και μια συμβολοσειρά με ωφέλιμο φορτίο JSON (εάν υπάρχει).
final byte[] b = this.b(request.getUrl()); byte[] a; if (request.getBody() != null && request.getBody() instanceof JsonTypedOutput) { System.out.println('body'); // this.a(x, y) concatenates byte arrays a = this.a(b, ((JsonTypedOutput)request.getBody()).a); } else { a = b; }
Ακριβώς κοιτάζοντας τον κώδικα, ήταν δύσκολο να καταλάβουμε τον ακριβή αλγόριθμο για τον υπολογισμό HMAC. Έτσι, αποφάσισα να ξαναχτίσω την εφαρμογή με σύμβολα εντοπισμού σφαλμάτων για να καταλάβω ακριβώς πώς λειτουργεί η εφαρμογή. Έχω χρησιμοποιήσει ένα εργαλείο που ονομάζεται apktool https://code.google.com/p/android-apktool/ για να αποσυναρμολογήσετε το bytecode Dalvik χρησιμοποιώντας smali https://code.google.com/p/smali/ . Ακολούθησα τον οδηγό στο https://code.google.com/p/android-apktool/wiki/SmaliDebugging
Αφού δημιουργήσετε το apk, πρέπει να το υπογράψετε και να το εγκαταστήσετε στη συσκευή σας. Καθώς δεν είχα συσκευή Android, χρησιμοποίησα τον εξομοιωτή που συνοδεύει το Android SDK. Με λίγο κουτάλι, μπορείτε να το κάνετε:
jarsigner -verbose -keystore ~/.android/debug.keystore -storepass android -keypass android androiddebugkey jarsigner -verify -verbose -certs zipalign -v 4
Χρησιμοποίησα έναν ενσωματωμένο εξομοιωτή Android που συνοδεύει το SDK και μια εικονική εικόνα Atom x86 με ενεργοποιημένο το HAXM για να διασφαλίσω ότι λειτουργεί ομαλά.
tools/emulator -avd mydroid -no-boot-anim -cpu-delay 0
Εδώ είναι ένας καλός οδηγός για το πώς να δημιουργήσετε μια εικονική εικόνα: http://jolicode.com/blog/speed-up-your-android-emulator
Βεβαιωθείτε ότι βλέπετε τη γραμμή Το HAX λειτουργεί και ο εξομοιωτής λειτουργεί σε γρήγορη λειτουργία virt κατά την εκκίνηση του εξομοιωτή για να βεβαιωθείτε ότι έχετε ενεργοποιήσει το HAXM.
σχεδιαστική σκέψη για επιχειρηματική στρατηγική
Στη συνέχεια, εγκατέστησα το apk στον εξομοιωτή και έτρεξα την εφαρμογή. Ακολουθώντας τον οδηγό apktool, χρησιμοποίησα το απομακρυσμένο πρόγραμμα εντοπισμού σφαλμάτων IntelliJ IDEA για να συνδεθώ στον εξομοιωτή και να ορίσω ορισμένα σημεία διακοπής γραμμής:
Παίζοντας με την εφαρμογή για λίγο, κατάφερα να καταλάβω ότι το ιδιωτικό κλειδί χρησιμοποιούσε αρχικοποίηση RetrofitHttpClient
χρησιμοποιείται για τον υπολογισμό του HMAC μιας υπογραφής αιτήματος σύνδεσης. Στην απάντηση στο POST σύνδεσης λαμβάνετε ένα αναγνωριστικό χρήστη και το AccessToken (X-Access-Token
). Το διακριτικό πρόσβασης χρησιμοποιείται για την εξουσιοδότηση όλων των ακόλουθων αιτημάτων. Το HMAC για όλα τα αιτήματα σύνδεσης μετά την κατασκευή είναι κατασκευασμένο με τον ίδιο τρόπο όπως το αίτημα σύνδεσης, εκτός από το ότι το κλειδί συντίθεται με προσάρτηση .
στο αρχικό ιδιωτικό κλειδί.
Μόλις εξουσιοδοτηθείτε, η εφαρμογή στέλνει το ακόλουθο αίτημα:
POST https://hapi.couchsurfing.com/api/v2/users/1003669205/registerDevice ← 200 application/json
Καθώς μπόρεσα να αφαιρέσω εμπειρικά, αυτό το αίτημα είναι προαιρετικό για έλεγχο ταυτότητας. Μπόνους πόντους αν καταλάβετε για ποιο λόγο χρησιμοποιείται!
Μόλις γίνει έλεγχος ταυτότητας, μπορείτε να στείλετε ένα αίτημα για ανάκτηση του (ή του προφίλ χρήστη κάποιου άλλου), όπως αυτό:
GET https://hapi.couchsurfing.com/api/v2/users/1003669205 ← 200 application/json
Δεν πήρα πολλά στοιχεία, αλλά παρατήρησα ότι ένα προφίλ ενημερώνεται με αίτημα PUT. Μόνο για διασκέδαση, προσπάθησα να ενημερώσω ένα άλλο προφίλ με το ίδιο αίτημα - δεν ήταν εξουσιοδοτημένο, επομένως προφανώς εφαρμόζονται τα βασικά στοιχεία ασφαλείας.
Έγραψα ένα απλό σενάριο Python για να συνδεθώ χρησιμοποιώντας τα διαπιστευτήριά σας couchsurfing.com και να λάβω το προφίλ χρήστη: https://gist.github.com/nderkach/899281d7e6dd0d497533 . Εδώ είναι το περιτύλιγμα Python για το API: https://github.com/nderkach/couchsurfing-python με ένα πακέτο διαθέσιμο στο αποθετήριο pypi (pip install couchsurfing).
Δεν είμαι σίγουρος τι ακριβώς πρόκειται να κάνω με το API αυτή τη φορά. Ο κώδικας HTML στα προφίλ χρηστών δεν επιτρέπεται πλέον, επομένως θα πρέπει να βρω μια διαφορετική προσέγγιση στο παλιό πρόβλημα. Θα συνεχίσω να αναπτύσσω και να βελτιώνω το περιτύλιγμα API python, εάν υπάρχει ζήτηση για αυτό, και υποθέτοντας ότι το couchsurfing.com δεν θα προκαλέσει πάρα πολλά προβλήματα. Δεν εξερεύνησα το API πάρα πολύ και το δοκίμασα για κάποια βασικά τρωτά σημεία. Φαίνεται αρκετά ασφαλές, αλλά θα ήταν ενδιαφέρον να μάθετε αν μπορείτε να αποκτήσετε πρόσβαση στα δεδομένα που δεν είναι διαθέσιμα μέσω του ιστότοπου. Είτε έτσι είτε αλλιώς, τώρα μπορείτε να χρησιμοποιήσετε την αντίστροφη τεχνική λογισμικού για να δημιουργήσετε έναν εναλλακτικό πελάτη για Windows Phone, Pebble ή τον έξυπνο καναπέ σας.
Υπάρχει μια συζήτηση που θα ήθελα να ανοίξω - γιατί να μην δημοσιεύσετε το API σας και να το δημοσιεύσετε; Ακόμα κι αν δεν κατάφερα να χαράξω το API, θα ήταν ακόμα δυνατό να γίνει απόσπαση του ιστότοπου. Θα ήταν πιο αργό και πιο δύσκολο να διατηρηθεί, αλλά σίγουρα θα προτιμούσαν οι καταναλωτές να χρησιμοποιούν ένα API και όχι ένα εργαλείο ξύρωσης. Η διαθεσιμότητα των API θα επιτρέψει σε τρίτους προγραμματιστές να βελτιώσουν το προϊόν της εταιρείας και να δημιουργήσουν υπηρεσίες προστιθέμενης αξίας γύρω από αυτό. Κάποιος μπορεί να υποστηρίξει ότι θα ήταν ακριβότερο να διατηρηθεί το δημόσιο API παρά ένα ιδιωτικό. αλλά και πάλι, τα πλεονεκτήματα των υπηρεσιών δημιουργίας κοινότητας πάνω από το προϊόν σας θα υπερέβαιναν το κόστος συντήρησης API.
Είναι δυνατόν να αποτρέψουμε εντελώς τη χρήση ενός ιδιωτικού API από πελάτες τρίτων; Δεν το νομίζω Η χρήση της προσάρτησης SSL θα αποτρέψει την εισροή αιτημάτων API χρησιμοποιώντας μια απλή διαφανή τεχνική διακομιστή μεσολάβησης όπως περιγράφεται παραπάνω. Στο τέλος, ακόμη και αν αποκρύψετε το δυαδικό λογισμικό, ένας παρακινητής χάκερ με κάποιους πόρους και χρόνο θα είναι πάντα σε θέση να αναστρέψει το δυαδικό λογισμικό της εφαρμογής και να πάρει το ιδιωτικό κλειδί / πιστοποιητικό. Πιστεύω ότι η υπόθεση ότι το τελικό σημείο του πελάτη είναι ασφαλές είναι εγγενώς λάθος. Ενα ΦΩΤΙΑ πελάτης είναι ένα αδύναμο σημείο.
Διατηρώντας ένα API ιδιωτικό, μια εταιρεία μεταδίδει βασικά ένα μήνυμα δυσπιστίας στους χρήστες τους. Σίγουρα, μπορείτε να προσπαθήσετε να προστατέψετε το ιδιωτικό σας API ακόμη περισσότερο. Ωστόσο, δεν θα προτιμούσατε να εφαρμόσετε μια βασική ασφάλεια για το API για την αποτροπή κακόβουλης χρήσης. και αντίθετα να εστιάσετε τους πόρους σας στη βελτίωση του λογισμικού για να παρέχετε μια καλύτερη εμπειρία χρήστη;
Couchsurfing, παρακαλώ, με ζάχαρη στην κορυφή, ανοίξτε το API.