TL; DR
กลุ่มของ แพ็กเกจ npm ห้าแพ็กเกจเผยแพร่ผ่านบัญชีสองบัญชี และจัดส่งสินค้า postinstall ฮุกที่อ่านข้อมูลรับรองการเข้าถึงระบบคลาวด์จากโฮสต์และส่งออกไปภายนอกเครื่อง แพ็กเกจเหล่านี้มีชื่อที่ฟังดูเหมือนผีและละเมิดลิขสิทธิ์ — coral-wraith, ecto-corsair-whisper-6f3b9, ecto-corsair-flag-x9m4, ecto-rust-read-f3a9c1, ecto-nightly-spirit — และแปลงสิ่งที่พวกเขารวบรวมได้ทั้งหมดให้เป็นของปลอม ecto_module: ตรวจสอบไฟล์ YAML manifest ก่อนส่ง เราติดตามคลัสเตอร์ดังนี้ ชั้นนอกสุดของโปรโตปลาสวึม.
โค้ดส่วนนี้จะทำงานก็ต่อเมื่อตรวจพบสภาพแวดล้อมที่เฉพาะเจาะจงเท่านั้น นั่นคือ โฮสต์ที่มีชื่อเป็น สตริงเลขฐานสิบหก 12 ตัวอักษร และไดเร็กทอรีการทำงานภายใต้ /app/node_modules — รูปทรงของการสร้างแบบคอนเทนเนอร์หรือเวิร์กเกอร์ CI เมื่อผ่านด่านนั้นแล้ว ฮุกจะสอบถาม บริการข้อมูลเมตาของอินสแตนซ์ AWS (IMDSv2) สำหรับข้อมูลประจำตัวบทบาท IAM จะแสดงรายการต่างๆ ผู้จัดการความลับของ AWS ครอบคลุมสามภูมิภาค แสดงค่าตัวแปรสภาพแวดล้อม และอ่านไฟล์ภายใต้ /appและค้นหาสตริงสำหรับเกมจับธง จากนั้นจะส่งผลลัพธ์ออกไปสองทาง: จากบีคอนไปยัง... webhook.site ตัวเก็บรวบรวมและรายการ PUT ที่แสดงไปยังปลายทาง IP ดิบ พร้อมด้วยรายการตัวเลือกสำรองที่เริ่มต้นด้วย localhost
คำอธิบายแพ็กเกจในภายหลังระบุว่า "เพย์โหลด CTF สำหรับการทดสอบห่วงโซ่อุปทานของ Verdaccio" เราได้รายงานคำอธิบายตนเองนั้นว่าเป็นข้อเท็จจริงที่สังเกตได้ พฤติกรรมนั้นเอง — การส่งออกไปยัง IP สาธารณะแบบเรียลไทม์ การอ่านข้อมูลประจำตัว IMDS จริง การเรียกใช้ Secrets Manager จริง — ก็คือสิ่งนั้นไม่ว่าจะมีป้ายกำกับอะไรก็ตาม และนั่นคือเหตุผลที่เวอร์ชันเหล่านี้ถูกจัดว่าเป็นมัลแวร์
มีชื่อหนึ่งในกลุ่มนั้น coral-wraithและไม่ได้หยุดอยู่แค่การเผยแพร่เพียงครั้งเดียว แต่ยังเผยแพร่ซ้ำอย่างรวดเร็วในหลายสิบเวอร์ชันภายในเวลาไม่กี่ชั่วโมง — 1.0.0 การปีนขึ้นไป 6.0.0 — และการพิมพ์ครั้งก่อนหน้านี้ที่มีชื่อเดียวกันได้ใช้การขยายขนาด 9999.0.x หมายเลขเวอร์ชัน รูปทรงคลาสสิกของ ความพยายามสร้างความสับสนในการพึ่งพาตลอดช่วงเวลานั้น ข้อมูลที่ส่งไปนั้นพัฒนาขึ้นอย่างเห็นได้ชัด: จากบีคอนระบุโฮสต์แบบครั้งเดียว กลายเป็นตัวกลางข้อมูลรับรอง AWS ที่สมบูรณ์แบบ ซึ่งห่อหุ้มด้วยการตรวจสอบสภาพแวดล้อมที่ทำให้ข้อมูลนั้นไม่ปรากฏให้เห็นภายนอกเป้าหมายที่ตั้งใจไว้
| แบบรวดเร็ว | 5 ชื่อ; coral-wraith ตีพิมพ์ซ้ำเพียงฉบับเดียวในหลายสิบเวอร์ชัน |
| ระบบนิเวศ (Ecosystem) | NPM |
| ติดตั้งเวกเตอร์ | postinstall สคริปต์วงจรชีวิต |
| เป้าหมายหลัก | ข้อมูลประจำตัวบทบาท AWS IAM + ค่าลับของ Secrets Manager, ตัวแปรสภาพแวดล้อม, /app ไฟล์ |
| อพยพ | webhook.site บีคอน + IP ดิบ C2 PUT |
| ประตูทริกเกอร์ | ชื่อโฮสต์แบบ 12 เลขฐานสิบหก + /app/node_modules cwd บวกกับการตรวจสอบสภาพแวดล้อมที่ระงับเพย์โหลดนอกบริบทนั้น |
| ความรุนแรง | สูง — การเปิดเผยข้อมูลประจำตัวระบบคลาวด์และข้อมูลลับที่ได้รับการจัดการจาก สภาพแวดล้อมการสร้างและรันไทม์แบบคอนเทนเนอร์ |
กายวิภาคการโจมตี
ทุกแพ็กเกจในคลัสเตอร์ถูกสร้างขึ้นด้วยวิธีเดียวกัน: เกือบว่างเปล่า index.js (โมดูล.ส่งออก = {}), บรรทัดเดียว package.json บท — “postinstall”: “node postinstall.js” — และน้ำหนักบรรทุกใน postinstall.jsการติดตั้งแพ็กเกจก็เพียงพอแล้วที่จะเรียกใช้ hook ไม่จำเป็นต้องนำเข้าหรือเรียกใช้ฟังก์ชันใดๆ เพิ่มเติม
ประตูกำหนดเป้าหมาย ก่อนที่จะทำอะไรก็ตาม ยานอวกาศตระกูลเอคโตจะตรวจสอบสภาพแวดล้อมโดยรอบก่อน:
function isAppWorker(): host = os.hostname() if host does NOT match /^[0-9a-f]{12}$/ -> exit if cwd does NOT contain "/app/node_modules" -> exit if cwd contains "/tmp/npm-safe" -> exit otherwise -> proceed ชื่อโฮสต์แบบ 12 เลขฐานสิบหกเป็นรูปแบบเริ่มต้นที่ Docker กำหนดให้กับคอนเทนเนอร์ และ /app/node_modules เป็นเส้นทางการติดตั้งภายในคอนเทนเนอร์แบบทั่วไป เงื่อนไขข้อที่สามจะยกเลิกหากเส้นทางนั้นดูเหมือนไดเร็กทอรีการแตกไฟล์แบบแซนด์บ็อกซ์ ผลลัพธ์โดยรวมคือ เพย์โหลดจะอยู่ในสถานะหยุดนิ่งบนแล็ปท็อปของนักพัฒนาหรือแซนด์บ็อกซ์สำหรับการวิเคราะห์ และจะทำงานก็ต่อเมื่ออยู่ภายในคอนเทนเนอร์สำหรับการสร้างหรือรันไทม์เท่านั้น ซึ่งเป็นสภาพแวดล้อมที่มีแนวโน้มที่จะมีข้อมูลรับรองระบบคลาวด์แบบเรียลไทม์ แพ็กเกจที่เก่าที่สุดในคลัสเตอร์ ผีปะการังไม่มีเกตดังกล่าวและเรียกใช้คอลเลกชัน (ที่เรียบง่ายกว่า) โดยไม่มีเงื่อนไข
ชุดเมื่อประตูเปิดออก ตะขอจะยื่นออกมาทางด้านล่าง execFileSync(“/bin/sh”, [“-c”, …]) และเรียกใช้คำสั่งผสมเพียงคำสั่งเดียวซึ่งเรียงลำดับดังนี้:
1. PUT /latest/api/token to 169.254.169.254 (IMDSv2 token request) 2. GET .../iam/security-credentials/ (IAM role name) 3. GET .../iam/security-credentials/<role> (temporary credentials) 4. dump env | sort (environment variables) 5. list /app (excl. node_modules) + cat first 15 (application files) 6. aws secretsmanager list-secrets (us-east-1, eu-west-1, eu-central-1) 7. scrape readable files for HTB{...} (capture-the-flag strings) ขั้นตอนที่ 1–3 เป็นตัวอย่างการดึงข้อมูล IMDSv2 ตามตำรา: ขอโทเค็นเซสชัน จากนั้นแนบโทเค็นนั้นเป็นข้อมูลอ้างอิง X-aws-ec2-metadata-token ส่วนหัวเพื่อดึงบทบาท IAM ของอินสแตนซ์และคีย์การเข้าถึงชั่วคราวของบทบาทนั้น การเลือกใช้ IMDSv2 แทนที่จะใช้ IMDSv1 ที่ง่ายกว่าและไม่ต้องมีการตรวจสอบสิทธิ์ GET สิ่งที่ควรทราบคือ นั่นหมายความว่าเพย์โหลดจะทำงานได้แม้ในอินสแตนซ์ที่กำหนดค่าให้ต้องใช้การเข้าถึงเมตาเดต้าแบบใช้โทเค็น ซึ่งเป็นการรักษาความปลอดภัยที่ AWS แนะนำ ข้อมูลประจำตัวที่ส่งคืนโดยขั้นตอนที่ 3 มีอายุสั้น รหัสการเข้าถึง/คีย์การเข้าถึงลับ/เหรียญ ข้อมูลสามส่วน (triples) ที่กำหนดขอบเขตตามบทบาทของอินสแตนซ์นั้นๆ กล่าวคือ ผู้ถือครองคีย์เหล่านั้นสามารถทำสิ่งใดก็ตามที่บทบาทนั้นสามารถทำได้ ตลอดอายุการใช้งานของข้อมูลรับรองนั้น
ขั้นตอนที่ 4–6 ขยายขอบเขตการเก็บเกี่ยวให้กว้างขึ้น env ไฟล์ dump จะบันทึกทุกอย่างที่กระบวนการสร้างหรือรันไทม์ได้รับสืบทอดมา ซึ่งในทางปฏิบัติแล้วมักจะเป็นโทเค็นรีจิสทรี สตริงการเชื่อมต่อฐานข้อมูล และคีย์ API / app ฟังก์ชัน file walk สามารถอ่านไฟล์แอปพลิเคชันได้มากถึงสิบห้าไฟล์จากภายนอก node_modulesซึ่งสามารถแสดงการกำหนดค่าพื้นผิวได้ .env ไฟล์ หรือแหล่งที่มา ขั้นตอนที่ 6 เรียกใช้ aws secretsmanager list-secrets ในสามภูมิภาค ข้อมูลประจำตัวที่ดึงมาในขั้นตอนที่ 1–3 นั้นเป็นสิ่งที่ใช้ตรวจสอบความถูกต้องของการเรียกเหล่านั้น ดังนั้นการอ่าน IMDS และการแจงนับ Secrets Manager จึงเชื่อมโยงกันเป็นลำดับการยกระดับเดียว: บทบาทของอินสแตนซ์ → รายการข้อมูลลับที่จัดการ ขั้นตอนที่ 7 เป็นการอ้างอิงถึงกรอบของเกมจับธง — เมื่อ เอชทีบี{…} หากพบธง ระบบจะส่งธงไปโดยลำพัง แต่ถ้าไม่พบธง ข้อมูลดิบที่รวบรวมได้จะถูกแบ่งออกเป็นสี่ส่วนแล้วส่งไป
เวอร์ชันต่อมาในกลุ่มนี้ได้ยกระดับการทำงานไปอีกขั้น แทนที่จะหยุดอยู่ที่การตรวจสอบสินค้าคงคลัง พวกมันจะวิเคราะห์การตอบสนองของ IMDS และส่งออกคีย์ชั่วคราวเป็น AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY / โทเค็นเซสชัน AWS ตัวแปรสภาพแวดล้อม ยืนยันตัวตนด้วย aws sts get-caller-identityจากนั้นวนลูปตรวจสอบความลับทุกรายการที่ส่งคืนโดย รายการความลับ โทร aws secretsmanager get-secret-value ในแต่ละรายการ — ดึงเนื้อหาลับ ไม่ใช่แค่ชื่อของมัน เวอร์ชันเดียวกันนี้ยังอ่านไบนารีแฟล็กที่แทนที่ด้วยกระบวนการ (/อ่านแฟล็ก และเพื่อนๆ) และพยายาม ชาร์จวิ่ง ต่อต้านโปรเจ็กต์ Rust ใดๆ ที่พบภายใต้ / appขยายขอบเขตการเก็บเกี่ยวให้กว้างขึ้น นอกเหนือจากข้อมูลประจำตัวบนคลาวด์ ไปสู่ทุกสิ่งที่สภาพแวดล้อมการสร้างเปิดเผยออกมา
เวอร์ชันรุ่นหลังๆ เหล่านี้ยังมีการควบคุมที่เข้มงวดมากขึ้นด้วย นอกเหนือจากชื่อโฮสต์แบบ 12 เลขฐานสิบหกและ /app/node_modules เมื่อตรวจสอบแล้ว เพย์โหลดจะตรวจสอบการกำหนดค่ารีจิสทรีแพ็กเกจที่ใช้งานอยู่และเส้นทางไดเร็กทอรีการทำงาน และจะหยุดทำงานโดยไม่แสดงข้อความใดๆ เมื่อพบว่าเป็นการวิเคราะห์หรือบริบทการจำลอง แทนที่จะเป็นเป้าหมายที่ใช้งานอยู่ ผลรวมคือเพย์โหลดที่ไม่แสดงการกระทำใดๆ ที่สังเกตได้ในสภาพแวดล้อมการตรวจสอบส่วนใหญ่ และจะทำการรวบรวมข้อมูลทั้งหมดเฉพาะเมื่อตรวจสอบแล้วว่าอยู่บนโฮสต์คอนเทนเนอร์ที่แท้จริง
การกรองข้อมูลที่รวบรวมได้จะถูกส่งออกจากโฮสต์ผ่านสองช่องทาง ช่องทางแรกคือสัญญาณบีคอน POST ไปยังค่าคงที่ เว็บฮุค.ไซต์ ตัวเก็บรวบรวมข้อมูลจะเก็บชื่อโฮสต์ รหัส UID ตัวเลข ไดเร็กทอรีการทำงาน และข้อมูลที่รวบรวมได้สูงสุด 120 KB ประการที่สอง ข้อมูลจะถูกรวมเข้าไว้ใน "รายการโมดูล" ปลอมในรูปแบบ YAML และ PUT ไปยัง /api/modules/ บนเซิร์ฟเวอร์เป้าหมาย:
ecto_module: name: "<flag-or-chunk-0>" version: "1.0.0" power_level: "<chunk-1>" ship_deck: "<chunk-2>" cargo_hold: "<chunk-3>" ชื่อฟิลด์ของรายการ (ระดับพลังงาน, ดาดฟ้าเรือ, ห้องเก็บสินค้า) เป็นเพียงการตกแต่ง — ข้อมูลที่ถูกขโมยจะซ่อนอยู่ภายในค่าสตริง ซึ่งเป็นเหตุผลว่าทำไมโปรแกรมตรวจสอบเครือข่ายจึงเห็นสิ่งที่ดูเหมือนการอัปโหลดไฟล์ manifest ของ package-registry ที่ไม่เป็นอันตราย แทนที่จะเป็นการดัมพ์ข้อมูลอย่างชัดเจน ช่องสัญญาณบีคอนยังส่งข้อมูลมากกว่านั้นด้วย: POST ร่างกายถึง เว็บฮุค.ไซต์ ประกอบด้วยชื่อโฮสต์, UID ตัวเลข, ไดเร็กทอรีการทำงาน และข้อมูลไบนารีที่รวบรวมได้สูงสุด 120 KB ดังนั้นแม้การส่งสัญญาณเพียงครั้งเดียวก็ให้ข้อมูลครบถ้วน เว็บฮุค.ไซต์ เป็นบริการตรวจสอบคำขอฟรี การใช้งานเป็นตัวรวบรวมข้อมูลหมายความว่าผู้ให้บริการไม่จำเป็นต้องสร้างโครงสร้างพื้นฐานการรับข้อมูลของตนเองสำหรับช่องทางนั้น และคำขอที่บันทึกไว้จะคงอยู่ในที่เก็บข้อมูลของบริการ
การประกาศ PUT เดินตามรายการสำรองที่เริ่มต้นด้วยหลายรายการ 127.0.0.1/localhost ท่าเรือต่างๆ แล้วจึงส่งต่อไปยังที่อยู่สาธารณะสามแห่งใน `154.57.164.0/24` โดยจะหยุดที่ปลายทางแรกที่ตอบกลับด้วยสถานะ 2xx ลำดับการเริ่มจาก localhost นั้นสอดคล้องกับคำอธิบายตนเองของ "การทดสอบ verdaccio" (รีจิสทรีภายในเครื่องบน loopback) แต่การใช้ IP สาธารณะเป็นตัวสำรองหมายความว่าข้อมูลจะออกจากโฮสต์เมื่อใดก็ตามที่ loopback ไม่ได้กำลังรับฟังอยู่ ซึ่งก็คือในเครื่องใดๆ ก็ตามที่ไม่ใช่เครื่องทดสอบของผู้เขียนเอง
ปฏิบัติการ
กลุ่มข้อมูลแสดงให้เห็นถึงการเติบโตของความสามารถทีละน้อย ไม่ใช่การลดลงเพียงครั้งเดียว เราจัดเรียงตามพฤติกรรมที่สังเกตได้ ไม่ใช่ตามเวลาที่เผยแพร่:
| ระยะ | แพ็คเกจ / เวอร์ชัน | พฤติกรรม |
|---|---|---|
| วิ่งเร็ว | coral-wraith 9999.0.x | หมายเลขเวอร์ชันที่สูงเกินจริงซึ่งสอดคล้องกับความพยายามสร้างความสับสนในการพึ่งพา การแจงนับระหว่างการติดตั้งและการดึงข้อมูลออก |
| เมล็ดพันธุ์ | coral-wraith 1.0.0 | postinstall จะรวบรวมไฟล์ id/env/flag; ส่งคำสั่ง PUT ครั้งเดียวไปยัง 154[.]57[.]164[.]71:30782เครื่องหมาย ECT-472839 |
| การวนซ้ำอย่างรวดเร็ว | coral-wraith 1.0.1 → 6.0.0 | มีการปล่อยข้อมูลหลายสิบรายการภายในเวลาไม่กี่ชั่วโมง; เพย์โหลดได้รับ... isAppWorker() ประตู, การดึงข้อมูลประจำตัว IMDSv2, แบบเต็ม get-secret-value การตรวจสอบสภาพแวดล้อมรีจิสทรี/พาธ และเครื่องหมายซิงค์คู่ ถือเป็นจุดหมุน |
| ชื่อคู่ขนาน | ecto-corsair-whisper-6f3b9 1.0.14–1.0.18 | บรรทุกสัมภาระที่มีประตูควบคุมแบบเดียวกัน; webhook.site บีคอนและรายการสำรองปลายทางหลายจุด |
| สายพันธุ์ | ecto-rust-read-f3a9c1 1.0.1–1.0.2 | เพิ่มเครื่องหมายอ่างล้างจานเพิ่มเติม ECT-987654, ECT-654321, ECT-839201 |
| สายพันธุ์ | ecto-corsair-flag-x9m4 1.0.0, ecto-nightly-spirit 1.1.0 | เพย์โหลดแบบเดียวกัน ระบบควบคุมและสั่งการ (C2) และบีคอนแบบเดียวกัน |
ลักษณะเด่นของกลุ่มซอฟต์แวร์นี้คือจังหวะการเผยแพร่: แทนที่จะเป็นแพ็กเกจเดียวและเวอร์ชันเดียว ชื่อเดียวกันจะถูกเผยแพร่ซ้ำแล้วซ้ำเล่าอย่างรวดเร็ว โดยแต่ละเวอร์ชันจะเป็นเพียงการเปลี่ยนแปลงเล็กน้อยจากเวอร์ชันก่อนหน้า พร้อมกับเวอร์ชันย่อยที่มีชื่อแตกต่างกันอีกจำนวนหนึ่งซึ่งมีเนื้อหาเดียวกัน กระซิบ โค้ดของครอบครัวนี้แยกออกเป็นสองลายนิ้วมือที่ใกล้เคียงกัน — ชุดหนึ่งตรวจจับสองจุดสำคัญ อีกชุดตรวจจับสามจุด (จุดอ่านไฟล์เพิ่มเติม) — แต่ทั้งสองชุดให้ผลลัพธ์เป็นข้อมูลเดียวกัน ความแตกต่างอยู่ที่การเปลี่ยนแปลงของโค้ด ไม่ใช่การแยกพฤติกรรม เวอร์ชันของ กระซิบ นอกเหนือจากช่วงที่วิเคราะห์ (อย่างน้อยถึง 1.0.25 ในขณะที่เขียน) พบว่ามีการใช้งานจริงในทะเบียน และ ผีปะการัง ชื่อนั้นยังคงไต่ระดับเวอร์ชันของตัวเองขึ้นไปเหนือหน้าต่างบานเดิม
ตัวชี้วัดของการประนีประนอม
ตัวชี้วัดทั้งหมดด้านล่างนี้ถูกดึงมาจากซอร์สโค้ดของแพ็กเกจบนดิสก์ ตัวชี้วัดเครือข่ายถูกตัดทอนแล้ว
เครือข่าย
| ตัวบ่งชี้ | บทบาท |
|---|---|
hxxp://154[.]57[.]164[.]71:30782 | เป้าหมาย C2 PUT (coral-wraith) |
hxxp://154[.]57[.]164[.]80:30543 | C2 PUT fallback (ecto-*) |
hxxp://154[.]57[.]164[.]82:31250 | C2 PUT fallback (ecto-*) |
hxxp://154[.]57[.]164[.]71:31289 | C2 PUT fallback (ecto-*) |
hxxps://webhook[.]site/602a4c72-7033-4e28-92ea-dc66e59206e5 | ตัวเก็บรวบรวมสัญญาณ |
169[.]254[.]169[.]254/latest/... | การอ่านข้อมูลรับรอง IMDSv2 (ฝั่งเป้าหมาย เมตาเดต้า AWS) |
พฤติกรรม/ไฟล์
| ตัวบ่งชี้ | บทบาท |
|---|---|
"postinstall": "node postinstall.js" | ติดตั้งเวกเตอร์ |
ecto_module: YAML พร้อม power_level / ship_deck / cargo_hold กุญแจ | แผนผังรายการส่งออก |
เครื่องหมายอ่างล้างจาน ECT-472839, ECT-987654, ECT-654321, ECT-839201 | ส่วนเส้นทาง C2 /api/modules/<marker> |
isAppWorker() ประตู: โฮสต์ /^[0-9a-f]{12}$/cwd ประกอบด้วย /app/node_modules | เงื่อนไขการเปิดใช้งาน |
aws secretsmanager list-secrets เกินกว่า us-east-1, eu-west-1, eu-central-1 | การแจงนับความลับ |
HTB{...} การดึงข้อมูลด้วย regex | การเก็บเกี่ยวแบบจับธง |
ค่าแฮชของไฟล์ (sha256, บันทึกได้ในระหว่างการวิเคราะห์)
| เนื้อไม่มีมัน | sha256 |
|---|---|
coral-wraith/postinstall.js | ce5ff035cfdfed1d0015446424b352c27b66bcb77e9fdb0a51e4245199146824 |
ecto-corsair-whisper-6f3b9 1.0.18/postinstall.js | b58432acba376aa6976f0490d9a1c04257ccdbc856d8390260c50322d63e31c3 |
การระบุสาเหตุและพฤติกรรมที่สังเกตได้
ชื่อแพ็กเกจทั้งห้าชื่อถูกเผยแพร่ภายใต้บัญชี npm สองบัญชี แต่พวกมันมีโครงสร้างพื้นฐานร่วมกันมากพอที่จะถือว่าเป็นคลัสเตอร์เดียวกัน ecto_module แผนผังแสดงรายละเอียด เหมือนกัน ECT-472839 เครื่องหมายอ่างล้างจานหลัก เหมือนกัน เว็บฮุค.ไซต์ รหัสผู้เก็บรวบรวมและปลายทาง C2 อยู่ในที่เดียวกัน บล็อก `154.57.164.0/24` แพ็กเกจเมล็ดพันธุ์ (`coral-wraith`)(เรียบง่ายกว่าและไม่มีการควบคุม) และตระกูล ecto ที่มีการควบคุมจึงถูกมองว่าเป็นการพัฒนาต่อยอดจากชุดเครื่องมือเดียวกัน มากกว่าจะเป็นความพยายามที่แยกจากกัน
ในเวอร์ชันต่อมา แพ็กเกจเหล่านี้จะอธิบายตัวเองดังนี้ “ข้อมูล CTF สำหรับการทดสอบห่วงโซ่อุปทานของ Verdaccio” เราแสดงป้ายกำกับนั้นในฐานะข้อเท็จจริงที่สังเกตได้ และไม่ได้กล่าวซ้ำว่าเป็นข้อค้นพบเกี่ยวกับจุดประสงค์ สิ่งที่โค้ดทำนั้นชัดเจนและไม่ขึ้นอยู่กับวิธีการติดป้ายกำกับ: มันอ่านข้อมูลประจำตัวบทบาท IAM จากบริการเมตาเดตาของอินสแตนซ์ แสดงรายการความลับที่ได้รับการจัดการในสามภูมิภาคของ AWS และส่งผลลัพธ์ไปยัง IP สาธารณะและตัวเก็บรวบรวมเว็บฮุคของบุคคลที่สาม ชุดทดสอบแบบวนรอบอย่างเดียวที่แท้จริงจะไม่ต้องการรายการสำรอง IP สาธารณะ การอ่านข้อมูลประจำตัว IMDS หรือการเรียกใช้ Secrets Manager ข้ามภูมิภาค เนื่องจากขาออกและการเข้าถึงข้อมูลประจำตัวนั้นเป็นของจริง เวอร์ชันที่มีการจำกัดการเข้าถึงจึงถูกจัดว่าเป็นอันตราย
คุณสมบัติที่โดดเด่นที่สุดในเชิงปฏิบัติคือ เกตที่ใช้งานได้เฉพาะในคอนเทนเนอร์เท่านั้น มันเป็นทั้งมาตรการหลบเลี่ยง – ทำให้เงียบในแล็ปท็อปและในสภาพแวดล้อมการวิเคราะห์ – และเป็นมาตรการกำหนดเป้าหมาย โดยจะทำงานเฉพาะในที่ที่มีบทบาท IAM จริงและข้อมูลลับที่ใช้งานอยู่ นักวิเคราะห์ที่เรียกใช้แพ็กเกจเหล่านี้ในสภาพแวดล้อมทั่วไปจะไม่พบอะไรเลย พฤติกรรมนี้จะปรากฏขึ้นเฉพาะภายใต้ชื่อโฮสต์แบบ Docker และเส้นทางการติดตั้งภายในคอนเทนเนอร์เท่านั้น
ผลกระทบ แนวโน้ม และคำแนะนำสำหรับกองหลัง
ความเสี่ยงในที่นี้คือการเปิดเผยข้อมูลประจำตัวระบบคลาวด์และข้อมูลลับภายในคอนเทนเนอร์สำหรับการสร้างและรันไทม์ ข้อมูลประจำตัวบทบาท IAM ที่ดึงมาจาก IMDS จะมีสิทธิ์อนุญาตตามที่บทบาทนั้นมีอยู่ secretsmanager:ListSecrets (และผลสืบเนื่องใดๆ) รับค่าความลับ(ขยายขอบเขตไปถึงความลับของแอปพลิเคชันที่จัดเก็บไว้) การดัมพ์ตัวแปรสภาพแวดล้อมมักจะมีโทเค็นรีจิสทรี URL ของฐานข้อมูล และคีย์ API ในบริบทของ CI หรือคอนเทนเนอร์ ซึ่งเป็นสิ่งที่เกตเวย์เลือกใช้ การติดตั้งแบบส่งต่อเพียงครั้งเดียวของแพ็กเกจเหล่านี้ก็เพียงพอที่จะทำให้ข้อมูลเหล่านั้นรั่วไหลได้
Ectoplasm สอดคล้องกับรูปแบบที่เราพบเห็นอย่างต่อเนื่อง: เพย์โหลดที่ติดตั้งในระหว่างการติดตั้งซึ่งเข้าถึงเมตาเดต้าบนคลาวด์และข้อมูลลับที่ได้รับการจัดการ แทนที่จะเป็นไฟล์ในเครื่อง และจะจำกัดการทำงานให้ทำงานเฉพาะในสภาพแวดล้อมที่มีมูลค่าสูงเท่านั้น ข้อสังเกตด้านการป้องกันสองประการมีดังต่อไปนี้
- สามารถตรวจจับรูปร่างได้. hook การติดตั้ง npm/PyPI ที่มีกราฟการเรียกใช้งานไปถึง API ความลับบนคลาวด์ (AWS Secret Manager, ความลับของ gcloud, az keyvault) หรือที่อยู่ IMDS และ sink ขาออกของเครือข่าย เป็นรูปแบบที่มีสัญญาณแคบและมีความแรงสูง ซึ่งแทบจะไม่เกิดขึ้นในสคริปต์วงจรชีวิตที่ถูกต้องเลย การวิเคราะห์การไหลแบบสถิต สามารถระบุได้โดยไม่ต้องอาศัยโดเมนหรือ IP ใดๆ โดยเฉพาะ
- การทำให้สภาพแวดล้อมแข็งแกร่งขึ้นจะลดทอนประสิทธิภาพลง การบังคับใช้ IMDSv2 ด้วยขีดจำกัดจำนวนฮอปที่ 1 จะป้องกันไม่ให้เวิร์กโหลดคอนเทนเนอร์เข้าถึงเมตาเดตาของอินสแตนซ์ การกำหนดขอบเขตบทบาท IAM ให้มีสิทธิ์น้อยที่สุดจะจำกัดขอบเขตความเสียหายของข้อมูลประจำตัวที่รั่วไหล และการเรียกใช้การติดตั้งด้วย - ละเว้นสคริปต์ ในระบบ CI จะลบเวกเตอร์ install-hook ออกทั้งหมดสำหรับแพ็กเกจที่ไม่จำเป็นต้องใช้
สำหรับผู้ดูแลระบบรักษาความปลอดภัย การตรวจสอบเชิงปฏิบัติได้แก่: แจ้งเตือนการเชื่อมต่อขาออกจากคอนเทนเนอร์ build/CI ไปยัง IP สาธารณะที่ไม่ได้รับอนุญาตในระหว่าง ติดตั้ง NPMระวังการเข้าถึง IMDS ที่มาจากสคริปต์วงจรชีวิตของแพ็กเกจ และให้ถือว่า hook การติดตั้งใดๆ ที่เรียกใช้ CLI บนคลาวด์นั้นน่าสงสัย จนกว่าจะพิสูจน์ได้เป็นอย่างอื่น
มีข้อสังเกตเพิ่มเติมอีกสองประการที่เฉพาะเจาะจงกับคลัสเตอร์นี้ ประการแรก เนื่องจากการเปิดใช้งานถูกจำกัดไว้เฉพาะสภาพแวดล้อมแบบคอนเทนเนอร์ แพ็กเกจที่ดูเหมือนไม่ทำงานเมื่อตรวจสอบบนเวิร์กสเตชันอาจยังคงทำงานอยู่ในการผลิต — การตรวจสอบจำเป็นต้องจำลองเงื่อนไขชื่อโฮสต์และเส้นทางของคอนเทนเนอร์ หรืออ่านซอร์สโค้ดโดยตรง แทนที่จะอาศัยเพียงแค่ “ฉันติดตั้งแล้วและไม่มีอะไรเกิดขึ้น” ประการที่สอง การใช้บริการตรวจสอบคำขอสาธารณะเป็นตัวเก็บรวบรวมบีคอนหมายความว่าข้อมูลที่ถูกขโมยไปบางส่วนอาจสามารถกู้คืนได้สำหรับการตอบสนองต่อเหตุการณ์: องค์กรที่พบแพ็กเกจเหล่านี้ในแผนผังการพึ่งพาของตนสามารถวิเคราะห์ได้ว่าบีคอนที่ประสบความสำเร็จควรมีอะไรบ้างจากตรรกะการรวบรวมของเพย์โหลด และควรหมุนเวียนข้อมูลประจำตัวบทบาท IAM โทเค็นรีจิสทรี และความลับที่จัดการได้ซึ่งสามารถเข้าถึงได้จากสภาพแวดล้อมการสร้างหรือรันไทม์ที่ได้รับผลกระทบ การหมุนเวียนใบรับรองไม่ใช่การลบแพ็กเกจ คือวิธีการแก้ไขปัญหาที่ได้ผลหลังจากการติดตั้งเสร็จสิ้นแล้ว





