Deep-Dive · Ανάλυση Ευπάθειας Breaking Security News

Όταν το Node2Shell (CVE-2026-111497) ξέφυγε από τη Node.js και έγινεHTTP2Shell

Ένα out-of-bounds write σε έναν Brotli decoder γραμμένο σε C — δεμένο μέσα στα runtimes που θεωρούσαμε «ασφαλή υποδομή». Ξεκίνησε ως bug της Node.js. Τελείωσε ως κλάση τρωτότητας που αγγίζει κάθε HTTP client, agent, CLI και CI runner που αποσυμπιέζει bytes που δεν ελέγχει. Αυτό το άρθρο είναι ο πλήρης χάρτης: ανατομία, μετάλλαξη, blast radius, kill chains, ανίχνευση και πλάνο μετριασμού.

cve-inspect — sandbox
$ cve-inspect --id CVE-2026-111497
  alias      : Node2Shell → HTTP2Shell
  type       : out-of-bounds write (native C)
  component  : bundled Brotli decoder
  carriers   : Node.js · Bun · Python (brotli / brotlicffi)
  entry      : HTTP απόκριση με Content-Encoding: br
  impact     : heap corruption → RCE
  patched    : Node 22.23.4 / 24.22.1 / 26.12.1 · Bun latest
  status     : public PoCs · όχι (ακόμη) στο CISA KEV
📅 24 Οκτ 2026 🎯 Στόχοι: HTTP clients / agents / CI ⚠️ Βαρύτητα: Κρίσιμη (εκτίμηση) 🧩 Κατηγορία: memory safety σε bundled C
01

Σε ενενήντα δευτερόλεπτα

Αν δεν διαβάσεις τίποτα άλλο, διάβασε τον παρακάτω πίνακα. Κάθε γραμμή είναι ένα δεδομένο που χρειάζεται για να αποφασίσεις πόσο σε αφορά — και με ποια σειρά θα κάνεις actions.

ΤαυτότηταCVE-2026-111497 — αρχικό όνομα Node2Shell, σημερινή ορολογία HTTP2Shell.
Τύπος bugOut-of-bounds write: εγγραφή bytes εκτός ορίων buffer σε native C κώδικα — όχι λογικό σφάλμα, διαβρώση μνήμης.
Στοιχείο-στόχοςΟ Brotli decoder (Content-Encoding: br) που συνοδεύεται ως bundled C library μέσα στα runtimes Node.js και Bun.
Οδός εισόδουHTTP απόκριση που ελέγχει (ή παραποιεί) ο attacker, δηλωμένη ως brotli-compressed. Ο client την αποσυμπιέζει αυτόματα.
ΕπίπτωσηHeap corruption → απομακρυσμένη εκτέλεση κώδικα στην πλευρά του client· σε αποτυχία, crash/DoS ως ελάχιστο αποτέλεσμα.
Παράθυρο patchNode.js 22.23.4 (LTS 22) · 24.22.1 (LTS 24) · 26.12.1 (26) · Bun τελευταία έκδοση · Python: ανά έκδοση των brotli/brotlicffi.
Ποιοι άλλοιΚάθε HTTP stack με transparent brotli decompression: clients, SDKs, telemetry/backup agents, CLIs, CI runners, native bindings.
Κατάσταση 24/10Δημόσια PoC repositories εντός 24ώρου. Δεν βρίσκεται (ακόμη) στο CISA KEV — το παράθυρο είναι ανοιχτό, όχι κλειστό.

Το σενάριο που να μείνει: ένα service κάνει server-side fetch σε URL που επηρεάζεται από input χρήστη — ακόμα κι έμμεσα, μέσω redirects, previews ή webhooks. Ο attacker απαντά με Content-Encoding: br και crafted brotli stream. Ο decoder διαβρώνει τη μνήμη της διεργασίας μέσα στο εσωτερικό σου δίκτυο. Από εκεί: metadata endpoints, tokens, lateral movement.

02

Χρονολόγιο: εννέα μέρες που άλλαξαν το bug

Το HTTP2Shell δεν γεννήθηκε έτοιμο. Είναι αποτέλεσμα αλυσιδωτών αποκαλύψεων — και του πώς η ερευνητική κοινότητα «αναδιαβάζει» ένα advisory μετά τη δημοσίευσή του. Η σειρά έχει σημασία: δείχνει πώς ένα ήδη patchαρισμένο bug μετατρέπεται σε κλάση τρωτότητας.

20–21 ΟΚΤ

Το προοίμιο: PHP2Shell

Δύο κρίσιμα RCE στην PHP (CVE-2026-109618, CVE-2026-109619) δημοσιοποιούνται και patchάρονται βιαστικά. Θέμα: native parsing & compression primitives ως επιθετική επιφάνεια. Η αγορά security «ζεσταίνεται» πάνω στην ιδέα.

21 ΟΚΤ

Node2Shell — το advisory

Ανακοινώνεται το CVE-2026-111497: out-of-bounds write στον bundled Brotli decoder της Node.js και του Bun. Κυκλοφορούν οι διορθωμένες εκδόσεις 22.23.4, 24.22.1, 26.12.1. Η αρχική ανάγνωση: «Node servers — patchάρετε».

22 ΟΚΤ

Πρώτα PoCs

Εντός 24ώρου εμφανίζονται δημόσια PoC repositories. Στη γειτονική οικογένεια, το Exploit-DB καταγράφει το #52704 (PHP2Shell, 22/10). Το bug παύει να είναι θεωρητικό.

23 ΟΚΤ

Η επέκταση σε Python

Έρευνα της Aikido τεκμηριώνει ότι τα Python packages brotli και brotlicffi είναι οχήματα της ίδιας λογικής ευπάθειας — και μέσω αυτών, κάθε Python HTTP stack που κάνει transparent decompression. Το blast radius βγαίνει από τη JavaScript.

23–24 ΟΚΤ

Η μετονομασία: HTTP2Shell

Ο κλάδος υιοθετεί τον όρο HTTP2Shell (HTTP-to-Shell): όχι πια «bug της Node.js», αλλά κλάση τρωτότητας. Την ίδια μέρα το CISA KEV προσθέτει το CVE-2026-114625 (Arista VeloCloud Orchestrator SQLi) και το CVE-2026-110447 (Collabora Online) — τεχνικά άσχετα, αλλά με κοινό θέμα: επιφάνειες που «απλώς δέχονται και επεξεργάζονται» δεδομένα.

24 ΟΚΤ · σήμερα

Το παρόν

Καμία τεκμηριωμένη μαζική in-the-wild εκμετάλλευση που να οδηγεί σε KEV — αλλά τα PoCs είναι δημόσια και το παράθυρο ανοίγει. Στόχος του άρθρου: μετατροπή του «advisory fatigue» σε εκτελέσιμο πλάνο.

03

Ανατομία: από byte σε shell

3.1 · Τι είναι ο Brotli — και γιατί είναι παντού context

Ο Brotli είναι ο αλγόριθμος συμπίεσης που έφερε η Google για το web: μικρότερα payloads από gzip σε σχεδόν κάθε περιεχόμενο, και μια σχεδόν απόλυτη υιοθέτηση από τα σύγχρονα HTTP stacks. Ο server δηλώνει Content-Encoding: br, ο client το καταλαβαίνει, όλοι χαίρονται. Το κόστος αυτής της ευκολίας κρύβεται σε μια λεπτομέρεια αρχιτεκτονικής: η reference υλοποίηση του Brotli είναι γραμμένη σε C — γλώσσα χωρίς αυτόματο έλεγχο ορίων μνήμης.

Τα runtimes δεν ξαναγράφουν τον decoder από το μηδέν. Τον ενσωματώνουν: η Node.js τον κουβαλάει χρόνια για να υποστηρίζει brotli αποκρίσεων, το Bun έκανε το ίδιο. Αυτό σημαίνει ότι ο C κώδικας τρέχει μέσα στη διεργασία της εφαρμογής σου — ίδιος heap, ίδιες permissions, κανένα sandbox ανάμεσα. Όταν εκεί μέσα υπάρχει out-of-bounds write, δεν μιλάμε για «λάθος λογικής» που επιστρέφει λάθος αποτέλεσμα. Μιλάμε για εγγραφή σε μνήμη που δεν της αναλογεί — με όλες τις συνέπειες που έχει αυτό σε επίπεδο μηχανής.

3.2 · Out-of-bounds write: γιατί είναι χειρότερο από read primitive

Η κοινότητα έχει ζήσει ξανά το «native decoder τρώει untrusted bytes»: το Heartbleed ήταν out-of-bounds read — διάβαζε μνήμη που δεν έπρεπε και τη διέρρεε. Το read είναι σοβαρό. Το write όμως είναι άλλη κατηγορία: δεν σεναριάζει μόνο «τι έμαθε ο attacker», αλλά «τι μπορεί να κάνει ο attacker».

Μια εγγραφή εκτός ορίων διαβρώνει ό,τι βρεθεί δίπλα: metadata του heap, αντικείμενα γειτονικά, pointers συναρτήσεων. Με σωστή προετοιμασία (heap grooming — δηλαδή στοίχειωση του heap ώστε το «δίπλα» να είναι ακριβώς ό,τι σε συμφέρει), η διαβρώση μετατρέπεται σε έλεγχο ροής εκτέλεσης — και από εκεί σε εκτέλεση κώδικα επιλογής του attacker. Είναι δύσκολο, context-sensitive, και εξαρτάται από build: allocators, ASLR, hardening flags. Αλλά τα δημόσια PoCs που εμφανίστηκαν αμέσως μετά το advisory αποδεικνύουν το προφανές: εφικτό.

Η βασική εξίσωση: decompression σημαίνει parsing δεδομένων που έρχονται από άλλον. Αν τα bytes της απόκρισης τα ελέγχει ο attacker, τότε εκείνος τρέχει —κατόπιν αιτήματός του— έναν C parser μέσα στη διεργασία σου. Το write σπανίζει περισσότερο από το read, κοστίζει περισσότερο, και γι' αυτό αξίζει περισσότερο στην αγορά των exploits.

3.3 · Το μοτίβο του θύματος victim pattern

Ποιος είναι ο κοινός παρονομαστής όλων των πιθανών θυμάτων; Ο κώδικας που κάνει HTTP fetch χωρίς να γνωρίζει ότι συμμετέχει σε decompression. Δες πόσο αθώο μοιάζει:

javascript · fetch με default encodings
// ΚΑΘΕ service που κάνει κάτι τέτοιο είναι ύποπτο:
const res = await fetch(userInfluencedUrl, {
  headers: { 'accept-encoding': 'gzip, deflate, br' }  // ← το br στο προεπιλεγμένο σετ
});

// Η αποσυμπίεση είναι ΑΟΡΑΤΗ στον developer:
const body = await res.text();  // ← εδώ, μέσα στη διεργασία, τρέχει ο C decoder

// Ο developer δεν είδε ποτέ το "br". Δεν το ζήτησε ρητά.
// Απλώς συμβαίνει — γιατί έτσι συμπεριφέρονται όλοι οι HTTP clients.

Η κεφαλίδα Content-Encoding: br απαντάται σε δύο γραμμές από οποιονδήποτε HTTP server-παγίδα. Δεν χρειάζεται ιδιαίτερη ρύθμιση από τον attacker: η διαπραγμάτευση έχει γίνει από τον ίδιο σου τον client. Η ευκολία αυτή είναι που κάνει το primitive τόσο ευρύ.

3.4 · Η αλυσίδα εκμετάλλευσης kill path

attacker URL→HTTP 200 + Content-Encoding: br→crafted brotli meta-block→OOB write στο heap→heap grooming→έλεγχος εκτέλεσης→shell σε JS runtime
04

Η μετάλλαξη: γιατί «Node2Shell» ήταν λάθος όνομα

Τα ονόματα ευπαθειών δεν είναι διαφημίσεις — είναι μοντέλα σκέψης. Όταν η αρχική ονοματολογία έδειχνε «Node», οι ομάδες που δεν έτρεχαν Node.js καρφίτσωσαν το advisory στον πίνακα «later». Αυτό ήταν το ακριβέστερο λάθος της εβδομάδας: το bug δεν ζει στην Node.js ως πλατφόρμα, αλλά σε έναν C decoder που η Node.js τυχαίνει να κουβαλάει — και τον οποίο κουβαλάνε και άλλοι.

Με αυτόν τον φακό, η «επέκταση» σε Python δεν είναι καμία έκπληξη. Η έρευνα της Aikido τεκμηρίωσε ότι τα ευρέως διαδεδομένα πακέτα brotli και brotlicffi λειτουργούν ως οχήματα: μόλις υπάρχουν στο environment, αρκετοί HTTP clients της Python ενεργοποιούν αυτόματα τη διαπραγμάτευση και αποσυμπίεση του brotli. Ο developer δεν έγραψε ούτε μία γραμμή γι' αυτό. Η ύπαρξη ενός πακέτου σε ένα requirements.txt άλλαξε συμπεριφορά ασφαλείας ολόκληρης της εφαρμογής. Αυτό είναι το οριστικό supply-chain μάθημα του HTTP2Shell.

Ο κανόνας του HTTP2Shell, μια φορά: «Αν η διεργασία σου αποσυμπιέζει brotli bytes που μπορεί να επηρεάσει τρίτος, και ο decoder είναι ο ευάλωτος, τότε είσαι επιφάνεια επίθεσης — ανεξαρτήτως γλώσσας, runtime ή οικοσυστήματος». Το HTTP2Shell δεν είναι ευπάθεια· είναι ο κάτοχος χάρτης της ευπάθειας.

4.1 · Ρητός κώδικας vs αόρατος κώδικας surface

🎯 Ρητός κώδικας

Άμεσες κλήσεις σε decompression APIs, custom decoders, ρητές ρυθμίσεις encodings. Εδώ τουλάχιστον ξέρεις ότι υπάρχει η επιφάνεια: τη βλέπεις σε code review, τη βάζεις σε SBOM, τη φυλάς.

👻 Αόρατος κώδικας

Το Content-Encoding handling μέσα στα HTTP clients. Κανείς δεν το ζητά ρητά, κανείς δεν το βλέπει. Είναι η «υδάτινη στήριξη» του εκμεταλλεύσιμου surface — και υπάρχει παντού: clients, agents, SDKs, CLIs, monitoring.

Η σωστή ερώτηση δεν είναι «ποιος καλεί τον decoder» αλλά «ποιος τερματίζει bytes που μπορεί να είναι br-encoded από πηγή που δεν ελέγχεις πλήρως». Με αυτό το κριτήριο ο χάρτης των δυνητικών θυμάτων απλώνεται σε επίπεδα — και αυτό μας οδηγεί στο blast radius.

05

Blast radius: ο πλήρης χάρτης εκθέσεων

3
Γραμμές fix στη Node.js: 22.23.4 · 24.22.1 · 26.12.1
2+1
Runtimes στο επίκεντρο: Node.js, Bun — και Python ως δίαυλος επέκτασης
2
PyPI packages-οχήματα: brotli, brotlicffi
1
Κοινή υπόθεση που τα ενώνει όλα: transparent decompression

5.1 · Τα πέντε επίπεδα εκθέσεων tier map

TierΤι είναιΠαραδείγματαΈκθεσηΓιατί
TIER 0Runtimes με bundled decoderNode.js (παλαιότερες εκδόσεις), BunΑΜΕΣΗΟ ευάλωτος C κώδικας τρέχει in-process σε κάθε decompression. Κάθε fetch με br-encoded απόκριση είναι υποψήφιο trigger.
TIER 0.5Python decode packagesbrotli, brotlicffi (C bindings)ΑΜΕΣΗ, ΥΠΟ ΟΡΟΥΣΤο binding φορτώνει C decoder στη διεργασία. Η έκθεση ενεργοποιείται από την παρουσία του πακέτου και τη χρήση του από HTTP stack.
TIER 2HTTP clients & SDKsfetch/undici/axios/got/superagent στο Node · requests/httpx/aiohttp στην Python όταν υπάρχει brotliΕΜΜΕΣΗ, ΔΙΑΔΕΔΟΜΕΝΗΟ client διαπραγματεύεται br και αποσυμπιέζει αυτόματα. Ο developer δεν βλέπει ποτέ το encoding.
TIER 3Agents, CLIs, CI/CDTelemetry/backup agents, package managers, artifact fetchers, monitoring daemons, CI runnersΕΜΜΕΣΗ, ΥΠΟΤΙΜΗΜΕΝΗΤρέχουν unattended, κάνουν fetch από πηγές που σπάνια ελέγχονται και συχνά κρατούν τα υψηλότερα privileges του οικοσυστήματος.
TIER 4Native static consumersRust/Go/C++ bindings προς την upstream C library, embedded, appliancesΑΣΑΦΗΣΔεν υπάρχουν τυποποιημένα advisories ανά binding. Χρειάζεται δικός σου έλεγχος: ποια έκδοση του C decoder είναι statically συνδεδεμένη.

5.2 · Γιατί οι browsers είναι (σχετικά) ασφαλέστεροι context

Εύλογη ερώτηση: «ο browser μου κάνει fetch και decompress brotli όλη μέρα — γιατί δεν μιλάμε γι' αυτό;». Τρεις λόγοι. Πρώτον, οι μεγάλοι browsers διατηρούν δικές τους, ενεργά fuzzed υλοποιήσεις decoders — δεν κληρονομούν τυφλά την upstream C library.

Δεύτερον, η αρχιτεκτονική τους είναι sandboxed: ακόμη κι ένα επιτυχές memory corruption στον renderer πρέπει να διασχίσει επιπλέον φράγματα για να γίνει ουσιαστικό RCE. Τρίτον, το threat model τους παρακολουθείται από τις καλύτερα χρηματοδοτούμενες security ομάδες του πλανήτη. Αυτό δεν σημαίνει μηδενικό ρίσκο — σημαίνει ότι το ρεαλιστικό κέντρο βάρους του HTTP2Shell είναι το server-side & infrastructure-side HTTP: τα δικά σου services, agents και runners.

5.3 · Το γλυκό σημείο: το cloud threat model

06

Τρία kill chains, βήμα-βήμα

Η θεωρία τελειώνει εδώ. Ακολουθούν τα τρία ρεαλιστικά σενάρια με τα οποία το HTTP2Shell γίνεται περιστατικό — το καθένα με ανάλυση «γιατί δουλεύει» και, το σημαντικότερο, «τι το σπάει».

KC-A

SSRF → εσωτερικό HTTP client → RCE → κλοπή cloud identity

1. user input → URL→2. server-side fetch→3. attacker responder: br payload→4. OOB write→5. RCE→6. IMDS credentials→7. lateral
Σενάριο

Η εφαρμογή έχει λειτουργία που κάνει fetch σε URL: preview εικόνων, import από link, webhook verification, URL health-check. Ο attacker καταχωρεί το δικό του endpoint. Όταν το service κάνει fetch, ο attacker-server απαντά 200 με Content-Encoding: br και crafted payload. Ο bundled decoder corruptάρει τη μνήμη της εσωτερικής διεργασίας. Σε cloud environment, το πρώτο που ψάχνει ένα shell είναι το metadata service — και μόλις πάρει credentials, ο attacker δεν χρειάζεται πια το bug.

Γιατί δουλεύει

Ο client «θέλει» να δεχθεί br (το διαπραγματεύτηκε ο ίδιος), η αποσυμπίεση είναι αόρατη στον κώδικα, και το θύμα είναι από τα πιο privileged processes της εφαρμογής.

Τι το σπάει

Egress allowlist που εμποδίζει fetch σε μη εγκεκριμένους hosts · patchαρισμένο runtime · Accept-Encoding χωρίς br σε internal fetchers · token-based metadata protections (τύπου IMDSv2) που δεν απαντούν σε τυφλά GETs.

KC-B

Edge/CDN/cache poisoning ή hostile network: το MITM μονοπάτι

1. compromised CDN/proxy→2. legit request→3. παραποιημένη απόκριση + br→4. decompression στον client→5. RCE
Σενάριο

Ο attacker δεν χρειάζεται να είναι ο endpoint: αρκεί να κάθεται «στο δρόμο». Compromised CDN, poisoned cache, εταιρικό proxy με TLS interception, hostile Wi-Fi. Η εφαρμογή κάνει fetch σε απολύτως νόμιμο domain — αλλά η απόκριση που φτάνει είναι παραποιημένη. Το σενάριο αντιστρέφει την κλασική ήρεμη διαπίστωση «κάνω fetch μόνο σε trusted hosts»: το «trusted» αφορά το DNS name, όχι τα bytes.

Γιατί δουλεύει

Τα TLS termination σημεία και τα caches έχουν τα δικά τους compromise vectors, και η εφαρμογή εμπιστεύεται τον δρόμο που θεωρεί δικό της.

Τι το σπάει

Verification/pinning όπου πρακτικά υπαρκτό, patchαρισμένα runtimes, και επίγνωση ότι το «TLS-only» δεν είναι συνώνυμο του «τέλος ζωής του MITM».

KC-C

CI/CD: ο runner που κάνει fetch ως κλέφτης μυστικών

1. CI job→2. fetch artifacts/deps→3. compromised/malicious source→4. br payload→5. RCE στον runner→6. tokens → poisoned artifacts
Σενάριο

Οι CI runners είναι ο παράδεισος του HTTP2Shell: κάνουν αμέτρητα fetches (dependencies, base images, artifacts, release binaries), τρέχουν με τα ισχυρότερα tokens του οργανισμού, και κανείς δεν τα παρακολουθεί στενά. Ένα RCE σε runner σημαίνει: κλοπή provider credentials, poisoning των artifacts που παράγει, και — στο επόμενο deploy — RCE όπου τρέχουν τα artifacts.

Γιατί δουλεύει

Οι runners συχνά τρέχουν ξεπερασμένα images γιατί «θα αναδημιουργηθούν ούτως ή άλλως» — υπόθεση που σπάνια επαληθεύεται ποτέ.

Τι το σπάει

Pinned & checksum-verified artifact sources · egress proxies στο CI · fresh runner images από patched bases · short-lived, scoped tokens αντί για αιώνια.

Το κοινό μοτίβο άμυνας: και στα τρία σενάρια το bug χρειάζεται δύο πράγματα για να δουλέψει: (1) ευάλωτο decoder στη διεργασία και (2) δρόμο για attacker-influenced bytes. Κατέστρεψε το ένα και το kill chain σπάει. Κατέστρεψε και τα δύο — και το σενάριο γίνεται θεωρία.

07

Η οικογένεια X2Shell: pattern, όχι σύμπτωση

Το HTTP2Shell δεν εμφανίστηκε σε κενό. Η ίδια εβδομάδα είδε τη δημοσιοποίηση του PHP2Shell — δύο κρίσιμα RCE στην PHP που patchάρονταν βιαστικά στις 20–21 Οκτωβρίου, με ένα τρίτο σχετικό bug που παραμένει χωρίς emergency fix. Τα «X2Shell» δεν μοιράζονται κώδικα· μοιράζονται φιλοσοφία: τα δεδομένα που «απλώς γίνονται parse» από native code είναι η πιο υποτιμημένη επιθετική επιφάνεια του internet.

ΌνομαCVE(s)PrimitiveΠού χτυπάΚατάσταση patch
Node2ShellCVE-2026-111497OOB write σε bundled Brotli decoderNode.js & Bun runtimes (client-side decompression)PATCHED 21/10
HTTP2ShellCVE-2026-111497 WIDER LENSΤο ίδιο primitive σε ευρύτερη ανάγνωση: κάθε HTTP stack με brotli αποσυμπίεσηPython (brotli/brotlicffi), agents, CLIs, CI, native consumersΜΕΡΙΚΩΣ — ανά component
PHP2Shell (×2)CVE-2026-109618 · CVE-2026-109619Unauthenticated RCE στην PHP engine (mod_php vector)PHP ≥ 5.4, web frontendsPATCHED 20–21/10
PHP2Shell (3ο bug)—Σχετικό bug χωρίς πλήρεις λεπτομέρειεςPHPΧΩΡΙΣ EMERGENCY FIX
Node.js hardening waveCVE-2026-105481 → 106074Σειρά flaws στη Node.js (NVD batch)Node.js internalsWAVE PATCHES

Η χρονική συγκυρία έχει σημασία: την ίδια περίοδο το CISA KEV πρόσθεσε το CVE-2026-114625 (Arista VeloCloud Orchestrator — SQL injection στο edge) και το CVE-2026-110447 (Collabora Online/CODE server). Τεχνικά άσχετα μεταξύ τους — αλλά το μήνυμα της εβδομάδας είναι ενιαίο: τα επίπεδα που «απλώς δέχονται και επεξεργάζονται» bytes και queries είναι το κύριο θέατρο. Αν δουλεύεις σε blue team, αυτό είναι το briefing σου για το τρίμηνο.

08

Κατάσταση exploitation: τι είναι πραγματικό, τι ανοιχτό

📦 Τι είναι τεκμηριωμένο

Δημόσια PoC repositories για το Node2Shell/HTTP2Shell δημιουργήθηκαν εντός 24ώρου από τη δημοσιοποίηση. Στη γειτονική οικογένεια, το Exploit-DB φιλοξενεί το #52704 (PHP2Shell PoC, 22/10). Η τεχνική λεπτομέρεια του primitive είναι πλέον δημόσιο κτήμα.

🕵️ Τι δεν έχει συμβεί (ακόμη)

Καμία τεκμηριωμένη μαζική in-the-wild εκμετάλλευση που να οδηγεί σε προσθήκη στο CISA KEV (ως τις 24/10). Το KEV απαιτεί παρατηρηθείσα εκμετάλλευση — όχι θεωρητική δυνατότητα. Αυτό είναι παράθυρο, όχι εγγύηση.

8.1 · Η εκτίμηση για το παράθυρο threat outlook

Το κόστος exploit του HTTP2Shell είναι υψηλότερο από ένα κλασικό web RCE: χρειάζεται delivery (attacker-influenced response) και αξιόπιστη heap exploitation ανά build. Αυτό μεταφράζεται έτσι: μαζική σάρωση τύπου «loud scanner» είναι ενοχλητική αλλά εφικτή — με DoS ως παρενέργεια· η στοχευμένη εκμετάλλευση είναι το πραγματικό ρίσκο, ειδικά από initial access brokers που πωλούν πρόσβαση. Ιστορικά, τέτοια primitives οπλοποιούνται μέσα σε 2–6 εβδομάδες. Το patch window σου δεν είναι «μέχρι να μπει στο KEV» — είναι τώρα.

Anti-FOMO σημείωμα: το να μην είσαι στο KEV δεν σημαίνει «δεν με αφορά κανέναν». Σημαίνει «δεν το έκαναν ακόμη με τρόπο που να φάνηκε». Τα πιο ακριβά περιστατικά της δεκαετίας ξεκίνησαν ακριβώς έτσι: από ένα bug «που κανείς δεν χρησιμοποιούσε» — μέχρι που κάποιος το χρησιμοποίησε πολύ καλά.

09

CVSS & τοπίο κινδύνου

Το επίσημο scoring είναι δουλειά των vendor/advisory teams. Παρακάτω δίνονται editorial εκτιμήσεις ανά σενάριο, για να μπουν στο risk register σου με σωστές προσδοκίες — όχι ως επίσημα scores.

ΣενάριοVector (CVSS v3.1, εκτίμηση)ScoreΣχόλιο
Worst case: ανοιχτό, unauthenticated delivery (π.χ. δημόσιος fetcher χωρίς φίλτρα)AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H9.8Attacker-controlled response path χωρίς τριβή.
Ρεαλιστικό: SSRF-gated delivery (γενικότερα: delivery-dependent AC:H)AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H8.1Το πιο συνηθισμένο πραγματικό σενάριο: ισχυρό bug, φραγμένος δρόμος.
Internal-only: adjacent network, περιορισμένη fetch επιφάνειαAV:A/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:H7.5Το segmentation μειώνει την πιθανότητα, όχι τη σοβαρότητα.

9.1 · Κλίμακα σοβαρότητας ανά σενάριο severity ladder

Worst case — open delivery
9.8
SSRF-gated (ρεαλιστικό)
8.1
Internal-only (segmented)
7.5

Πώς να το διαβάσεις: η σοβαρότητα του bug δεν αλλάζει — αλλάζει ο δρόμος. Το delivery gate (allowlists, έλεγχος redirects, φιλτράρισμα encodings) είναι το μόνο που κρατά ένα 9.8 θεωρητικό και ένα 8.1 πρακτικό. Αυτό ακριβώς δουλεύει το πλάνο μετριασμού.

10

Ανίχνευση: βρες αν είσαι εκτεθειμένος — σήμερα

10.1 · Asset inventory: τρία commands, τρία λεπτά triage

bash · έλεγχος εκθέσεων
# 1. Node.js runtime: πρέπει να είναι ≥ 22.23.4 / 24.22.1 / 26.12.1
node -p "process.versions.node"

# 2. Bun runtime: αναβάθμισε στην τελευταία έκδοση
bun --version

# 3. Python: υπάρχει brotli decoder στο environment;
python3 -c "import brotli" 2>/dev/null && echo "brotli: ΕΓΚΑΤΕΣΤΗΜΕΝΟ — έλεγξε έκδοση/advisory"
python3 -c "import brotlicffi" 2>/dev/null && echo "brotlicffi: ΕΓΚΑΤΕΣΤΗΜΕΝΟ — έλεγξε έκδοση/advisory"

# 4. Ποια έκδοση; (για τα αρχεία του περιστατικού)
pip show brotli brotlicffi 2>/dev/null | grep -E "Name|Version"

Σε κλίμακα υποδομής (μία φορά, όχι χειροκίνητα): φέρε τα δεδομένα από SBOM, container image scans και dependency resolution σε κεντρικό inventory. Ρώτα συγκεκριμένα: «ποιος τρέχει Node/Bun παλαιότερο από τις patched εκδόσεις;» και «ποια images περιέχουν brotli/brotlicffi;». Αν η απάντηση είναι «δεν ξέρουμε», αυτό είναι το πρώτο σου finding.

10.2 · Log hunting: ψάξε αν οι δοκιμές ήδη γίνονται hunting

bash · proxy / application logs
# Ποια upstream hosts στέλνουν br-encoded αποκρίσεις μέσω egress proxy;
grep -i "content-encoding: br" egress-access.log | sort | uniq -c | sort -rn | head

# Crash patterns: segfault/abort μέσα σε brotli symbols
grep -E "BrotliDecoder|brotli.*SEGV|bit_reader" application.log
11

Πλάνο μετριασμού: 0–24 ώρες, 7 μέρες, 30 μέρες

ΦΑΣΗ 1 · 0–24h

Σταμάτα την αιμορραγία

  • Αναβάθμισε όλα τα Node.js σε 22.23.4 / 24.22.1 / 26.12.1 (ή νεότερα) και το Bun στην τελευταία έκδοση. Rebuild images — όχι μόνο restart.
  • Σε Python environments όπου το brotli δεν είναι λειτουργική ανάγκη: pip uninstall brotli brotlicffi — η απουσία του πακέτου απενεργοποιεί τη διαπραγμάτευση br στους περισσότερους clients.
  • Σε egress proxies και CI: σκάλισε το Accept-Encoding (χωρίς br) για τους server-side fetchers.
  • Έλεγξε τα CI runners και τα unattended agents — είναι τα Tier 3 θύματα που κανείς δεν θυμάται.
ΦΑΣΗ 2 · 7 μέρες

Κλείσε τους δρόμους

  • Χαρτογράφησε κάθε server-side fetch: ποιες συναρτήσεις, ποια inputs τις τροφοδοτούν, ποια hosts επιτρέπονται. Μετέτρεψε σε egress allowlist ό,τι μπορεί.
  • Οπλίσε την ανίχνευση: rules για br-encoded αποκρίσεις από άγνωστους upstreams και alert σε shell-spawn από runtime διεργασίες.
  • Σβήσε τα SSRF φώτα: έλεγξε redirects (πολλοί fetchers ακολουθούν ανοιχτά redirects — εκεί πέφτει το SSRF gate), DNS rebinding, IP literals.
  • Container base images: rebuild από patched bases και κανόνες στο registry που μπλοκάρουν παλιές εκδόσεις.
ΦΑΣΗ 3 · 30 μέρες

Άλλαξε την αρχιτεκτονική

  • Κεντροποίησε την εξερχόμενη HTTP σε ένα wrapper: ένα σημείο policy για encodings, allowlist, timeouts, retries — και ένα σημείο logging για όλο το fetch surface.
  • Πρόσθεσε «native decoder drift» στη διαδικασία SBOM: τρύπες σε bundled C libraries δεν φαίνονται στο dependency tree — θέλουν image-level scanning.
  • Procurement rule: τα νέα SDKs/agents να δηλώνουν πώς κάνουν decompression και τι έχουν bundled. Ρώτα — είναι δωρεάν due diligence.
  • Tabletop exercise: «RCE σε runner/agent με cloud credentials» — 90 λεπτά που αποκαλύπτουν τα κενά σου πριν τα αποκαλύψει κάποιος άλλος.
nginx · egress proxy — strip brotli από server-side fetchers
# Ο proxy κάνει fetch για λογαριασμό applications; Μην αφήνεις το br να περάσει:
location / {
    proxy_set_header Accept-Encoding "identity";   # μη διαπραγματεύεσαι br
    proxy_hide_header Content-Encoding;            # και μην το κουβαλήσεις πίσω
    proxy_pass http://upstream;
}
12

FAQ — οι ερωτήσεις που θα σου κάνουν αύριο

Επηρεάζεται ο browser μου;
Σχετικά όχι. Οι μεγάλοι browsers διατηρούν δικές τους, ενεργά fuzzed υλοποιήσεις brotli decoders και τρέχουν σε sandboxed αρχιτεκτονική που κάνει το μονοπάτι memory-corruption→RCE δραματικά ακριβότερο. Το κέντρο βάρους του HTTP2Shell είναι τα server-side και infrastructure-side HTTP clients — όχι ο browser σου.
Το όνομα «HTTP2Shell» σημαίνει ότι αφορά το HTTP/2 πρωτόκολλο;
Όχι — και είναι η πιο συχνή παρανόηση. Το «2» σημαίνει «to»: HTTP-to-Shell. Το bug δεν σχετίζεται με το πρωτόκολλο HTTP/2 ούτε με smuggling τεχνικές του. Είναι καθαρά θέμα αποσυμπίεσης brotli στην πλευρά του client.
Έχω μόνο Python services — με αφορά;
Αν στα environments σου υπάρχει εγκατεστημένο το brotli ή το brotlicffi (ή κάποιο πακέτο που τα φέρνει ως dependency) και κάποιος HTTP client χρησιμοποιεί transparent brotli decompression — ναι. Η έκθεση δεν καθορίζεται από τη γλώσσα αλλά από την παρουσία του decoder και τον δρόμο των bytes.
Μπορώ απλώς να απεγκαταστήσω το brotli; Θα σπάσει κάτι;
Αν κανένα κρίσιμο path δεν βασίζεται σε brotli (σπάνιο για εσωτερικά APIs — τα περισσότερα δουλεύουν άψογα με gzip/identity), η απεγκατάσταση είναι η πιο άμεση μείωση surface. Έλεγξε για functionality που εξαρτάται από br (συνήθως bandwidth optimization σε εξωτερικά APIs) και κάνε staged rollout.
Δεν είναι στο CISA KEV — γιατί να βιαστώ;
Το KEV καταγράφει παρατηρηθείσα εκμετάλλευση, όχι δυνατότητα. Τα δημόσια PoCs υπάρχουν, η τεχνική λεπτομέρεια είναι public, και τα προηγούμενα X2Shell bugs έδειξαν γρήγορη οπλοποίηση. Όταν ένα bug μπει στο KEV, το παράθυρο έχει ήδη κλείσει για τους οργανισμούς που περίμεναν αυτό το σήμα.
Είναι ίδιο bug με το PHP2Shell;
Όχι — διαφορετικός κώδικας, διαφορετικό οικοσύστημα, διαφορετικά CVEs. Ανήκουν όμως στην ίδια κλάση: native parsers/decompressors που τρώνε untrusted bytes. Το κοινό είναι το pattern, όχι ο κώδικας — γι' αυτό τα αναλύουμε μαζί: ό,τι ισχύει για το delivery model του ενός ισχύει σε μεγάλο ποσοστό και για του άλλου.
Έχω WAF — με καλύπτει;
Μερικώς. Τα WAFs βλέπουν κυρίως requests και συχνά δεν inspectάρουν compressed response bodies προς τον client — οπότε το malicious br payload προς τον server-side fetcher σου μπορεί να περάσει αόρατο. Το WAF είναι χρήσιμο layer, αλλά εδώ η κύρια άμυνα είναι: patched runtimes και έλεγχος του fetch surface (allowlist, redirects, DNS).
Ποιο είναι το ένα action αν μπορώ να κάνω μόνο ένα;
Αναβάθμισε τα runtimes (Node/Bun) σε patched versions παντού — συμπεριλαμβανομένων των CI runners και των agents — και επιβεβαίωσέ το με inventory query, όχι με εμπιστοσύνη. Είναι η μόνη κίνηση που εξουδετερώνει το primitive ανεξαρτήτως delivery path.
13

Μίνι γλωσσάρι

Out-of-bounds (OOB) write

Εγγραφή δεδομένων εκτός των ορίων ενός buffer στη μνήμη. Πιο «πολύτιμη» από OOB read: μπορεί να οδηγήσει σε εκτέλεση κώδικα, όχι μόνο σε διαρροή.

Brotli

Αλγόριθμος συμπίεσης της Google (Content-Encoding: br), reference υλοποίηση σε C, που ενσωματώνουν δεκάδες runtimes και libraries.

Bundled library

C/C++ κώδικας που ενσωματώνεται απευθείας στη διεργασία ενός runtime — ίδιο heap, ίδιες permissions, κανένα sandbox ανάμεσα.

Transparent decompression

Η αυτόματη αποσυμπίεση ενός HTTP response από τον client βάσει του header Content-Encoding — χωρίς ρητή ενέργεια του developer.

Heap grooming

Τεχνική στοίχειωσης της μνήμης heap ώστε η διαβρώση να πέσει σε αντικείμενα/pointers που ωφελούν τον attacker.

SSRF

Server-Side Request Forgery: ο attacker πείθει ένα server-side component να κάνει request σε URL της επιλογής του. Το «on-ramp» του KC-A.

IMDS

Instance Metadata Service: το metadata endpoint των cloud VMs, από το οποίο κλέβονται credentials μετά από RCE. Δείτε KC-A, βήμα 6.

Egress allowlist

Κανόνας που επιτρέπει εξερχόμενες συνδέσεις μόνο σε εγκεκριμένους προορισμούς. Σπάει το KC-A στο βήμα 2.

SBOM

Software Bill of Materials: η «συνταγή» των components μιας εφαρμογής. Εδώ, με επέκταση και στα bundled native libraries — όχι μόνο στο dependency tree.

CISA KEV

Known Exploited Vulnerabilities Catalog: επίσημος κατάλογος ευπαθειών με παρατηρηθείσα ενεργή εκμετάλλευση. Compliance anchor για πολλούς οργανισμούς.

CVSS v3.1

Σύστημα βαθμολόγησης σοβαρότητας (0–10). Τα vectors του άρθρου είναι editorial εκτιμήσεις σεναρίων, όχι επίσημα scores.

Kill chain

Η αλυσίδα βημάτων από αρχική πρόσβαση έως τελικό στόχο. Σπάει κανείς ένα κρίκο, σταματά η επίθεση — δείτε τις Φάσεις 1–3.

14

Πηγές & receipts

Ό,τι αναφέρεται εδώ βασίζεται σε δημόσια διαθέσιμο υλικό την ώρα της σύνταξης (24/10/2026, 15:42 UTC). Κατηγορίες: ADVISORY για επίσημες πηγές, RESEARCH για ερευνητικές αναλύσεις, PRESS για δημοσιογραφική κάλυψη.

S1Aikido — Node2Shell: Node.js Brotli RCE (CVE-2026-111497) RESEARCHRoot cause, συνθήκες RCE, patched versions, ποιοι επηρεάζονται. S2Aikido — HTTP2Shell: Python packages vulnerable (brotli/brotlicffi) RESEARCHΗ τεκμηρίωση της επέκτασης του blast radius εκτός Node.js — η βάση της μετονομασίας. S3Brandefense — Node2Shell: Fixed Node.js Versions and Check ADVISORYΟι διορθωμένες εκδόσεις: 22.23.4, 24.22.1, 26.12.1. S4Cycode — node2shell: What to Patch in Node.js RESEARCHOut-of-bounds write στον bundled Brotli decoder (Node.js και Bun), προτεραιότητες patch. S5Wiz — PHP2Shell: AI uncovers critical RCE RESEARCHΗ γειτονική οικογένεια: RCE + Heartbleed-style memory disclosure, AI-assisted ανακάλυψη. S6Sansec — PHP2Shell RESEARCHPHP ≥ 5.4, συνθήκες exploit και η απαίτηση γνώσης του target. S7Huntress — php2shell, Leaked Critical PHP Vulnerabilities RESEARCHΧρονολόγηση δημοσιοποίησης (20/10) και λεπτομέρειες. S8Akamai — Understanding PHP2Shell RESEARCHΤεχνική ανάλυση των CVE-2026-109618/109619. S9NVD — CVE-2026-111497 & Node.js batch (CVE-2026-105481 → 106074) ADVISORYΕπίσημη καταγραφή ευπαθειών, CVSS vectors. S10CISA KEV Catalog ADVISORYΠροσθήκες 23/10: CVE-2026-114625 (Arista VeloCloud), CVE-2026-110447 (Collabora) — context της εβδομάδας. S11Exploit-DB — στοιχείο #52704 RESEARCHΔημόσιο PoC υλικό στην οικογένεια X2Shell (22/10). S12GitHub Advisory Database + fresh PoC repos RESEARCHΠαρακολούθηση νέων PoC repositories για Node2Shell/HTTP2Shell εντός του πρώτου 24ώρου.
Disclaimer & ενημερώσεις: Το άρθρο συντάχθηκε στις 24/10/2026 (15:42 UTC) με βάση δημόσια διαθέσιμες πηγές. Οι βαθμολογίες CVSS είναι editorial εκτιμήσεις σεναρίων — επίσημα θεωρούνται μόνο όσα δημοσιεύονται στα advisories των vendors και στο NVD. Η κατάσταση (PoCs, KEV, mitigations) εξελίσσεται: επιβεβαίωνε πάντα με τα επίσημα advisories πριν λάβεις παραγωγικές αποφάσεις. Το άρθρο θα ενημερωθεί όταν υπάρξουν ουσιαστικές αλλαγές (in-the-wild exploitation, νέα advisories, KEV προσθήκες).

Διαφάνεια: τα research & press receipts (S1–S8) ήταν δημόσιες αναλύσεις την ημέρα σύνταξης και μπορούν να αλλάξουν χωρίς προειδοποίηση — οι επίσημες homepages/advisories παραμένουν η τελική πηγή αλήθειας. Οι CVSS βαθμολογίες του άρθρου είναι editorial εκτιμήσεις σεναρίων, όχι επίσημα scores. Όλες οι πηγές δημόσια προσβάσιμες · το άρθρο δεν αποτελεί συμβουλευτική ασφαλείας.