TL; DR
แพ็กเกจ npm จำนวน 20 แพ็กเกจถูกเผยแพร่ในช่วงสองวัน คือปลายเดือนกรกฎาคมและต้นเดือนสิงหาคม ปี 2026 โดยอ้างว่าเป็นไลบรารีส่วนประกอบ UI ภายในและยูทิลิตี้แบ็กเอนด์ที่ใช้ร่วมกัน แต่ไม่มีแพ็กเกจใดที่ใช้งานฟังก์ชันการทำงานตามที่โฆษณาไว้เลย แต่ละแพ็กเกจประกอบด้วยคลาสจำลอง ไฟล์ README ที่อธิบายว่าแพ็กเกจนั้นเป็นแบบภายใน และไฟล์ชื่อ... _polyfill.js.
ส่วนที่น่าสนใจคือไฟล์นั้นถูกเรียกใช้งานจากที่ใด นี่ไม่ใช่ hook สำหรับการติดตั้ง — ไฟล์ manifest ไม่ได้ระบุ preinstall, install หรือ postinstall เลย แต่บรรทัดสุดท้ายของ index.js อ่าน: try { require("./_polyfill"); } catch (_) {}โค้ดส่วนนี้จะทำงานครั้งแรกเมื่อโค้ดแอปพลิเคชันนำเข้าแพ็กเกจ ติดตั้งด้วย --ignore-scriptsที่ standard คำแนะนำสำหรับการลดความเสี่ยงในห่วงโซ่อุปทานในระหว่างการติดตั้ง ไม่ได้ป้องกันมัน.
อะไร _polyfill.js หน้าที่ของมันคือ การดึงไฟล์ปฏิบัติการเฉพาะแพลตฟอร์มจากโฮสต์ Cloudflare Workers หนึ่งในสามตัว เขียนไฟล์นั้นลงในไดเร็กทอรีชั่วคราวภายใต้ชื่อแบบสุ่ม ทำเครื่องหมายให้เป็นไฟล์ปฏิบัติการ และเรียกใช้ไฟล์นั้นโดยแยกจากกระบวนการหลัก ไฟล์ปฏิบัติการนั้นเป็นตัวโหลด: มันจะแสดงรายการผลิตภัณฑ์รักษาความปลอดภัยปลายทางตามชื่อกระบวนการ ตรวจสอบชื่อผู้ใช้ปัจจุบันกับบัญชีสภาพแวดล้อมการวิเคราะห์ที่รู้จัก แก้ไขอินเทอร์เฟซการวัดระยะทาง AMSI และ ETW ในหน่วยความจำ ติดตั้งการคงอยู่ถาวรภายใต้ชื่อของส่วนประกอบเสียงของ Windows และดึงไบนารีตัวที่สามที่มีขนาดหลายเมกะไบต์ ขั้นตอนที่สามจะมาถึงในรูปแบบเข้ารหัสและเป็น ถอดรหัสและประมวลผลในหน่วยความจำแทนที่จะเขียนลงดิสก์.
เมื่อวันที่ 1 สิงหาคม ประมาณสี่ชั่วโมงหลังจากที่ยืนยันแล้วว่าแพ็กเกจเหล่านั้นเป็นอันตรายจากการตรวจสอบด้วยตนเอง ชื่อแพ็กเกจ 19 จาก 20 ชื่อถูกลบออกจาก npm โดยผู้เผยแพร่เองภายในเวลาเพียง 25 วินาที ต่อมาในวันที่ 2 สิงหาคม หนึ่งในชื่อแพ็กเกจเหล่านั้นถูกลงทะเบียนใหม่อีกครั้งโดยบัญชีผู้ใช้ที่แตกต่างกัน แต่ใช้โค้ดเดียวกัน โครงสร้างพื้นฐานด้านการขนส่งรองรับทั้งสามขั้นตอนแล้วในขณะที่เขียนเอกสารนี้
| แบบรวดเร็ว | มีชื่อ npm 20 ชื่อ และเวอร์ชันที่เผยแพร่แล้วประมาณ 74 เวอร์ชัน |
| ธีมการตั้งชื่อ | beaver-ui-* (13) accounts-* (3) บวก afisha-storybook-default, bcore-bravo-eslint-config, arbocrate-sla-prober-arbocrate-sla-prober-core, a.poltoradnev-package-c |
| ทริกเกอร์ | การนำเข้าโมดูล (require(ไม่ใช่สคริปต์วงจรชีวิตของ npm) |
| 1 เวที | _polyfill.js — การเรียกคืนและการปล่อย |
| 2 เวที | ตัวโหลดแบบเชื่อมโยงคงที่ บรรจุในรูปแบบ UPX บน Linux การตรวจสอบความปลอดภัยของปลายทาง การแก้ไขช่องโหว่ AMSI/ETW การคงอยู่ของข้อมูล |
| 3 เวที | beacon_linux.bin / beacon_mac.bin / update_win.exeขนาด 4–13 เมกะไบต์; ส่งข้อมูลในรูปแบบเข้ารหัส และประมวลผลในหน่วยความจำ |
| แพลตฟอร์ม | ลินุกซ์ x64 และ arm64, มอสโค้ทแบบสากล, วินโดว x64 |
| สำนักพิมพ์ | สองบัญชี หนึ่งโค้ดเบส |
| สถานะ | รายชื่อ 19 จาก 20 รายชื่อยังไม่ได้รับการเผยแพร่ โดยผู้ดำเนินการ; 1 เผยแพร่ซ้ำและใช้งานได้จริง; โครงสร้างพื้นฐานการจัดส่งใช้งานได้จริง |
กายวิภาคการโจมตี
ขั้นตอนที่ 1 — บรรจุภัณฑ์
สมาชิกทุกรายจัดส่งไฟล์รูปทรงสามไฟล์แบบเดียวกัน index.js ส่งออกคลาสที่มี ในนั้น() ที่กำหนดค่าบูลีน รุ่น ()และใน กำหนดค่า() นั่นเป็นการรวมออบเจ็กต์ตัวเลือกเท่านั้น ไม่มีอะไรอื่น README.md ให้บรรทัดการติดตั้ง, a ต้องการ บรรทัดและประโยค “แพ็กเกจภายใน ดูแนวทางปฏิบัติได้ใน CONTRIBUTING.md” — การมีส่วนสนับสนุน.md ไม่ได้อยู่ในไฟล์ทาร์บอล
_polyfill.js ไฟล์มีขนาดไม่ถึง 5 KB และอ่านได้เหมือนโค้ดโครงสร้างพื้นฐานทั่วไป โดยจะเริ่มต้นด้วยการตรวจสอบสภาพแวดล้อมสามขั้นตอน:
if (process.env.DISABLE_TELEMETRY ||
process.env.ANALYTICS_OPT_OUT ||
process.env.DO_NOT_TRACK)
return; ตัวแปรเหล่านั้นคือการควบคุมความเป็นส่วนตัวแบบดั้งเดิม ในที่นี้ ตัวแปรเหล่านั้นจะควบคุมว่าไฟล์ไบนารีจะถูกดาวน์โหลดและเรียกใช้งานหรือไม่ เครื่องที่ตั้งค่าตัวแปรเหล่านั้น ห้ามติดตาม ถูกข้ามไปโดยสิ้นเชิง
ถัดมาคือตราประทับแบบรันครั้งเดียว: ไฟล์ที่ /tmp/.analytics_stateหรือ สถานะการวิเคราะห์ ภายใต้ % อุณหภูมิ% บนระบบปฏิบัติการ Windows เวลาในการแก้ไขจะถูกเปรียบเทียบกับช่วงเวลา 20,357 วินาที ภายในช่วงเวลานั้น โมดูลจะส่งคืนค่าทันที ดังนั้นการนำเข้าซ้ำๆ ในระหว่างการสร้างจะทำให้เกิดการพยายามดึงข้อมูลเพียงครั้งเดียว แทนที่จะเป็นหลายสิบครั้ง
โฮสต์ปลายทางไม่ได้ปรากฏเป็นค่าคงที่ แต่จะถูกสร้างขึ้นในระหว่างการทำงานจากส่วนประกอบย่อย:
["oob-worker.cf102-","baf.workers.d","ev"].join("") โฮสต์สามตัวถูกสร้างขึ้นด้วยวิธีนี้และสลับตำแหน่งก่อนใช้งาน ดังนั้นลำดับจึงแตกต่างกันไปในแต่ละครั้งที่เรียกใช้งาน การดึงข้อมูลเป็นการร้องขอ HTTPS GET ที่กำหนดให้กับ IPv4 ด้วย User-Agent of node-fetch/2.6 — ค่าที่เป็นไปได้ที่กระบวนการ Node จะส่งออกมา การตอบสนองที่มีขนาดต่ำกว่า 1,000 ไบต์จะถูกละทิ้งและจะลองใช้โฮสต์ถัดไป
หากทั้งสามวิธีล้มเหลว โมดูลจะเปลี่ยนไปใช้ DNS โดยจะส่งคำขอ TXT เพื่อขอข้อมูล ค. เพื่อให้ได้จำนวนชิ้นส่วน จากนั้นจึงร้องขอ 0. ตลอด น. โดยประมวลผลเป็นชุดละสิบรายการ จะนำคำตอบมาต่อกัน และถอดรหัสผลลัพธ์เป็น base64 เส้นทางนี้จะส่งไฟล์ปฏิบัติการเดียวกันผ่านระเบียน DNS TXT ซึ่งสามารถใช้งานได้ในสภาพแวดล้อมที่ HTTP ขาออกถูกกรอง แต่การแก้ไข DNS ไม่ถูกกรอง
ไบต์ที่ดึงมาจะถูกเขียนลงไป /var/tmp/.cache_<8-hex> บนระบบ Unix หรือ %TEMP%\dotnet_diag_<8-hex>.exe บน Windows — ชื่อไฟล์จะอ่านได้ว่าเป็นไฟล์วินิจฉัยของ .NET ส่วนบน Unix ไฟล์จะมีโหมดเป็น 0755 การเปิดใช้งานคือ วางไข่ สีสดสวย แยกออก: จริง, stdio: “ละเว้น”และ อ้างอิง()ดังนั้นกระบวนการลูกจึงมีอายุยืนยาวกว่ากระบวนการ Node ที่เริ่มต้นมันขึ้นมา ในระบบ Windows การเรียกใช้งานจะเพิ่ม... windowsHide: true.
รายละเอียดสองอย่างช่วยเติมเต็มภาพให้สมบูรณ์ ผู้ช่วยถูกนิยามว่าอย่างไร? const _l = (…a) => process.stderr.write(“”) ฟังก์ชันนี้จะถูกเรียกใช้ในแต่ละขั้นตอนของการดึงข้อมูล โดยจะเขียนสตริงว่างและละทิ้งอาร์กิวเมนต์ และจะทำหน้าที่แทนที่ส่วนของการบันทึกข้อมูล และทุกแพ็กเกจจะจัดส่งไฟล์ขนาด 81 KB มาด้วย lib/telemetry.js โดยในส่วนหัวของเอกสารระบุว่าเป็น “SDK สำหรับการวิเคราะห์ข้อมูล” ที่มี “การขนส่งผ่าน HTTPS พร้อมการหมุนเวียนและการลองใหม่ ณ ปลายทาง” และ “การค้นหาบริการโดยใช้ DNS สำหรับการสำรองข้อมูลเมื่อเกิดข้อผิดพลาด” แต่ในเวอร์ชันปัจจุบันยังไม่มีส่วนใดที่ต้องการใช้งานฟังก์ชันนี้
ขั้นตอนที่ 2 — รถตัก
ไฟล์ไบนารีสำหรับ Linux x64 เป็นไฟล์ ELF ที่เชื่อมโยงแบบคงที่และบีบอัดด้วย UPX 3.96 ส่วนไฟล์ไบนารีสำหรับ macOS เป็นไฟล์ไบนารีแบบสากลที่ครอบคลุมทั้ง x86_64 และ arm64 และไฟล์ไบนารีสำหรับ Windows เป็นไฟล์ปฏิบัติการคอนโซล PE32+ ที่ถูกตัดทอนแล้ว ไฟล์ทั้งสี่ถูกดึงมาตรวจสอบแบบคงที่ แต่ไม่มีไฟล์ใดถูกเรียกใช้งาน
ไฟล์นำเข้าและตารางสตริงของเวอร์ชัน Windows อธิบายพฤติกรรมของมันได้อย่างชัดเจน มันแก้ไขปัญหาได้ เป็น DebuggerPresent, ตรวจสอบว่ามีดีบักเกอร์ระยะไกลอยู่หรือไม่และ กระบวนการข้อมูลการสอบถาม Ntและอ่าน SYSTEM\CurrentControlSet\Services\Disk\Enum — เส้นทางรีจิสทรีที่มีค่าระบุตัวควบคุมดิสก์เสมือน โดยจะเรียกใช้ฟังก์ชันนี้ GetDiskFreeSpaceExW และ สถานะหน่วยความจำทั่วโลกซึ่งสอดคล้องกับการตรวจสอบว่าทรัพยากรของโฮสต์ตรงกับอินสแตนซ์การวิเคราะห์ที่มีอายุสั้นหรือไม่
ไฟล์นี้มีรายชื่อชื่อผู้ใช้: ผู้ใช้ปัจจุบัน, ผู้ดูแลระบบไอที, ฮ่อง ลี, กล่องทดสอบ, ฮาปูบส์, มิโลซ, ทิม, ผู้ดูแลระบบ, มัลแวร์, ตัวอย่าง, ไวรัส, สิ่งแวดล้อมสิ่งเหล่านี้หลายชิ้นเป็นหลักฐานที่ได้มาจากสภาพแวดล้อมการวิเคราะห์ที่ได้รับการบันทึกไว้ในที่สาธารณะ
นอกจากนี้ยังประกอบด้วยรายการผลิตภัณฑ์รักษาความปลอดภัยปลายทางและชื่อกระบวนการของผลิตภัณฑ์เหล่านั้น ซึ่งเรียงลำดับผ่านทาง CreateToolhelp32Snapshot และ กระบวนการ32แรกW/กระบวนการ32ถัดไปW:
- คราวด์สไตรค์ ฟอลคอน (
csfalconservice,CSFalconContainer) - คาร์บอนแบล็ค (
cb.exe) - กระบอกสูบ (
cylancesvc.exe) - Bitdefender (
bdagent.exe) - Kaspersky (
avp.exe,kavfs.exe) - เทรนด์ไมโครและดีพซีเคียวริตี้ (
coreServiceShell,ds_agent.exe) - ไฟร์อาย/เทรลลิกซ์ (
xagt.exe) - แทนเนียม (
taniumclient.exe) - Hitmanpro (
hmpalert.exe) - ยืดหยุ่นได้ (
elastic-agent.exe,elastic-endpoint,filebeat.exe,winlogbeat.exe) - วาซูห์และออสซีซีค (
wazuh-agent.exe,ossec-agent.exe) - Check Point
- windows Defender
มีสัญลักษณ์เพิ่มเติมอีกสองตัว: แอมซิสแกนบัฟเฟอร์ซึ่งเป็นจุดเริ่มต้นที่ Windows เปิดเผยสำหรับการสแกนเนื้อหาในหน่วยความจำ และ อีทีดับเบิ้ลยูอีเวนท์ไรท์ซึ่งเป็นฟังก์ชันที่ Event Tracing สำหรับ Windows ใช้บันทึกเหตุการณ์ ทั้งสองอย่างนี้เป็นเป้าหมายทั่วไปสำหรับการแก้ไขภายในกระบวนการ ซึ่งจะระงับข้อมูลการวัดระยะทางที่อินเทอร์เฟซเหล่านั้นจะสร้างขึ้นหากไม่มีการแก้ไขดังกล่าว
Persistence ปรากฏขึ้นสองครั้งบน Windows ไฟล์ไบนารีถูกคัดลอกไปยัง %APPDATA%\Microsoft\Windows\Themes\SystemSoundsService.exeและมีกลไกสองอย่างที่อ้างอิงถึงสิ่งนี้: ค่าภายใต้ ซอฟต์แวร์\Microsoft\Windows\CurrentVersion\เรียกใช้และงานที่กำหนดไว้ซึ่งลงทะเบียนไว้แล้ว
schtasks /Create /F /SC ONLOGON
/TN "\Microsoft\Windows\Multimedia\SystemSoundsService"
/TR "\"%s\""
/RL HIGHEST เส้นทางของงาน ชื่อของงาน และชื่อไฟล์ปฏิบัติการ ล้วนเหมือนกับส่วนประกอบเสียงของ Windows ของแท้ /RL สูงสุด ร้องขอสิทธิ์ระดับสูงสุดที่มีอยู่
การสร้างสำหรับ macOS ใช้รูปแบบเดียวกัน โดยใช้ชื่อที่เหมาะสมกับแพลตฟอร์ม: มันจะเขียนรายการคุณสมบัติไปยัง ~/Library/LaunchAgents/com.apple.windowserver.helper.plist และวางไฟล์ปฏิบัติการไว้ที่ ~/.local/share/runtime/com.apple.runtimeมันตรวจสอบ... /แอปพลิเคชัน/VMware Fusion.app และ /ไลบรารี/การสนับสนุนแอปพลิเคชัน/VMware Tools.
ความสามารถของเครือข่ายครอบคลุมการขนส่งสามรูปแบบ: WININET.dll สำหรับ HTTPS ที่มี https://%s:%d%s รูปแบบสตริง WS2_32.dll ซ็อกเก็ต และ DNSAPI.dll สีสดสวย DNSQuery_A ข้างๆ ค.%ส.%ส รูปแบบสตริง — รูปแบบคำสั่งค้นหาแบบนับส่วนย่อยเดียวกันกับที่ใช้ในขั้นตอนแรก
คำอธิบายข้างต้นคือสิ่งที่การนำเข้า สตริง และเส้นทางรีจิสทรีของไฟล์ไบนารีแสดงให้เห็นเมื่อตรวจสอบ การวิเคราะห์แบบหลายเอนจิ้นสาธารณะของตัวอย่าง Windows เดียวกันนี้เพิ่มรายละเอียดที่การอ่านตารางการนำเข้าแบบคงที่เพียงอย่างเดียวไม่สามารถสร้างได้ และได้นำมาอ้างอิงไว้ในที่นี้แทนที่จะเป็นการกล่าวซ้ำว่าเป็นข้อสังเกตโดยตรง การวิเคราะห์ดังกล่าวรายงานว่าการอ้างอิง AMSI และ ETW ไม่เพียงแต่ได้รับการแก้ไขเท่านั้น แต่ยังได้รับการแก้ไขเพิ่มเติมด้วย — แอมซิสแกนบัฟเฟอร์ in amsi.dll และ อีทีดับเบิ้ลยูอีเวนท์ไรท์ in ntdll.dll — ซึ่งจะระงับการสแกนเนื้อหาในหน่วยความจำและการติดตามเหตุการณ์สำหรับกระบวนการนั้น นอกจากนี้ยังรายงานการตรวจสอบการป้องกันการวิเคราะห์โดยอิงตามเวลาด้วย ตรวจสอบว่ามีดีบักเกอร์ระยะไกลอยู่หรือไม่และระบุ รับบริบทเธรด เรียกใช้เป็นการตรวจสอบจุดหยุดฮาร์ดแวร์โดยการอ่านรีจิสเตอร์ดีบัก นอกจากนี้ยังรายงานมิวเท็กซ์แบบอินสแตนซ์เดียวด้วย Global\{7A3B9E1F-C2D4-4F8A-B5E6-D7A1F0C3E2B9}และชื่อ บริการเสียงระบบ โดยกำหนดค่าเป็น Run-key ค่า mutex นั้นไม่ได้อยู่ในสตริงที่กู้คืนได้ที่นี่ — ตัวกรองการดึงข้อมูลที่ใช้ไม่รวมโทเค็นเลขฐานสิบหกตัวพิมพ์ใหญ่ที่มีวงเล็บปีกกา — และค่าดังกล่าวถูกบันทึกไว้ในตารางตัวบ่งชี้โดยอาศัยการวิเคราะห์สาธารณะนั้นมากกว่าการสังเกตโดยตรง
3 เวที
ตัวโหลดอ้างอิงถึงชุดเส้นทางเพิ่มเติมบนโฮสต์เดียวกัน ซึ่งทั้งหมดสามารถเข้าถึงได้ในระหว่างการวิเคราะห์: บีคอน_ลินุกซ์.บิน ขนาดไฟล์ 5.3 เมกะไบต์ บีคอน_แมค.บิน ขนาดไฟล์ 13.3 เมกะไบต์ update_win.exe ขนาดไฟล์ 10.3 เมกะไบต์ และ อาร์ม.บิน ไฟล์เหล่านี้มีขนาด 4.3 MB ไม่สามารถเรียกค้นได้ และไม่ทราบพฤติกรรมของไฟล์เหล่านั้น
สำหรับเส้นทางของ Windows การวิเคราะห์สาธารณะของตัวโหลดอธิบายวิธีการจัดการขั้นตอนที่สามดังนี้: มันถูกดึงมาผ่าน WinINet มาถึงในรูปแบบเข้ารหัส และถูกถอดรหัสในหน่วยความจำและดำเนินการแบบสะท้อนกลับ — หน่วยความจำถูกจัดสรร แก้ไขการนำเข้า ประมวลผลการย้ายตำแหน่ง และส่งการควบคุมไปยังเธรดใหม่ผ่านทาง สร้างเธรดด้วยเหตุนี้ ขั้นตอนที่สามจึงไม่ถูกเขียนลงในระบบไฟล์ ดังนั้นการตรวจจับโดยใช้ไฟล์และการตรวจสอบทางนิติวิทยาศาสตร์ของดิสก์หลังเกิดเหตุจึงไม่สามารถกู้คืนข้อมูลใดๆ จากขั้นตอนนี้ได้ นอกจากนี้ยังหมายความว่าการดึงไบต์จากโฮสต์ผู้ส่งข้อมูลจะให้ผลลัพธ์เป็นข้อความที่เข้ารหัส ไม่ใช่ไฟล์ปฏิบัติการที่สามารถวิเคราะห์ได้
ปฏิบัติการ
เวลาทั้งหมดเป็นเวลา UTC และมาจากข้อมูลเมตาของรีจิสทรี npm ซึ่งบันทึกการสร้างและการยกเลิกการเผยแพร่แพ็กเกจโดยอิสระจากผู้สังเกตการณ์ใดๆ
| เมื่อ | อะไร |
|---|---|
| 2026-07-31 09:25:05 → 09:29:56 | มีการสร้างชื่อสิบชื่อ โดยแต่ละชื่อเริ่มต้นด้วยเวอร์ชัน 0.0.1โดยห่างกันประมาณสิบสามวินาที |
| 2026-08-01 09:38 → 11:29 | ชื่อที่มีอยู่เดิมจะไต่ระดับขึ้นไปเรื่อยๆ ผ่านหมายเลขเวอร์ชันที่สูงเกินจริง 6.1.9 ตลอด 6.1.12, 9.9.9 ตลอด 9.9.12, 8.9.3 ตลอด 8.9.6, 5.4.6 ตลอด 5.4.9. |
| 2026-08-01 13:04:14 → 13:04:18 | อีกเก้าอย่าง beaver-ui-* ชื่อเหล่านี้ถูกสร้างขึ้นในเวลาเพียงสี่วินาที และเผยแพร่โดยตรงในเวอร์ชัน 12.x โดยไม่มีประวัติมาก่อน |
| 2026-08-01 ~13:00–14:30 | เวอร์ชันที่ถูกจัดว่าเป็นเวอร์ชันที่เป็นอันตรายจากการตรวจสอบด้วยตนเอง |
| 2026-08-01 17:39:49 → 17:40:14 | รายชื่อ 19 จาก 20 รายชื่อที่ไม่ได้รับการเผยแพร่ในเวลา 25 วินาที ถูกเผยแพร่ตามลำดับ โดยแต่ละรายชื่อห่างกันประมาณ 1.2 วินาที |
| 2026-08-02 18:58:41 | a.poltoradnev-package-c สร้างขึ้นใหม่อีกครั้งภายใต้บัญชีผู้ดูแลระบบเวอร์ชันอื่น 0.0.2. |
| 2026-08-02 19:20:28 | เวอร์ชั่น 33.9.5 ตีพิมพ์ในชื่อเดียวกัน |
| 2026-08-02 20:14 | โฮสต์ส่งมอบทั้งสามตัวให้บริการในขั้นตอนที่สองและสาม; การสำรองข้อมูล DNS ตอบกลับด้วยจำนวนชิ้นส่วน (chunk counts) |
มีสองประเด็นในนี้ที่ควรค่าแก่การพิจารณาเป็นพิเศษ
การระเบิดเวลา 13:04 ทำให้มีแพ็กเกจ 9 รายการถูกบันทึกในระบบภายในเวลา 4 วินาที โดยแต่ละรายการมีเวอร์ชันเดียวอยู่ในช่วง 12 และไม่มี 0.0.1 ด้านล่างนั้น หมายเลขเวอร์ชันในระดับนี้ บนชื่อที่เพิ่งออกมาเมื่อวันก่อน ไม่ได้บ่งบอกถึงประวัติการวางจำหน่ายแต่อย่างใด
ลำดับขั้นตอนการยกเลิกการเผยแพร่ก็เป็นไปอย่างเป็นกลไกเช่นกัน: ชื่อ 19 ชื่อ ระยะเวลา 25 วินาที เว้นระยะห่างอย่างสม่ำเสมอ npm จะบันทึกสิ่งเหล่านี้เป็นเหตุการณ์การยกเลิกการเผยแพร่ตามปกติ แทนที่จะเป็นตัวยึดตำแหน่งที่การลบที่เริ่มต้นโดยรีจิสทรีทิ้งไว้ ซึ่งจะทำให้การดำเนินการนั้นตกอยู่กับบัญชีผู้เผยแพร่ แทนที่จะเป็นรีจิสทรี
ตัวชี้วัดของการประนีประนอม
โฮสต์และเส้นทางต่างๆ ถูกปิดใช้งานแล้ว ห้ามทำการค้นหาหรือดึงข้อมูลเหล่านั้นจากระบบใช้งานจริง
| ประเภท | ความคุ้มค่า |
|---|---|
| ผู้ให้บริการจัดส่ง | oob-worker[.]cf99-9b3[.]workers[.]dev |
| ผู้ให้บริการจัดส่ง | oob-worker[.]cf102-baf[.]workers[.]dev |
| ผู้ให้บริการจัดส่ง | oob-worker[.]cf103-070[.]workers[.]dev |
| การขนส่ง DNS | tin[.]dl[.]well1[.]site (ลินุกซ์ x64) tina[.] (arm64) ldr[.] (MacOS) win[.] (Windows) — จำนวนชิ้นส่วนที่นับได้ c.<domain>ข้อมูลที่ <n>.<domain> |
| เส้นทางระยะที่ 2 | /pkg/package, /pkg/package-arm64, /pkg/loader_mac, /pkg/package.exe |
| เส้นทางระยะที่ 3 | /pkg/beacon_linux.bin, /pkg/beacon_mac.bin, /pkg/update_win.exe, /pkg/arm.bin |
| เส้นทางดรอป (ยูนิก) | /var/tmp/.cache_<8-hex> |
| เส้นทางการวาง (Windows) | %TEMP%\dotnet_diag_<8-hex>.exe |
| ความคงทน (Windows) | %APPDATA%\Microsoft\Windows\Themes\SystemSoundsService.exe; งาน \Microsoft\Windows\Multimedia\SystemSoundsServiceค่าคีย์การทำงาน SOFTWARE\Microsoft\Windows\CurrentVersion\Run\SystemSoundsService |
| มิวเท็กซ์ (Windows) | Global\{7A3B9E1F-C2D4-4F8A-B5E6-D7A1F0C3E2B9} |
| ความคงทน (macOS) | ~/Library/LaunchAgents/com.apple.windowserver.helper.plistไบนารีที่ ~/.local/share/runtime/com.apple.runtime |
| แสตมป์รันครั้งเดียว | /tmp/.analytics_state, %TEMP%\analytics_state (หน้าต่าง 20,357 วินาที) |
| ขอลายเซ็น | HTTPS GET, IPv4-pinned, User-Agent: node-fetch/2.6 |
| ไฟล์ขั้นตอนที่ 1 | _polyfill.js, SHA-256 392dc9ec85042ce1796bfa9b8c7bf6e05c7710579aab8b7b1eb73788683883af |
| ไฟล์ที่ไม่มีการอ้างอิง | lib/telemetry.js, SHA-256 2266c9b8e199daebe31a9afcb61d9b0d76706b63c92312fc8223d22de42e63c7 |
| ขั้นตอนที่ 2 (Linux x64) | SHA-256 7e486657f30594afda379b97030252a09a19fe8055e25c9e371544f59bd8e9e3 |
| ขั้นตอนที่ 2 (Linux arm64) | SHA-256 aafc37589c0d21fb729761a1579ca3b278b95bce152aacfa29243ffd27f5eeb7 |
| ขั้นตอนที่ 2 (macOS) | SHA-256 c214746c74cae8ece8bdaf69aa05da4db6ce013f9e77452d1eed1a002fd9ba00 |
| ขั้นตอนที่ 2 (Windows) | SHA-256 d632c2c0c7801c3da57cf849fe4b4ca8351d9a7fe73c31050bf5dbcc96a16791 |
ชื่อแพ็คเกจ
การระบุสาเหตุและพฤติกรรมที่สังเกตได้
มีบัญชี npm สองบัญชีที่เกี่ยวข้อง โดยชื่อที่ยังไม่ได้เผยแพร่ทั้งสิบเก้าชื่อนั้น ถูกเผยแพร่โดยบัญชีหนึ่งบัญชี a.poltoradnev-package-c แอปพลิเคชันนี้ได้รับการจดทะเบียนใหม่เมื่อวันที่ 2 สิงหาคม โดยใช้ชื่อบัญชีและโดเมนอีเมลที่แตกต่างกัน โค้ดมีที่มาเดียวกันทั้งสองการจดทะเบียน และการจดทะเบียนครั้งที่สองใช้โฮสต์การส่งมอบเดียวกัน โดเมนสำรอง DNS เดียวกัน โครงสร้าง drop-path เดียวกัน และตราประทับ run-once เดียวกัน
เอกสารที่ตีพิมพ์ซ้ำทั้งสองฉบับยังแสดงให้เห็นถึงวิธีการประกอบอีกด้วย เวอร์ชันต่างๆ 0.0.2 และ 33.9.5 มีไบต์เหมือนกันทุกประการ ยกเว้นสตริงเวอร์ชันใน package.jsonและ index.js จัดส่งเป็น 0.0.2 ประกาศ const VERSION = “33.9.5”วัตถุโบราณทั้งสองชิ้นถูกตัดมาจากต้นไม้ต้นเดียวกันและติดหมายเลขภายหลัง ไม่มี 0.0.2 ประวัติการพัฒนาของ 0.0.2 อนุญาตให้เป็นตัวแทน
การกำหนดหมายเลขเวอร์ชันในชุดทั้งหมดเป็นไปตามตรรกะเดียวกัน ชื่อแพ็กเกจในแคมเปญนี้อ่านได้เหมือนกับสิ่งที่จะมีอยู่ภายในองค์กรมากกว่าที่จะอยู่ในรีจิสทรีสาธารณะ เช่น ชุดส่วนประกอบ UI, การกำหนดค่า ESLint, ตัวตรวจสอบ SLA, แพ็กเกจที่ตั้งชื่อตามบุคคล เมื่อบิลด์แก้ไขการพึ่งพาโดยใช้ชื่อและตรวจสอบรีจิสทรีสาธารณะควบคู่ไปกับรีจิสทรีส่วนตัว หมายเลขเวอร์ชันที่สูงกว่าจะเป็นเวอร์ชันที่ชนะ ชื่อที่สร้างขึ้นที่ 0.0.1 ในวันจันทร์และดำเนินการ 12.9.6 วันอังคารนี้ถือเป็นวันที่เหมาะสมสำหรับการเปรียบเทียบดังกล่าว
การเผยแพร่ทั้งสองครั้งมีความแตกต่างกันในลักษณะที่บ่งบอกถึงการทำซ้ำ โดยรหัสที่ออกมาก่อนหน้านี้ได้ตั้งชื่อไฟล์ข้อมูลหลักไว้แล้ว setup.js และระบุโฮสต์การจัดส่งห้ารายการ โดยไฟล์ปัจจุบันมีชื่อว่า _polyfill.js และแสดงรายการสามรายการ เวอร์ชันก่อนหน้านี้จะลบไฟล์ที่ถูกทิ้งหลังจากเริ่มกระบวนการได้ห้าวินาที ทำให้กระบวนการยังคงทำงานจาก inode ที่ถูกลบไปแล้ว เวอร์ชันปัจจุบันไม่ทำเช่นนั้น (ไม่ได้อ้างอิง) lib/telemetry.js ยังคงอยู่ในไฟล์บีบอัด (tarball) ทั้งสองแบบ ยังคงจัดส่งอยู่ แต่ไม่ได้เชื่อมต่อผ่านสายแล้ว
มีข้อสังเกตหนึ่งเกี่ยวกับสวิตช์ปิดเครื่องที่ควรกล่าวถึงก่อนcisเพราะมันขัดแย้งกับการตีความทั่วไป ปิดใช้งานระบบส่งข้อมูลทางไกล, ANALYTICS_OPT_OUTและ ห้ามติดตาม สิ่งเหล่านี้ได้รับการยกย่อง และจะถูกตรวจสอบก่อนที่จะดำเนินการใดๆ ต่อไป นักวิจัยที่ตั้งค่าสภาพแวดล้อมการวิเคราะห์ใดๆ ก็ตาม จะสังเกตเห็นแพ็กเกจที่ไม่ได้ทำอะไรเลย
ผลกระทบและสิ่งที่กองหลังสามารถทำได้
ผลกระทบในทางปฏิบัติของกลไกการกระตุ้นเวลานำเข้านั้นมีขอบเขตจำกัดและควรค่าแก่การกล่าวถึงแยกต่างหาก npm install –ignore-scripts การป้องกันไม่ให้สคริปต์วงจรชีวิตทำงานนั้นเป็นคำแนะนำที่ดี แต่ในกรณีนี้มันไม่มีผลอะไร เพราะโค้ดนี้ไม่ได้ใช้สคริปต์วงจรชีวิต โค้ดส่วนนี้จะทำงานเมื่อโค้ดแอปพลิเคชัน การทดสอบ การรวมไฟล์ หรือตัวตรวจสอบไวยากรณ์นำเข้าโมดูลเป็นครั้งแรก บนระบบ CI ที่ติดตั้งแล้วทำการสร้างทันที การทำงานทั้งสองส่วนจะห่างกันเพียงไม่กี่วินาที
สำหรับการล่าหาช่องโหว่ สัญญาณที่คงทนถาวรนั้นเป็นโครงสร้างมากกว่าลักษณะที่แท้จริง โฮสต์ ชื่อไฟล์ และเส้นทางการวางไฟล์จะเปลี่ยนแปลงไป รูปทรงเหล่านี้จึงเปลี่ยนแปลงได้ยากกว่า:
- จุดเริ่มต้นของโมดูลซึ่งข้อความสุดท้ายคือ try { require(“./x”); } catch (_) {} เกี่ยวกับไฟล์ที่ไม่ใช่ส่วนหนึ่งของ API ที่ส่งออก แพ็กเกจที่มี polyfill ของแท้จะนำเข้า polyfill นั้นที่ส่วนบนสุดของไฟล์และใช้ผลลัพธ์จาก polyfill นั้น การละเลยข้อผิดพลาดทุกอย่างจากการนำเข้าที่ส่วนท้ายของไฟล์ไม่ใช่การจัดการข้อผิดพลาด
- สตริงโฮสต์ที่ประกอบโดย .เข้าร่วม("") จากชุดชิ้นส่วนต่างๆ โค้ดที่ถูกต้องตามหลักไวยากรณ์ไม่มีเหตุผลที่จะต้องแบ่งชื่อโฮสต์ออกเป็นหลายส่วนในอาร์เรย์
- แพ็กเกจที่มีการประกาศการพึ่งพาว่างเปล่า แต่กลับเข้าถึงแพ็กเกจนั้น ที่ https, DNSและ กระบวนการของเด็ก ในขั้นตอนการนำเข้า การดึงข้อมูลและการดำเนินการในแพ็กเกจที่โฆษณาส่วนประกอบ UI คือข้อค้นพบทั้งหมด
- หมายเลขเวอร์ชันไม่สอดคล้องกับอายุของแพ็กเกจ ชื่อที่เพิ่งปรากฏครั้งแรกเมื่อไม่กี่วันก่อนในเวอร์ชันหลักที่มีหมายเลขสองหลัก โดยไม่มีการออกเวอร์ชันใหม่ระหว่างนั้น กำลังอธิบายถึงสิ่งอื่นที่ไม่ใช่การพัฒนาของมันเอง
- เขียนถึง / var / tmp or % อุณหภูมิ% ตามด้วย chmod ถึงเวลา 07:55 และการเกิดใหม่แบบแยกส่วน ลำดับเหตุการณ์นั้นสั้น เป็นระเบียบ และมักไม่ก่อให้เกิดอันตรายใดๆ ร่วมกัน
บนระบบ Windows มีการตรวจสอบสองวิธีที่ราคาไม่แพงและมีความน่าเชื่อถือสูง สิ่งตกค้างคือสตริงคงที่ และไม่มีสิ่งใดควรอยู่ในระบบที่สะอาด: งานที่กำหนดเวลาไว้ที่ \Microsoft\Windows\Multimedia\SystemSoundsServiceค่าคีย์ Run ที่ชื่อว่า บริการเสียงระบบและไฟล์ปฏิบัติการที่มีชื่อนั้นภายใต้ %APPDATA%\Microsoft\Windows\Themes\บริการเสียงของ Windows ของแท้ไม่ได้อยู่ที่ใดที่หนึ่งเหล่านั้น ประการที่สอง ตัวโหลดใช้มิวเท็กซ์แบบอินสแตนซ์เดียวที่กำหนดไว้ตายตัว Global\{7A3B9E1F-C2D4-4F8A-B5E6-D7A1F0C3E2B9}การมีอยู่ของมิวเท็กซ์บนโฮสต์เป็นตัวบ่งชี้ และเนื่องจากตัวโหลดถือว่ามิวเท็กซ์ที่มีอยู่แล้วนั้น "ทำงานอยู่แล้ว" การสร้างมิวเท็กซ์ล่วงหน้าจึงเป็นการป้องกันในระยะสั้นที่ได้ผลในขณะที่กำลังวางแผนแก้ไขปัญหา
การตรวจจับในขั้นตอนที่สามเป็นปัญหาที่ยากกว่าและควรทำความเข้าใจให้ชัดเจน จากการวิเคราะห์ของสาธารณะพบว่า ข้อมูลจะถูกถอดรหัสและจัดเก็บไว้ในหน่วยความจำแทนที่จะเขียนลงดิสก์ ดังนั้นการสแกนไฟล์และการตรวจสอบทางนิติวิทยาศาสตร์ของดิสก์จึงไม่สามารถตรวจพบได้ สิ่งที่ยังคงสังเกตได้คือร่องรอยของตัวโหลดเอง ได้แก่ รายการคงอยู่ของข้อมูล มิวเท็กซ์ และคำขอขาออกไปยังโฮสต์การส่งมอบหรือโดเมน DNS-TXT
สำหรับสภาพแวดล้อมที่แก้ไขการพึ่งพาจากทั้งรีจิสทรีส่วนตัวและรีจิสทรีสาธารณะ การแก้ไขปัญหาจะไม่เปลี่ยนแปลงไปจากที่กล่าวมาทั้งหมด: กำหนดขอบเขตชื่อภายในเพื่อให้ชื่อสาธารณะไม่สามารถตอบสนองความต้องการได้ และตรึงการแก้ไขไว้ที่รีจิสทรีภายในสำหรับขอบเขตเหล่านั้น พฤติกรรมการเพิ่มเวอร์ชันที่อธิบายไว้ข้างต้นจะใช้ได้เฉพาะในกรณีที่เวอร์ชันสาธารณะที่สูงกว่าสามารถชนะชื่อได้เท่านั้น
สุดท้ายนี้ การยกเลิกการเผยแพร่ควรค่าแก่การอ่านอย่างละเอียดถี่ถ้วนมากกว่าที่จะมองว่าเป็นจุดจบ ชื่อ 19 ชื่อหายไปจากทะเบียนภายใน 25 วินาที และหนึ่งชื่อกลับมาในวันถัดไปภายใต้บัญชีใหม่ โดยที่โครงสร้างพื้นฐานการส่งมอบยังคงไม่เปลี่ยนแปลงตลอดมา การลบแพ็กเกจไม่ได้หมายถึงการลบการดำเนินการ โฮสต์ยังคงให้บริการในทุกขั้นตอนขณะที่เขียนข้อความนี้ ต้นไม้การพึ่งพาใดๆ ที่แก้ไขชื่อเหล่านี้ระหว่างวันที่ 31 กรกฎาคมถึง 1 สิงหาคม ควรได้รับการพิจารณาว่ามีโอกาสได้ดำเนินการในขั้นตอนที่หนึ่ง ไม่ว่าชื่อนั้นจะยังคงอยู่หรือไม่ก็ตาม
อ้างอิง
- การวิเคราะห์ตัวโหลด Windows ด้วยหลายเอนจิ้น — แหล่งที่มาของรายละเอียดเกี่ยวกับการแก้ไข AMSI/ETW การประมวลผลแบบสะท้อนกลับในหน่วยความจำ และมิวเท็กซ์ที่กล่าวถึงข้างต้น
- เอกสารประกอบการใช้งานสคริปต์ npm — เหตุการณ์วงจรชีวิตที่แคมเปญนี้ไม่ได้ใช้
- เอกสารการติดตั้ง npm — ปก - ละเว้นสคริปต์ และขอบเขตของมัน




