- GitHub Action อย่างเป็นทางการถูกปลอมด้วยการ อัปเดตแท็กแบบบังคับ จนเกิด การโจมตีซัพพลายเชนที่กระจายมัลแวร์
- ผู้โจมตี สลับ 75 จาก 76 แท็กไปยังคอมมิตอันตราย ทำให้มี เวิร์กโฟลว์มากกว่า 10,000 รายการ ได้รับผลกระทบ
- สคริปต์ที่ถูกปลอมทำงานเป็น 3 ขั้นตอนคือ รวบรวมข้อมูลลับ · เข้ารหัส · ส่งข้อมูลออก และมีโค้ด TeamPCP Cloud stealer รวมอยู่ด้วย
- แท็กที่ติดเชื้อยังคงใช้งานได้อยู่ โดยยืนยันว่า @0.35.0 หรือ commit SHA ที่ระบุเท่านั้นที่ปลอดภัย
- จำเป็นต้องเปลี่ยนข้อมูลรับรองทั้งหมดและ ตรึงด้วย commit SHA และยังพบการปนเปื้อนแบบเดียวกันในอิมเมจบน Docker Hub
ภาพรวมการโจมตีซัพพลายเชนของ Trivy GitHub Actions
- GitHub Action อย่างเป็นทางการของ Trivy (
aquasecurity/trivy-action) ถูกผู้โจมตีปลอมด้วยวิธี บังคับอัปเดตแท็ก (force-push) จนมีการกระจายโค้ดอันตราย
- ผู้โจมตีเปลี่ยน 75 จาก 76 แท็กเวอร์ชัน ให้ชี้ไปยังคอมมิตอันตราย เพื่อให้ถูกรันอัตโนมัติใน CI/CD pipeline
- มี ไฟล์ GitHub workflow มากกว่า 10,000 ไฟล์ ที่อ้างอิง action นี้อยู่ ทำให้ขอบเขตความเสียหายกว้างมาก
- แท็กที่ติดเชื้อยังคงใช้งานได้อยู่ และยืนยันว่า @0.35.0 เป็นเวอร์ชันเดียวที่ปลอดภัย
- Socket ตรวจพบเหตุการณ์ GitHub Action อันตราย 182 รายการแบบเรียลไทม์ตั้งแต่ 19:15 UTC และจัดประเภทเป็น Backdoor, Infostealer, และ Reconnaissance
สาเหตุและวิธีดำเนินการของการโจมตี
- ตามข้อมูลจากผู้ดูแล Trivy การโจมตีครั้งนี้เกิดจาก การขโมยข้อมูลรับรองที่มีสิทธิ์เขียน
- ในการเจาะระบบก่อนหน้านี้ช่วงต้นเดือนมีนาคม ความลับในสภาพแวดล้อม CI รั่วไหล และกระบวนการหมุนเปลี่ยน (rotating) ไม่สมบูรณ์ ทำให้ข้อมูลรับรองชุดใหม่บางส่วนยังตกอยู่กับผู้โจมตี
- ผู้โจมตีใช้ข้อมูลรับรองนี้เพื่อทำ การอัปเดตแท็กที่ผ่านการยืนยันตัวตน โดยไม่ต้องอาศัยช่องโหว่ของ GitHub เอง
- แทนที่จะ push ไปยัง branch หรือสร้าง release ใหม่ ผู้โจมตีเลือก เขียนทับแท็กเดิมแบบบังคับให้ชี้ไปยังคอมมิตใหม่
- แต่ละแท็กถูกปลอมให้ดูเหมือนปกติ โดยคัดลอก metadata ของคอมมิตเดิมไว้ทั้งหมด เช่น ผู้เขียน อีเมล เวลาประทับ และข้อความคอมมิต
- อย่างไรก็ตาม คอมมิตต้นฉบับมีการเซ็น GPG แต่คอมมิตของผู้โจมตี ไม่มีลายเซ็น และวันที่ของ parent commit ไม่สอดคล้องกันเพราะเป็นปี 2026
- แม้ GitHub จะแสดงสถานะ Immutable Release ก็ยังเป็นไปได้ว่าผู้โจมตีเผยแพร่ในสภาพอันตรายก่อนแล้วจึงล็อกไว้
- ดังนั้นอย่าพึ่งพาป้าย “Immutable” และวิธีใช้งานที่ปลอดภัยมีเพียง การตรึงด้วย commit SHA (pinning) เท่านั้น
โครงสร้างการปลอมแท็ก
- ผู้โจมตีสร้างคอมมิตใหม่โดยอิงจากคอมมิตล่าสุดของ branch
master (57a97c7e)
- เปลี่ยนเฉพาะไฟล์
entrypoint.sh ให้เป็นเวอร์ชันอันตราย ส่วนไฟล์อื่นคงเดิม
- แต่ละแท็กปลอมยังคัดลอกหมายเลข PR ข้อความคอมมิต และข้อมูลผู้เขียนจากของเดิมไว้ทั้งหมด
- หากหน้า GitHub release แสดงข้อความ “0 commits to master since this release” อาจใช้เป็น ตัวบ่งชี้เชิงภาพของแท็กที่ถูกปลอม ได้
- เหตุผลที่แท็ก
0.35.0 ไม่ถูกปลอม เป็นเพราะเดิมก็ชี้ไปยัง HEAD ของ master อยู่แล้ว
โครงสร้างของ payload อันตราย
entrypoint.sh ที่ถูกปลอมมีทั้งหมด 204 บรรทัด โดย บรรทัด 4~105 เป็นโค้ด Infostealer และหลังจากนั้นเป็นโค้ดสแกนของ Trivy ตามปกติ
- มัลแวร์ประกอบด้วย 3 ขั้นตอน
- ขั้นที่ 1: การรวบรวม (Collection) — ดึงข้อมูลลับจากหน่วยความจำของโปรเซส runner และจาก filesystem
- ขั้นที่ 2: การเข้ารหัส (Encryption) — เข้ารหัสข้อมูลที่เก็บมาได้ด้วย AES-256-CBC และ RSA-4096
- ขั้นที่ 3: การส่งข้อมูลออก (Exfiltration) — ส่งข้อมูลไปยังโดเมนที่ผู้โจมตีควบคุมหรือไปยังบัญชี GitHub ของเหยื่อ
-
ขั้นที่ 1: การรวบรวมข้อมูลลับ
- อ่าน environment variable ของโปรเซส GitHub Actions runner (
Runner.Worker, Runner.Listener, runsvc, run.sh) จาก /proc/<pid>/environ แล้วดึงรายการที่มีคีย์เวิร์ด env, ssh
- บน GitHub-hosted runner จะรัน สคริปต์ memory dump ที่เขียนด้วย Python ผ่าน
sudo เพื่อค้นหาแพตเทิร์น "isSecret":true ในหน่วยความจำของโปรเซส Runner.Worker
- บน self-hosted runner จะรันตัวขโมยข้อมูลรับรองจาก filesystem ที่ระบุว่าเป็น TeamPCP Cloud stealer
- เป้าหมายครอบคลุมกว้างมาก เช่น SSH key, ข้อมูลรับรอง AWS/GCP/Azure, Kubernetes token, การตั้งค่า Docker, รหัสผ่านฐานข้อมูล, ไฟล์ environment, TLS key, การตั้งค่า VPN, Webhook URL, คีย์กระเป๋าเงิน และอื่น ๆ
-
ขั้นที่ 2: การเข้ารหัส
- สร้าง session key ขนาด 32 ไบต์ด้วย
openssl rand แล้วเข้ารหัสข้อมูลด้วย AES-256-CBC
- session key จะถูกเข้ารหัสด้วยกุญแจสาธารณะ RSA-4096 โดยใช้ OAEP padding
- ข้อมูลที่เข้ารหัสแล้ว (
payload.enc) และ session key (session.key.enc) จะถูกรวมเป็น tpcp.tar.gz
-
ขั้นที่ 3: การส่งข้อมูลออก
- ช่องทางแรก: ส่ง HTTPS POST ไปที่
https://scan[.]aquasecurtiy[.]org (ใช้โดเมนที่สะกด aquasecurity ผิด)
- ช่องทางที่สอง: หากล้มเหลว จะใช้ GitHub Personal Access Token ของเหยื่อเพื่อสร้าง public repository ชื่อ
tpcp-docs
- อัปโหลด
tpcp.tar.gz เป็น release asset → จากนั้นผู้โจมตีค้นหา repository นี้ผ่าน GitHub Search เพื่อเก็บข้อมูล
- การใช้โครงสร้างพื้นฐานของ GitHub ช่วยพยายามหลบเลี่ยงไฟร์วอลล์และอาจเพิ่มโอกาสหลบการตรวจจับ
- ขั้นสุดท้ายมีการลบไฟล์ชั่วคราวเพื่อลดร่องรอย
ผู้โจมตีและผู้อยู่เบื้องหลัง
- ในคอมเมนต์ของโค้ดอันตรายมีการระบุชื่อ “TeamPCP Cloud stealer” ไว้ชัดเจน
- TeamPCP (DeadCatx3, PCPcat, ShellForce) เป็น กลุ่มโจมตีสภาพแวดล้อมคลาวด์เนทีฟ ที่เคยมีกรณีใช้ประโยชน์จากช่องโหว่ใน Docker API, Kubernetes, Redis และ Ray dashboard
- เมื่อเดือนกุมภาพันธ์ 2026 Flare และ The Hacker News เคยรายงานถึง แคมเปญ ransomware, การขโมยข้อมูล และการขุดคริปโต ที่เกี่ยวข้องกับกลุ่มนี้
- ฟังก์ชันเก็บ Solana validator key และกระเป๋าเงินคริปโต สอดคล้องกับแรงจูงใจทางการเงิน
การรับมือและคำแนะนำ
- หยุดใช้แท็กเวอร์ชันทั้งหมดของ Trivy Action และใช้ได้เฉพาะ commit SHA
57a97c7e7821a5776cebc9bb87c984fa69cba8f1 หรือ แท็ก 0.35.0 เท่านั้น
- pipeline ที่ติดเชื้อควรถูกมองว่าเป็น การรั่วไหลของความลับแบบสมบูรณ์ และต้องเปลี่ยนข้อมูลรับรองคลาวด์, SSH key, API token, รหัสผ่านฐานข้อมูล, Docker token ทั้งหมดทันที
- แนะนำให้ตรวจสอบว่ามี repository
tpcp-docs อยู่ใน GitHub organization หรือไม่ และตรวจสอบ log ของ trivy-action ที่รันหลัง 19:00 UTC ของวันที่ 19 มีนาคม
ตัวบ่งชี้การบุกรุก (IOCs)
- ตัวบ่งชี้ด้านเครือข่าย:
scan[.]aquasecurtiy[.]org
- แฮชไฟล์:
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a (entrypoint.sh)
- GitHub Actions ที่ติดเชื้อ: ครอบคลุมทุกเวอร์ชันของ
aquasecurity/trivy-action@0.0.1 ~ @0.34.2 (รวม 75 แท็ก)
อัปเดตเพิ่มเติม (22 มีนาคม)
- ยืนยันแล้วว่าบน Docker Hub ก็มี อิมเมจ Trivy (
0.69.4, 0.69.5, 0.69.6, latest) ที่ปนเปื้อน payload แบบ Infostealer เดียวกัน
- แท็ก
latest ถูกชี้ไปยังอิมเมจอันตรายและถูกแจกจ่ายให้ผู้ใช้ในช่วงเวลาที่มีการเปิดเผย
- รายละเอียดเพิ่มเติมสามารถดูได้จากรายงานแยกของ Socket “Trivy Docker Images Compromised”
1 ความคิดเห็น
ความเห็นจาก Hacker News
สงสัยว่าทำไม GitHub ถึงไม่บังคับใช้ การจัดการเวอร์ชันแบบเปลี่ยนแปลงไม่ได้ (immutable versioning) กับ Actions
ในคู่มือความปลอดภัยแนะนำให้ pin ด้วย commit SHA แต่ถ้าทำให้ไม่สามารถเผยแพร่ Action ได้เลยหากไม่ pin ตั้งแต่แรก ก็น่าจะช่วยลดปัญหาแบบนี้ได้
ในมุมของทีมความปลอดภัย การ pin เวอร์ชันปลอดภัยกว่า แต่ขณะเดียวกันถ้า อัปเดตความปลอดภัยไม่ถูกนำมาใช้โดยอัตโนมัติ ก็อาจกลายเป็นความเสี่ยงได้
ท้ายที่สุดต้องมีทางออกที่ตอบโจทย์ทั้งสองด้านโดยไม่ทำลายประสิทธิภาพการทำงาน
อยากเรียกสิ่งนี้ว่า “ความย้อนแย้งของการ Pin”
ถึงอย่างนั้นก็ควรเริ่มลงมือเปลี่ยนกันสักวันหนึ่ง
การยอมให้อัปเดตอาจกลับช่วยเพิ่มความปลอดภัยได้ด้วยซ้ำ
นี่เป็นปัญหาคล้ายกับข้อถกเถียงเรื่อง static linking vs dynamic linking
แถม Trivy Action เองก็ถูกออกแบบมาให้ดึงเวอร์ชันล่าสุดอยู่แล้ว
เหตุการณ์นี้เป็นคำเตือนว่า ผลิตภัณฑ์ด้าน “ความปลอดภัยของซัพพลายเชน (supply chain security)” เองก็อาจเปราะบางพอ ๆ กับสแตกที่มันพยายามปกป้อง
โดยเฉพาะเครื่องมือความปลอดภัยแบบ “รันเราได้ทุกที่ (run us everywhere)” ซึ่งเปิดช่องทางโจมตีใหม่ที่ทำให้การโจมตีเพียงครั้งเดียวสามารถทำให้ผู้ใช้จำนวนมากตกอยู่ในความเสี่ยงพร้อมกันได้
ตอนแรกนึกว่า Trivy ไม่ได้ทำ การหมุนเวียนข้อมูลรับรอง (rotation) อย่างถูกต้อง
แต่พวกเขาอธิบายว่า “ระหว่างกระบวนการหมุนเวียนแบบไม่เป็นอะตอม (non-atomic) ผู้โจมตีอาจล่วงรู้โทเคนใหม่ได้”
GitHub ปกติจะไม่แสดงโทเคนอีกหลังจากออกให้แล้ว แต่ก็อาจต่างกันไปตามวิธีการยืนยันตัวตนที่ใช้
แค่สร้างองค์กร GitHub ใหม่ ชื่อนั้นก็ถูกยึดไปทันที จนต้องขอให้ GitHub ทำ กระบวนการสร้างแบบอะตอมมิก ให้
เป็นเหตุการณ์ที่คำว่า “ควรสแกนหาช่องโหว่ ไม่ใช่กลายเป็นช่องโหว่เสียเอง” ใช้ได้อย่างเหมาะเจาะ
มีเหตุการณ์ที่เกี่ยวข้องคือ การถูกเจาะซัพพลายเชนของ Trivy แบบชั่วคราว
เมื่อวันที่ 22 มีนาคม ผู้โจมตีใช้ข้อมูลรับรองที่ขโมยมาเผยแพร่ อิมเมจ DockerHub ของ Trivy v0.69.5 และ v0.69.6 ที่เป็นอันตราย
(ลิงก์ประกาศความปลอดภัย)
มีเหตุการณ์สองครั้งในวันที่ 19 และ 22 มีนาคม และดูเหมือนว่าผู้โจมตีจะคงสิทธิ์เข้าถึงไว้ได้ต่อเนื่องแม้จะมีการหมุนเวียนข้อมูลรับรองไปแล้วสองรอบ
“สองสัปดาห์ที่ผ่านมาแย่มาก”
เพราะ Trivy ถูกเจาะ เลยต้องรับมือกับ รายงานความปลอดภัยและการประชุม จำนวนมาก
เป็นบทเรียนว่า “การทำซอฟต์แวร์ความปลอดภัย ไม่ได้แปลว่าต้องเก่งเสมอไป”
ทีมความปลอดภัยของเราก็พยายามจะนำสแกนเนอร์ตัวใหม่เข้ามาทุกเดือน แต่ถ้าเราอนุญาต สิทธิ์เข้าถึงในวงกว้าง ตามที่พวกเขาร้องขอ เราคงโดนเจาะไปหลายรอบแล้ว
setup-trivyAction โคลน main branch ตรง ๆ แล้วรันเชลล์สคริปต์หมายความว่าสามารถรันโค้ดตามอำเภอใจได้ในทุก CI workflow
Aqua ถูกเจาะเมื่อต้นเดือนนี้ และหลังจาก กักกันล้มเหลว ถึงสองครั้ง ก็ลามไปถึงบัญชี Docker Hub ด้วย
ตอนนี้คิดว่าพวกเขาจำเป็นต้องให้ผู้เชี่ยวชาญภายนอกเข้ามาช่วยแล้ว
ส่วนใหญ่มันก็เป็นแค่ตัวสร้างรายงานเสียงดัง และถ้าผู้โจมตีเข้ามาอยู่ข้างในได้แล้ว มันก็ป้องกันอะไรไม่ได้เลย
สแกนเนอร์ใหม่ควรถูกจำกัดให้อยู่ใน แซนด์บ็อกซ์ที่แยกออกมา และเข้าถึงได้เฉพาะข้อมูลแบบอ่านอย่างเดียว พร้อมยังไม่ควรให้สิทธิ์ใน production จนกว่าจะผ่านการตรวจสอบเพียงพอ
ไม่อย่างนั้นก็ แทบไม่ต่างจากเอาคีย์ลับไปโพสต์ลง pastebin
มันกลายเป็นวัฒนธรรมความปลอดภัยแบบ “ขยับให้เร็วแล้วพังทุกอย่าง” ไปแล้ว
เลยเกิดวัฒนธรรมที่ ซอฟต์แวร์ความปลอดภัยคุณภาพต่ำ ก็ยังต้องนำมาใช้เสมอ
ส่วนตัวคิดว่า Trivy เองไม่ได้แย่ และบริษัทเราก็ใช้อยู่
เพียงแต่เรา ตรึงเวอร์ชันด้วย Nix และเขียน Actions workflow เอง จึงไม่ได้รับผลกระทบจากการถูกเจาะครั้งนี้
ผู้โจมตีสามารถทำ การอัปเดตแท็กแบบบังคับ (force-update) ได้ในขณะที่ผ่านการยืนยันตัวตนแล้ว
เรื่องนี้น่าจะป้องกันได้ถ้าเปิดใช้ตัวเลือกเก่าของ GitHub ที่ชื่อ “ห้ามเขียนทับแท็ก” ไว้
ยิ่งเกิดเหตุการณ์แบบนี้ซ้ำมากเท่าไร ก็ยิ่งรู้สึกว่าจำเป็นต้องมีมาตรฐานอย่าง Software Building Code
ชวนสงสัยว่าในปี 2026 จะมีเหตุผลแบบนี้เพิ่มขึ้นอีกกี่ครั้ง