สรุปสั้น
ผู้โจมตีที่มีความเชื่อมโยงกับเกาหลีเหนือถูกเชื่อมโยงกับชุดแพ็กเกจ npm อันตรายชุดใหม่ที่ปลอมตัวเป็นเครื่องมือ Rollup polyfill เพื่อเปิดทางให้เข้าถึงเครื่องเหยื่อจากระยะไกลและขโมยข้อมูล บริษัท JFrog ระบุว่าแพ็กเกจ “rollup-packages-polyfill-core” และ “rollup-runtime-polyfill-core” เลียนแบบโปรเจกต์ที่ถูกต้องชื่อ “rollup-plugin-polyfill-node” อย่างละเอียด ตั้งแต่คำอธิบาย เมทาดาทาของคลังโค้ด ไปจนถึงรูปทรงของแพ็กเกจ ทำให้ดูน่าเชื่อถือเมื่อมีการตรวจสอบ dependency อย่างรวดเร็ว แคมเปญนี้ยังเกี่ยวข้องกับแพ็กเกจอีกสี่ตัวที่ถูกลบออกจาก npm registry ไปแล้ว
จุดที่น่าสนใจคือแพ็กเกจตัวแรกจะติดตั้งและโหลดแพ็กเกจขั้นที่สองที่ปลอมตัวเป็นยูทิลิตี SVG ซึ่งจะดึงออบเจ็กต์ JSON จากบริการ JSONKeeper แล้ว eval ฟิลด์ที่ชื่อ model เพื่อรันมัลแวร์ JavaScript โครงสร้างแบบหลายชั้น ชื่อที่เลียนแบบ เมทาดาทาที่ดูถูกต้อง การรันซ่อนตอนติดตั้ง การตรวจสอบสภาพแวดล้อม และเพย์โหลดขโมยข้อมูลรับรองกับเปิดทางเข้าถึงระยะไกล ล้วนคล้ายกับแคมเปญ npm ที่เชื่อมโยงกับกลุ่ม Lazarus ของเกาหลีเหนือก่อนหน้านี้ มัลแวร์พุ่งเป้าไปที่ข้อมูลรับรอง คีย์คลาวด์ คีย์ SSH ข้อมูลเบราว์เซอร์ และกระเป๋าเงินคริปโตที่มักอยู่บนเครื่องของนักพัฒนาและเครื่อง build
รายละเอียดข่าว
เว็บไซต์ The Hacker News รายงานเมื่อวันที่ 3 กรกฎาคม พ.ศ. 2569 ว่า บริษัท JFrog เปิดเผยรายงานเชิงเทคนิคเกี่ยวกับชุดแพ็กเกจ npm อันตรายที่มีความเชื่อมโยงกับผู้โจมตีสัญชาติเกาหลีเหนือ ซึ่งปลอมตัวเป็นเครื่องมือ Rollup polyfill โดย JFrog ระบุว่า “แพ็กเกจเลียนแบบวางตัวเองอยู่ในเนมสเปซของชื่อ rollup, polyfill, core และ node เดียวกัน ซึ่งอาจดูสมเหตุสมผลระหว่างการตรวจสอบ dependency อย่างรวดเร็ว”
นอกจากสองแพ็กเกจหลักแล้ว แคมเปญยังเกี่ยวข้องกับแพ็กเกจอีกสี่ตัวที่ถูกลบออกไปแล้ว ได้แก่ quirky-token, react-icon-svgs, rollup-plugin-polyfill-connect และ swift-parse-stream โดย “rollup-packages-polyfill-core” จะติดตั้งและโหลด “swift-parse-stream” ส่วน “rollup-runtime-polyfill-core” จะติดตั้ง “quirky-token” ในทำนองเดียวกัน “react-icon-svgs” ถูกพบว่าติดตั้ง “rollup-plugin-polyfill-connect” เป็นขั้นที่สอง JFrog อธิบายว่า “แพ็กเกจขั้นที่สองเป็นยูทิลิตี SVG ที่แทบจะเหมือนกัน ซึ่งดึงออบเจ็กต์ JSON จาก JSONKeeper แล้ว eval ฟิลด์ model”
นี่ไม่ใช่ครั้งแรกที่ผู้โจมตีเกาหลีเหนืออัปโหลดแพ็กเกจ npm ปลอมเป็นเครื่องมือ Rollup polyfill เมื่อเดือนเมษายน พ.ศ. 2569 บริษัท Panther เคยเปิดเผยแคมเปญ npm ที่ต่อเนื่องซึ่งเผยแพร่แพ็กเกจอันตราย 108 ตัว ครอบคลุม 261 เวอร์ชัน เพื่อส่งมัลแวร์ BeaverTail และ OtterCookie ที่เชื่อมโยงกับปฏิบัติการ Contagious Interview จุดเริ่มต้นของการโจมตีคือคำสั่งติดตั้ง npm ที่เข้ารหัสแบบ Base64 สำหรับ “swift-parse-stream” (หรือ “quirky-token”) ที่ซ่อนอยู่ในแพ็กเกจขั้นแรก
วิธีการโจมตี
โค้ด JavaScript จะทำการตรวจสอบเพื่อหลีกเลี่ยงการทำงานภายในสภาพแวดล้อมการพัฒนาบนคลาวด์ แซนด์บ็อกซ์ serverless runtime และโครงสร้างพื้นฐานสำหรับการวิเคราะห์ เมื่อผ่านด่านนี้ไปได้ มัลแวร์จะติดตั้ง dependency ที่จำเป็นและติดต่อไปยังเซิร์ฟเวอร์ภายนอก (216.126.236[.]244) เพื่อดึงเพย์โหลด JavaScript ที่เข้ารหัสไว้ เพย์โหลดที่ถอดรหัสแล้วจะทำหน้าที่เป็นโหลดเดอร์สำหรับสคริปต์เพิ่มเติมที่เปิดทางให้เข้าถึงเครื่องที่ถูกยึดครองจากระยะไกล รองรับเซสชันเทอร์มินัลแบบโต้ตอบ การรันคำสั่ง การจับภาพหน้าจอ การหยุดโปรเซส รวมถึงการควบคุมเมาส์และแป้นพิมพ์บน Windows ผ่านแพ็กเกจ “@nut-tree-fork/nut-js” ตลอดจนขโมยข้อมูลจากเบราว์เซอร์และกระเป๋าเงินคริปโต เก็บไฟล์ที่ตรงกับนามสกุลที่กำหนด และจับเนื้อหาคลิปบอร์ดเป็นระยะ
ความสามารถเหล่านี้ทับซ้อนกับมัลแวร์ OtterCookie โดยเฉพาะการใช้ “@nut-tree-fork/nut-js” ควบคุมเมาส์และแป้นพิมพ์ระยะไกล ส่วนคอมโพเนนต์เก็บไฟล์ยังเจาะจงมองหาประวัติการใช้งานของโปรแกรมแก้ไขโค้ดอย่าง Microsoft Visual Studio Code, Windsurf และ Cursor พร้อมกับไฟล์ตั้งค่าเครื่องมือของนักพัฒนาและเครื่องมือ AI เช่น AWS, Microsoft Azure, Google Gemini, Anthropic Claude, Foundry, SSH และ Z shell (Zsh) JFrog เตือนว่าปลั๊กอิน Rollup มักถูกโหลดจากไฟล์ตั้งค่าในเครื่อง เครื่องเวิร์กสเตชันของนักพัฒนา และงาน CI ซึ่งสภาพแวดล้อมเหล่านี้มักเข้าถึงทรัพย์สินอ่อนไหว เช่น ซอร์สโค้ด npm token ข้อมูลรับรอง Git คีย์คลาวด์ คีย์ SSH ข้อมูลเบราว์เซอร์ และความลับของโปรเจกต์
การเปิดเผยครั้งนี้เกิดขึ้นพร้อมกับการค้นพบการโจมตี supply chain ซอฟต์แวร์อีกหลายกรณีโดยบริษัท Checkmarx, SafeDep และนักวิจัยของ AWS ที่มุ่งวางยาคลังแพ็กเกจโอเพนซอร์ส เช่น คลัสเตอร์ที่มีการ trojan แพ็กเกจ “pyrogram” อย่างน้อยแปดตัว (ปฏิบัติการ Navy Ghost), คลัสเตอร์ 30 แพ็กเกจ npm ปลอมเป็นเครื่องมือ Polymarket, คลัสเตอร์ 25 แพ็กเกจภายใต้ scope @marketfront ที่มี postinstall ขโมยข้อมูลรับรอง, แพ็กเกจ Python “security-alerts-sdk” ที่ฝังแบ็กดอร์ และแพ็กเกจ npm “events-runtime” ที่ typosquat แพ็กเกจ “events” เพื่อปล่อยตัวขโมยกระเป๋าเงินคริปโต
เมื่อเจาะลึกกลไกทางเทคนิค JFrog อธิบายว่าโค้ดอันตรายถูกต่อท้ายโค้ดปลั๊กอิน Rollup ที่ดูปกติ โดยเฉพาะไฟล์ CommonJS dist/index.js ที่ถูกฝังแบ็กดอร์ ขณะที่ไฟล์ ESM dist/es/index.js ไม่ถูกแตะ เมื่อแพ็กเกจถูก import ระหว่างขั้นตอน build หรือโหลด config ฟังก์ชันที่ตั้งชื่อพรางว่า ValidateSvgModule จะรันคำสั่งที่เข้ารหัส Base64 ซึ่งถอดออกมาเป็น npm install swift-parse-stream --no-save --silent --no-audit --no-fund เพื่อดึงแพ็กเกจขั้นที่สองมาแบบเงียบ ๆ จากนั้นเรียก require() แพ็กเกจนั้นแล้วเรียกฟังก์ชัน getPlugin() ที่คืนมา แพ็กเกจขั้นที่สอง (swift-parse-stream / quirky-token) วางตัวเป็นยูทิลิตีทำความสะอาด SVG แต่โค้ดจริงอยู่ท้ายไฟล์ ซึ่งจะยิง request ไปยัง www[.]jsonkeeper[.]com/b/3P9BF พร้อม header bearrtoken: logo แล้วนำฟิลด์ model ในออบเจ็กต์ JSON ที่ได้มา eval โดยตรง — ฟิลด์นี้บรรจุเพย์โหลด JavaScript ที่ obfuscate ไว้
เพย์โหลดจาก JSONKeeper เริ่มด้วยการตรวจ environment variable กว่าสิบตัว (เช่น CODESPACE_NAME, VERCEL, AWS_LAMBDA_FUNCTION_NAME, AWS_ACCESS_KEY_ID, GOOGLE_CLOUD_PROJECT, AZURE_FUNCTIONS_ENVIRONMENT, DOCKER, SOCKET_DEV) และเช็กว่าสตริง OS release มีคำว่า aws หรือไม่ เพื่อหลบ sandbox, cloud IDE, serverless runtime และโครงสร้างพื้นฐานสำหรับวิเคราะห์ เมื่อผ่านด่านนี้จะติดตั้ง axios และ socket.io-client แล้วดึงเพย์โหลดขั้นต่อไปจาก 216.126.236[.]244/api/service/98cb54c0b4ac259d30c9c1ca1ae87c68 โดย response อยู่ในรูป <base64 IV>:<base64 ciphertext> ซึ่งถอดรหัสด้วย AES-256-CBC โดยได้คีย์จาก crypto.scryptSync("98cb54c0b4ac259d30c9c1ca1ae87c68", "salt", 32) แล้วเขียนผลลัพธ์ (ประมาณ 114 KB) ลงไฟล์ <tmp>/pack ก่อนรันด้วย node pack
ตัว pack ทำหน้าที่เป็นโหลดเดอร์ปล่อยเพย์โหลดสี่ส่วนหลัก ได้แก่ scdata.js (คอมโพเนนต์ remote access และควบคุมเครื่อง), ldata.js (เก็บข้อมูลเบราว์เซอร์และกระเป๋าเงินคริปโต), ตัวเก็บไฟล์ทั่วระบบ และตัวเฝ้าดูคลิปบอร์ด คอมโพเนนต์ remote access ติดตั้ง ssh2, node-pty, sharp, screenshot-desktop, clipboardy และ @nut-tree-fork/nut-js แล้วเชื่อมต่อ Socket.IO ไปยัง 216.126.236[.]244:4801 เพื่อเปิด interactive terminal (powershell.exe บน Windows, zsh บนระบบอื่น), รันคำสั่ง, เปิด SSH session, จับภาพหน้าจอ และควบคุมเมาส์/แป้นพิมพ์บน Windows ส่วน ldata อัปโหลดข้อมูลไปยังพอร์ต 4809 โดยเจาะจงโปรไฟล์เบราว์เซอร์ (Chrome, Edge, Brave, Opera, LT Browser), ไฟล์ Login Data/Web Data, storage ของ extension กระเป๋าเงิน เช่น MetaMask (nkbihfbeogaeaoehlefnkodbefgpgknn) และบน macOS ยังพยายามดึง login.keychain-db ตัวเก็บไฟล์อัปโหลดไปพอร์ต 4806 โดยไล่สแกนหานามสกุลและคีย์เวิร์ดอ่อนไหว (*.env*, *.pem, *.key, *secret phrase*, *metamask*) รวมถึงไดเรกทอรี config ของเครื่องมือนักพัฒนาและ AI (.aws, .ssh, .gnupg, .cursor, .windsurf, .gemini, .claude) ขณะที่ตัวเฝ้าคลิปบอร์ดใช้ pbpaste และ Get-Clipboard ส่งค่าที่เปลี่ยนไปยัง 216.126.236[.]244/api/service/makelog
ผลกระทบต่อไทย
นักพัฒนาซอฟต์แวร์ไทยที่ใช้ npm และเครื่องมือ build สมัยใหม่ตกอยู่ในความเสี่ยงโดยตรง เนื่องจากการโจมตีนี้พุ่งเป้าไปที่เครื่องเวิร์กสเตชันของนักพัฒนาและเครื่อง build ที่มักเก็บ API key คีย์ SSH ข้อมูลกระเป๋าเงินคริปโต ข้อมูลรับรองคลาวด์ และความลับของโปรเจกต์ ที่น่ากังวลคือมัลแวร์เจาะจงมองหาไฟล์ตั้งค่าของเครื่องมือ AI ยอดนิยมที่นักพัฒนาไทยจำนวนมากใช้ เช่น Anthropic Claude, Google Gemini และ Cursor หากบริษัทซอฟต์แวร์หรือสตาร์ตอัปไทยติดตั้งแพ็กเกจปลอมเหล่านี้เข้าไปในไปป์ไลน์ ก็อาจทำให้ซอร์สโค้ดและคีย์คลาวด์ทั้งองค์กรรั่วไหลได้ องค์กรจึงควรยกระดับการตรวจสอบ dependency และระมัดระวังแพ็กเกจที่มีชื่อคล้ายเครื่องมือยอดนิยม
คำแนะนำ
ผู้ที่ติดตั้งแพ็กเกจที่กล่าวถึงข้างต้นควรลบออกจากเครื่องทันที สันนิษฐานว่าถูกเจาะแล้วและเปลี่ยนข้อมูลรับรองทั้งหมด (rotate credentials) บล็อกช่องทางการสื่อสารออกที่เป็นอันตราย และเปิดใช้การสแกน dependency ในไปป์ไลน์ CI/CD เพื่อตรวจจับแพ็กเกจที่เพิ่งเผยแพร่ใหม่หรือน่าสงสัย นักพัฒนาควรตรวจสอบชื่อแพ็กเกจอย่างละเอียดก่อนติดตั้ง โดยเฉพาะแพ็กเกจที่มีชื่อคล้ายเครื่องมือยอดนิยม และหลีกเลี่ยงการพึ่งพาการตรวจสอบ dependency แบบผิวเผิน ควรจำกัดสิทธิ์ของ postinstall script และแยกสภาพแวดล้อม build ออกจากข้อมูลรับรองที่มีความอ่อนไหวสูงเท่าที่ทำได้
Indicators of Compromise (IoCs)
หมายเหตุ: URL และ IP ด้านล่าง defang ไว้ (
hxxp,[.],[:]) เพื่อความปลอดภัย ห้ามเข้าถึงโดยตรง
| ประเภท | ตัวบ่งชี้ | คำอธิบาย |
|---|---|---|
| npm package | rollup-packages-polyfill-core | แพ็กเกจปลอม Rollup polyfill — XRAY-1008625 |
| npm package | rollup-runtime-polyfill-core | แพ็กเกจปลอม Rollup polyfill — XRAY-1008531 |
| npm package | swift-parse-stream | แพ็กเกจขั้นที่สอง (SVG utility) — XRAY-1005725 |
| npm package | quirky-token | แพ็กเกจขั้นที่สอง — XRAY-1003392 |
| npm package | rollup-plugin-polyfill-connect | แพ็กเกจขั้นที่สอง — XRAY-973019 |
| npm package | react-icon-svgs | แพ็กเกจที่ติดตั้ง rollup-plugin-polyfill-connect — XRAY-1011624 |
| URL | hxxps[:]//www[.]jsonkeeper[.]com/b/3P9BF | ดึง JSON payload แล้ว eval ฟิลด์ model |
| URL | hxxp[:]//216[.]126[.]236[.]244/api/service/98cb54c0b4ac259d30c9c1ca1ae87c68 | ดาวน์โหลดเพย์โหลด AES-256-CBC |
| URL | hxxp[:]//216[.]126[.]236[.]244/api/service/makelog | อัปโหลดคลิปบอร์ด |
| URL | hxxp[:]//216[.]126[.]236[.]244/api/service/process/ | C2 API |
| URL | hxxp[:]//216[.]126[.]236[.]244:4801 | Socket.IO remote access |
| URL | hxxp[:]//216[.]126[.]236[.]244:4806/upload | อัปโหลดไฟล์ที่เก็บได้ |
| URL | hxxp[:]//216[.]126[.]236[.]244:4809/upload | อัปโหลดข้อมูลเบราว์เซอร์/กระเป๋าเงิน |
| URL | hxxp[:]//216[.]126[.]236[.]244:4809/cldbs | อัปโหลดข้อมูล cloud DB |
| IP Address | 216[.]126[.]236[.]244 | โฮสต์ C2 หลัก |
| File Name | pack | เพย์โหลด loader ในโฟลเดอร์ temp |
| File Name | scdata.js | คอมโพเนนต์ remote access |
| File Name | ldata.js | คอมโพเนนต์ขโมยข้อมูลเบราว์เซอร์/กระเป๋าเงิน |
| File Name | vhost.ctl | ไฟล์ที่มัลแวร์สร้าง/ใช้งาน |
คำสั่งและพฤติกรรมที่ต้องเฝ้าระวัง (hunt-only — ไม่เข้า index อัตโนมัติ): npm install swift-parse-stream --no-save --silent --no-audit --no-fund, npm install quirky-token --no-save --silent --no-audit --no-fund, การรัน node pack / node scdata / node ldata, และการเรียก pbpaste / Get-Clipboard เพื่อดึงคลิปบอร์ด
