TL; DR
ผู้ดูแลระบบ npm รายหนึ่งใช้เวลาหกสัปดาห์ในการเผยแพร่แพ็กเกจ "ยูทิลิตี้" TypeScript ปลอม เช่น ts-form-utils, ts-project-lintและ ts-enum-helper.
แม้ว่าแพ็กเกจเหล่านี้จะแสดงตัวช่วยตรวจสอบความถูกต้องขนาดเล็กที่ดูเหมือนถูกต้องตามกฎหมาย แต่เพย์โหลดที่แท้จริงจะทำงานเมื่อติดตั้งหรือเรียกใช้ครั้งแรก และจะทำการตรวจสอบลายนิ้วมือของโฮสต์ ค้นหาองค์กรใน GitHub โคลนที่เก็บ และขโมยซอร์สโค้ด
มัลแวร์นี้มุ่งเป้าไปที่องค์กรที่มีมูลค่าสูงบน GitHub โดยเฉพาะ ซึ่งรวมถึงองค์กรหลายแห่ง Shopify จากนั้นระบบจะจัดเก็บและดึงข้อมูลจากแหล่งเก็บข้อมูลต่างๆ ไปยังจุดรวบรวมข้อมูลส่วนกลาง
ในส่วนหนึ่งของขั้นตอนการโจมตีนั้น เพย์โหลดจะถูกแทรกเข้าไป commitส่งไฟล์ sa กลับเข้าไปในที่เก็บข้อมูลของเหยื่อในขณะที่ปลอมตัวเป็นตัวตนการเขียนโค้ดอัตโนมัติของ Google google-labs-jules[bot].
เราติดตามแคมเปญดังกล่าว — ซึ่งมีชื่อว่า จูลส์แจ็กเกอร์ — ครอบคลุมขอบเขตผู้เผยแพร่หลายรายและอย่างน้อยห้ารุ่นของเพย์โหลด รวมถึงเวอร์ชันที่เข้ารหัสและเวอร์ชันที่คำนึงถึงสภาพแวดล้อมแบบแซนด์บ็อกซ์
มัลแวร์สายพันธุ์ใหม่ล่าสุดนี้มุ่งเป้าไปที่โครงสร้างพื้นฐานสำหรับการวิเคราะห์มัลแวร์โดยเฉพาะ โดยจะทำงานเฉพาะภายในสภาพแวดล้อมการวิเคราะห์ ขโมยโทเค็นบัญชีบริการเมตาเดต้าบนคลาวด์ และตรวจสอบส่วนควบคุมของ Kubernetes และพื้นที่จัดเก็บข้อมูลบนคลาวด์
ตัวบ่งชี้การบุกรุกหลัก (IOC) ที่ใช้ร่วมกันในทุกรุ่นของเพย์โหลดคือจุดสิ้นสุดการรวบรวมข้อมูล aaronstack[.]com/jules-collect.
ระดับความรุนแรง: วิกฤต
การโจมตี: วิธีการทำงาน
แพ็กเกจ JulesJacker ทุกแพ็กเกจใช้แม่แบบเดียวกัน package.json โฆษณาตัวช่วย TypeScript ที่ไม่เป็นอันตราย มีใบอนุญาต MIT และไม่มีการเชื่อมโยงไปยังที่เก็บซอร์สโค้ด index.js แพ็กเกจนี้ส่งออกฟังก์ชันการทำงานจริงจำนวนหนึ่ง เช่น นิพจน์ปกติสำหรับอีเมล แผนที่ enum และตารางกฎการตรวจสอบโค้ด เพื่อให้นักพัฒนาที่นำเข้าแพ็กเกจนี้เห็นพฤติกรรมที่สมเหตุสมผล ส่วนเจตนาร้ายนั้นอยู่ที่อื่น: ใน... หลังการติดตั้ง ตะขอ หรือในบล็อกที่ด้านล่างของ index.js ซึ่งจะทำงานเมื่อมีการเรียกใช้โมดูลนั้น
ข้อมูลที่ส่งผ่านไปยังอุปกรณ์ต่างๆ ได้ผ่านขั้นตอนภายในที่มีหมายเลขกำกับไว้อย่างชัดเจน (ผู้ใช้งานเป็นผู้กำหนดหมายเลขให้กับเหตุการณ์ข้อมูลทางไกลด้วยตนเอง) สค1-, สค3-, สค4-(และอื่นๆ) และการติดตามวิวัฒนาการนั้นเป็นวิธีที่ชัดเจนที่สุดในการทำความเข้าใจแคมเปญนี้
รุ่นที่ 1–2: การสอดแนมและการขโมยไฟล์ git-config
แพ็กเกจรุ่นแรกๆ เป็นโปรแกรมขโมยข้อมูลโดยตรง เมื่อติดตั้งแล้ว โปรแกรมจะเก็บรวบรวมตัวแปรสภาพแวดล้อม ไฟล์ hosts ของ GitHub CLI และการกำหนดค่า git ทั่วโลก (git config –global –list, git remote -vจากนั้นจึงส่งชุดข้อมูลไปยังเอนด์พอยต์ของคอลเลกชันด้วยวิธีการ POST ซึ่งเป็นการสร้างเอกลักษณ์ของผู้ดำเนินการขึ้นมา ได้แก่ เรื่องราวปกปิดอย่าง "ยูทิลิตี้การตรวจสอบความถูกต้องของฟอร์ม TypeScript" สัญญาณส่งออกไปยังโดเมนเดียว และความชอบที่จะใช้ข้อมูลประจำตัวของนักพัฒนามากกว่าข้อมูลของผู้บริโภค
รุ่นที่ 3: โพรบหลบหนีไฮเปอร์ไวเซอร์และเคอร์เนล
เวอร์ชันหนึ่งในช่วงกลางแคมเปญได้เปลี่ยนกลยุทธ์อย่างเข้มข้นไปสู่การโจมตีโครงสร้างพื้นฐาน แทนที่จะขโมยการตั้งค่า มันได้ทำการสอดแนมและตรวจสอบระบบ AF_VSOCK ซ็อกเก็ต, พื้นที่ MMIO ของเวอร์ติโอ, / dev / memและแฟล็กการเสริมความแข็งแกร่งของเคอร์เนล และแม้กระทั่งการพยายามทำให้เคอร์เนลล่มโดยใช้ sysrq ซึ่งเป็นพฤติกรรมที่เกี่ยวข้องกับการพยายามออกจากเครื่องเสมือนหรือคอนเทนเนอร์ แท็กการวัดระยะทาง (s0-vmm-recon, s1-vmm-vsock-fuzz, s2-vmm-mmio, s3-kernel-probe) ทำให้เจตนาชัดเจน รูปแบบนี้มีจุดมุ่งหมายอย่างชัดเจนเพื่อ สภาพแวดล้อมคลาวด์แซนด์บ็อกซ์และเซิร์ฟเวอร์เลสรันเนอร์ — เครื่องเสมือน (VM) ชั่วคราวประเภทหนึ่งที่ใช้สร้างและทดสอบโค้ดที่ไม่น่าเชื่อถือ
รุ่นที่ 3 (SC3): เวิร์มการเขียนข้ามคลังเก็บข้อมูล
จุดศูนย์กลางของแคมเปญนี้กลายเป็นโปรแกรมขโมยข้อมูลแบบแพร่กระจายเอง เมื่อติดตั้งแล้ว เพย์โหลดจะทำงานตามลำดับเวลาห้าขั้นตอน:
- 0 เวที (~100 มิลลิวินาที): สร้างลายนิ้วมือให้กับโฮสต์ — ชื่อโฮสต์ ข้อมูลผู้ใช้ และข้อมูลประจำตัวของ Git
- 1 เวที (~3 วินาที): ตรวจสอบว่าเหยื่อสังกัดองค์กรใดโดยการตรวจสอบ git remote -vจากนั้นค้นหาค่าที่กำหนดไว้ตายตัว การกำหนดค่าองค์กร การเข้าถึงตารางและที่เก็บข้อมูลทดสอบด้วย git ls-remote — ถูกส่งผ่านพร็อกซี SSRF ที่ผู้โจมตีควบคุมไว้ที่ http://git@192.168.0.1:8080.
- 2 เวที (~10 วินาที): git clone บีบอัดโครงสร้างไฟล์ด้วย tarball และ gzip ในทุก repository ที่เข้าถึงได้ในรายการเป้าหมาย เข้ารหัสแบบ base64 และแยกข้อมูลออกเป็นส่วนๆ
- 3 เวที (~45 วินาที): “การพิสูจน์การเข้าถึง” — โคลน repository ที่เขียนได้ วางไฟล์ชื่อ SECURITY-POC.md แล้ว commit โดยตั้งค่าผู้เขียนเป็น google-labs-jules[bot] <161369871+google-labs-jules[bot]@users.noreply.github.com> และข้อความ chore: update dependency cache, then push to the victim's mainline branch.
รายการเป้าหมายที่กำหนดไว้ตายตัวนั้นไม่ใช่รายการทั่วไป มันระบุเป้าหมายมากกว่าสามสิบรายการ Shopify แหล่งเก็บข้อมูลตามชื่อ — Shopify/shopify, Shopify/เอกลักษณ์, Shopify/การเรียกเก็บเงิน, Shopify/vault, Shopify/ความลับ, Shopify/โครงสร้างพื้นฐาน, Shopify/.githubและอื่นๆ อีกมากมาย ควบคู่ไปกับองค์กรทดสอบ แอรอนสแต็คบาร์นส์ซึ่งผู้ดำเนินการดูเหมือนจะควบคุมและใช้เป็นเป้าหมายในการเขียน
รุ่นที่ 4 (SC4): เข้ารหัสและมีประตูควบคุม
เวอร์ชันใหม่ล่าสุดสำหรับนักพัฒนาได้เพิ่มกลไกการหลบเลี่ยงสองชั้นเพิ่มเติมจากเวิร์ม SC3
ประการแรก ข้อมูลที่ส่งไปจะไม่ถูกส่งในรูปแบบข้อความธรรมดาอีกต่อไป ตรรกะที่แท้จริงจะอยู่ในรูปแบบข้อมูลที่เข้ารหัสด้วย AES-256-CBC lib/.perf.datโดยมี IV อยู่ใน 16 ไบต์แรก ตัวโหลดใน index.js สร้างคีย์ถอดรหัสขึ้นใหม่จากส่วนของสตริงที่ต่อกัน ถอดรหัสข้อมูลดิบ และเรียกใช้ด้วย ฟังก์ชันใหม่()แม้แต่ชื่อโมดูลก็ยังถูกแบ่งออกเพื่อหลีกเลี่ยงโปรแกรมสแกนไวรัสแบบคงที่ — require('crypt' + 'o'), require('f' + 's').
ประการที่สอง ระบบนี้ถูกจำกัดการเข้าถึงโดยโฮสต์ มีเพียงเวอร์ชันเดียวเท่านั้นที่จะถอดรหัสและทำงานได้เมื่อ... os.hostname() เท่ากับ เดฟบ็อกซ์ or ubuntu-fc-uvm (ค่าเริ่มต้นของ Firecracker microVM) หรือมีสตริงย่อยอยู่ภายใน เดฟบ็อกซ์ประตูอีกบานหนึ่งขึ้นอยู่กับการมีอยู่ของ จูลส์/ ไดเรกทอรีการทำงาน:
กล่าวอีกนัยหนึ่งคือ เพย์โหลด SC4 ถูกออกแบบมาให้ทำงานในโหมดพักบนแล็ปท็อปของนักพัฒนาทั่วไป และจะตื่นขึ้นมาทำงานก็ต่อเมื่ออยู่ภายในเอเจนต์ AI อัตโนมัติเท่านั้น สภาพแวดล้อมแซนด์บ็อกซ์ จริงๆ แล้วผู้ดำเนินการต้องการประนีประนอม
การเปิดใช้งานห้องปฏิบัติการ: รูปแบบโครงสร้างพื้นฐานสำหรับการวิเคราะห์
แพ็กเกจที่แปลกใหม่ที่สุดในแคมเปญนี้ ts-enum-helperไม่ได้โจมตีนักพัฒนาหรือ Shopify แต่อย่างใด postinstall.sh เริ่มต้นด้วยประตูที่เผยความลับทั้งหมด:
สคริปต์จะไม่ทำอะไรเลยเว้นแต่จะมีการตั้งค่าตัวแปรสภาพแวดล้อมเฉพาะสำหรับแพลตฟอร์มวิเคราะห์มัลแวร์ เมื่อมีการตั้งค่าแล้ว เพย์โหลดจะรู้ว่ามันกำลังทำงานอยู่ภายในแซนด์บ็อกซ์ที่มีอยู่เพื่อตรวจสอบและศึกษาแพ็กเกจแบบนี้โดยเฉพาะ และมันจะทำการโจมตีตอบโต้
ขั้นตอนแรก ระบบจะดึงโทเค็น OAuth ของบัญชีบริการ GCP จากเซิร์ฟเวอร์เมตาเดตาของอินสแตนซ์และส่งออกมา จากนั้นใช้โทเค็นนั้นในการตรวจสอบข้อมูล คอนโทรลเพลนของ Kubernetes สามารถเข้าถึงได้ที่ kubernetes.default.svc:
- แสดงรายการ ClusterRoleBindings, ClusterRoles และ Nodes;
- ตรวจสอบพ็อด ข้อมูลลับ และคอนฟิกแมปทั่วทั้งระบบ ระบบคูเบ, ผิดนัด, คูเบ-สาธารณะ, kube-node-leaseและเนมสเปซสำหรับการวิเคราะห์;
- ฟังก์ชัน SelfSubjectAccessReview จะเรียกใช้เพื่อระบุอย่างชัดเจนว่าข้อมูลส่วนบุคคลที่ถูกขโมยไปนั้นได้รับอนุญาตให้ทำอะไรได้บ้าง
สุดท้ายแล้ว มันจะใช้การโจมตีแบบ Brute-force เพื่อตั้งชื่อ Bucket ของ Google Cloud Storage ที่สร้างขึ้นจาก ID โปรเจ็กต์ GCP ที่กำหนดไว้ตายตัว (rare-signer-437603-p9) และหมายเลขโครงการ โดยการเดาชุดค่าผสมต่างๆ เช่น *-สร้าง, *-สิ่งประดิษฐ์และอีกหลาย ๆ การวิเคราะห์- คำนำหน้า (ผลการวิเคราะห์, แพ็กเกจการวิเคราะห์, การสแกนมะเร็งทุกรหัสการตอบกลับและเนื้อหาจะถูกบันทึกและส่งกลับไปยังที่เดิมด้วยวิธีการ POST จูลส์-คอลเลคต์ จุดสิ้นสุด
นี่เป็นกรณีหายากของการโจมตีแบบเจาะระบบห่วงโซ่อุปทานที่สร้างขึ้นมาโดยเฉพาะเพื่อโจมตีโครงสร้างพื้นฐานของผู้ป้องกันเอง เรื่องราวที่ใช้เป็นข้ออ้างตลอดทั้งแคมเปญนั้น—ซึ่งบางส่วนปรากฏอยู่ภายในเพย์โหลดในรูปแบบของความคิดเห็นที่อธิบายพฤติกรรมว่าเป็น “การทดสอบแนวคิดการวิจัยด้านความปลอดภัย … การเขียนข้ามคลังเก็บข้อมูลผ่านโทเค็นพร็อกซี Git ที่เกินขอบเขต”—เป็นการให้เหตุผลเข้าข้างตัวเองแบบเดียวกัน ไม่ว่าเป้าหมายในการทำงานจะเป็นคลังเก็บข้อมูลแบบโมโนรีโพของ Shopify หรือเซิร์ฟเวอร์เมตาเดตาของคลัสเตอร์วิเคราะห์ก็ตาม
ไทม์ไลน์และขอบเขตการย้ายระบบ
JulesJacker ไม่ใช่การปล่อยของครั้งเดียวจบ มันคือปฏิบัติการต่อเนื่องที่รอดพ้นจากการถูกปิดทะเบียนโดยการเปลี่ยนชื่อเท่านั้น
| เมื่อ | อีเว้นท์ |
|---|---|
| กลางเดือนเมษายน 2026 | แพ็กเกจแรกๆ ปรากฏอยู่ภายใต้ขอบเขตของผู้เผยแพร่เดิม ได้แก่ TS-utility façade, environment และ git-config exfiltration |
| ต้นเดือนพฤษภาคม 2026 | มีการเผยแพร่เวอร์ชันการสอดแนมเพื่อหลบหนีจากไฮเปอร์ไวเซอร์และเคอร์เนลแล้ว |
| กลางถึงปลายเดือนพฤษภาคม 2026 | เวิร์ม SC3 ที่โจมตีแบบเขียนข้ามคลังเก็บข้อมูล ปรากฏพร้อมกับเพย์โหลดที่มุ่งเป้าไปที่ Shopify และ google-labs-jules[bot] การปลอมแปลงตัวตน SC4 นำเสนอตัวโหลดที่เข้ารหัส AES และควบคุมโดยโฮสต์ |
| ปลายเดือนพฤษภาคม 2026 | npm จะลบขอบเขตผู้เผยแพร่เดิมออก ชื่อแพ็กเกจจะถูกแปลงเป็นตัวแทนเก็บข้อมูลด้านความปลอดภัยที่ว่างเปล่า |
| สัปดาห์เดียวกัน | ผู้ดำเนินการจะย้ายไปใช้ขอบเขตที่ดูคล้ายคลึงกันเกือบทุกประการ และเผยแพร่เวิร์มอีกครั้ง รวมถึงเวอร์ชันโครงสร้างพื้นฐานสำหรับการวิเคราะห์ด้วย |
การย้ายฐานปฏิบัติการเป็นส่วนที่ฝ่ายป้องกันควรให้ความสนใจ การปิดฐานปฏิบัติการแรกไม่ได้ทำให้แคมเปญสิ้นสุดลงหรือแม้แต่ชะลอลง ผู้ปฏิบัติการได้สร้างฐานปฏิบัติการคู่ขนานขึ้นมาแล้ว ซึ่งมีชื่อแตกต่างจากฐานปฏิบัติการเดิมเพียงตัวอักษรเดียว และยังคงเผยแพร่ต่อไปภายในสัปดาห์เดียวกัน ณ เวลาที่เขียนบทความนี้ ฐานปฏิบัติการใหม่... ts-form-utils (เวอร์ชัน 1.0.0 ถึง 1.1.0) ts-project-lint (1.0.0 และ 1.1.0) และแบบสแตนด์อโลน ts-enum-helper (1.0.0) ยังคงสามารถติดตั้งได้
ตัวบ่งชี้การประนีประนอม
ตัวชี้วัดทั้งหมดด้านล่างได้รับการยืนยันกับซอร์สโค้ดของแพ็กเกจแล้ว
| ประเภท | ตัวบ่งชี้ | หมายเหตุ : |
|---|---|---|
| เครือข่าย (C2) | aaronstack[.]com/jules-collect | จุดรับส่งข้อมูลเดียวสำหรับทุกรุ่น รับข้อมูล telemetry ในรูปแบบ JSON และส่วนย่อยของไฟล์ tarball ที่เก็บข้อมูลในรูปแบบ base64-gzip |
| เครือข่าย (พร็อกซี SSRF) | http://git@192.168.0.1:8080 | ส่วนหน้าสำหรับโทเค็นพร็อกซี Git ที่มีขอบเขตการใช้งานกว้างเกินไป ซึ่งใช้ในการเข้าถึงที่เก็บข้อมูลขององค์กรเป้าหมาย |
| เครือข่าย (คลาวด์) | metadata.google.internal/computeMetadata/v1kubernetes.default.svcstorage.googleapis.com/storage/v1/b | ใช้เฉพาะในเวอร์ชันโครงสร้างพื้นฐานการวิเคราะห์สำหรับการขโมยโทเค็นและการสอดแนมระนาบควบคุมของ Kubernetes เท่านั้น |
| เอกลักษณ์ | google-labs-jules[bot]161369871+google-labs-jules[bot]@users.noreply.github.com | ปลอม commit อัตลักษณ์ของผู้เขียนถูกผลักดันเข้าไปในสาขาหลักของเหยื่อ |
| เนื้อไม่มีมัน | lib/.perf.dat | ข้อมูลดิบที่เข้ารหัสด้วย AES-256-CBC; IV ถูกเก็บไว้ใน 16 ไบต์แรก และคีย์ถูกสร้างขึ้นใหม่แบบไดนามิกใน index.js. |
| เนื้อไม่มีมัน | SECURITY-POC.md | ตกหล่นและ commitถูกส่งกลับไปยังฐานข้อมูลเหยื่อพร้อมข้อความ chore: update dependency cache. |
| เนื้อไม่มีมัน | scripts/postinstall.sh | มีประตูทางเข้า $MALYSIS_ANALYSIS_IDระบุตัวแปรที่กำหนดเป้าหมายโครงสร้างพื้นฐานการวิเคราะห์ |
| เกี่ยวกับพฤติกรรม | os.hostname() ตรวจสอบ devbox / ubuntu-fc-uvm | มีการตรวจสอบสภาพแวดล้อมแบบแซนด์บ็อกซ์และเอเจนต์ AI ก่อนการถอดรหัสและการประมวลผลข้อมูล |
| เกี่ยวกับพฤติกรรม | .jules/ และ /app/.jules ไดเร็กทอรีอ่าน | การกำหนดเป้าหมายอย่างชัดเจนไปยังสภาพแวดล้อมการทำงานของเอเจนต์ AI |
| เกี่ยวกับพฤติกรรม | sc1-, sc3-, sc4-, s0-vmm-recon | ป้ายกำกับอุปกรณ์วัดระยะทางที่ผู้ปฏิบัติงานกำหนดเอง มีประโยชน์สำหรับการตรวจจับและการค้นหา |
| เป้าหมายคลาวด์ | rare-signer-437603-p9malysis-* การเดาแบบถัง | ตัวระบุโครงการ GCP และรูปแบบการแจงนับบัคเก็ตจัดเก็บข้อมูลที่ถูกกำหนดไว้ตายตัวฝังอยู่ในตัวแปรโครงสร้างพื้นฐานการวิเคราะห์ |
| รูปทรงบรรจุภัณฑ์ | ส่วนหน้าของแพ็คเกจยูทิลิตี้ TS ที่ไม่มีฟิลด์ที่เก็บข้อมูล | แม่แบบแคมเปญที่สอดคล้องกัน: แพ็กเกจยูทิลิตี้ TypeScript ปลอมที่มีเพย์โหลดที่เป็นอันตรายฝังอยู่ภายใน postinstall hooks หรือแนบมาด้วย index.js. |




