15 คะแนน โดย GN⁺ 2025-11-22 | 3 ความคิดเห็น | แชร์ทาง WhatsApp
  • dependency cooldown คือ เทคนิคความปลอดภัยที่เรียบง่ายและได้ผล ซึ่งสามารถบรรเทาการโจมตีซัพพลายเชนของโอเพนซอร์สได้เป็นส่วนใหญ่
  • โดยทั่วไปผู้โจมตีจะยึดโครงการโอเพนซอร์สยอดนิยมเพื่อกระจายโค้ดอันตราย แต่ช่วงเวลาที่การโจมตี เปิดเผยอยู่มักสั้นกว่า 1 สัปดาห์
  • หากตั้งค่า cooldown ให้รอช่วงเวลาหนึ่งหลังปล่อยเวอร์ชันใหม่ (เช่น 7 วัน) จะช่วย ลดความเสี่ยงการติดเชื้อจากการอัปเดตอัตโนมัติได้มาก
  • Dependabot, Renovate, pnpm ฯลฯ รองรับ ฟีเจอร์ cooldown เป็นมาตรฐานอยู่แล้ว ตั้งค่าได้ง่ายและไม่มีค่าใช้จ่ายเพิ่ม
  • หากมี cooldown เป็นค่าพื้นฐานในระดับ package manager ก็จะช่วย เสริมความปลอดภัยของซัพพลายเชนและลดการแจ้งเตือนที่ไม่จำเป็น ได้

โครงสร้างและปัญหาของการโจมตีซัพพลายเชน

  • การโจมตีซัพพลายเชน (supply chain attack) ส่วนใหญ่มีรูปแบบเดียวกัน
    • ผู้โจมตีใช้ การขโมยข้อมูลรับรอง หรือ ช่องโหว่ CI/CD เพื่อเข้าถึงโครงการโอเพนซอร์สยอดนิยม
    • อัปโหลดการเปลี่ยนแปลงอันตรายไปยังช่องทางเผยแพร่ เช่น PyPI, npm
    • ผู้ใช้ติดตั้งเวอร์ชันที่ปนเปื้อนจากการอัปเดตอัตโนมัติหรือการไม่ตรึงเวอร์ชันไว้
    • ผู้ให้บริการด้านความปลอดภัยตรวจพบและแจ้งเตือน จากนั้นคลังแพ็กเกจจึงลบเวอร์ชันดังกล่าวออก
  • ช่วงระหว่างขั้นตอน (1)~(2) มักยาว แต่ช่วง (2)~(5) จะเกิดขึ้นภายใน ไม่กี่ชั่วโมงถึงไม่กี่วัน ทำให้ช่วงเวลาที่ผู้โจมตีดำเนินการได้ค่อนข้างสั้น
  • ช่วงเวลาเปิดโอกาสในการโจมตี (window of opportunity) ของกรณีสำคัญในช่วง 18 เดือนล่าสุด
    • xz-utils: ประมาณ 5 สัปดาห์
    • Ultralytics: 12 ชั่วโมง (ขั้นที่ 1), 1 ชั่วโมง (ขั้นที่ 2)
    • tj-actions: 3 วัน
    • chalk: น้อยกว่า 12 ชั่วโมง
    • Nx: 4 ชั่วโมง
    • rspack: 1 ชั่วโมง
    • num2words: น้อยกว่า 12 ชั่วโมง
    • Kong Ingress Controller: ประมาณ 10 วัน
    • web3.js: 5 ชั่วโมง
  • ในกรณีเหล่านี้ 8 เหตุการณ์มี ช่วงเวลาการโจมตีน้อยกว่า 1 สัปดาห์ และส่วนใหญ่สามารถป้องกันได้ด้วย cooldown

แนวคิดและประสิทธิภาพของ cooldown

  • cooldown คือวิธีชะลอการใช้งาน dependency ใหม่ออกไปเป็นช่วงเวลาหนึ่งหลังจากถูกเผยแพร่
    • ในช่วงนี้ผู้ให้บริการด้านความปลอดภัยจะมีเวลาตรวจจับได้ว่าเป็นอันตรายหรือไม่
  • ข้อดี
    • มีประสิทธิภาพที่พิสูจน์ได้จากข้อมูลจริง และป้องกันการโจมตีขนาดใหญ่ได้เป็นส่วนใหญ่
    • นำไปใช้ได้ง่ายมาก และในเครื่องมือส่วนใหญ่ ตั้งค่าได้ฟรี
    • ตัวอย่างของ Dependabot
      version: 2
      - package-ecosystem: github-actions
        directory: /
        schedule:
          interval: weekly
        cooldown:
          default-days: 7
      
    • ช่วยจูงใจให้ผู้ให้บริการด้านความปลอดภัยมีพฤติกรรมเชิงบวก: มุ่งเน้นการตรวจจับอย่างรวดเร็วแทนการแจ้งเตือนเกินจำเป็นหรือการประชาสัมพันธ์

บทสรุปและข้อเสนอแนะ

  • การโจมตี 8 จาก 10 กรณีมี ระยะเวลาไม่เกิน 1 สัปดาห์ และสามารถป้องกันได้เป็นส่วนใหญ่ด้วย cooldown 7 วัน
  • หากใช้ cooldown 14 วัน จะป้องกันได้ทุกกรณียกเว้น xz-utils
  • cooldown ไม่ใช่คำตอบที่สมบูรณ์แบบ แต่เป็น วิธีง่าย ๆ ที่ลดความเสี่ยงจากการเปิดรับได้ 80~90%
  • นอกจาก Dependabot และ Renovate แล้ว ยังควรปรับปรุงให้ package manager เองรองรับ cooldown เป็นค่าพื้นฐาน ด้วย
  • ความปลอดภัยของซัพพลายเชนไม่ใช่แค่ปัญหาทางเทคนิค แต่ยังเป็นเรื่องของ โครงสร้างความไว้วางใจทางสังคม และ cooldown ก็เป็นมาตรการบรรเทาที่ใช้งานได้จริง

3 ความคิดเห็น

 
regentag 2025-11-23

จริง ๆ ถ้าไม่มีปัญหาอะไร ผมว่าการไม่อัปเดตเลยอาจจะดีกว่าด้วยซ้ำ
จำเป็นจริงหรือที่ต้องยอมรับความเสี่ยงเพื่อนำเวอร์ชันใหม่ที่แทบไม่ได้ต่างจากเวอร์ชันก่อนหน้ามาใช้

 
GN⁺ 2025-11-22
ความคิดเห็นบน Hacker News
  • ผู้คนกังวลว่าหากไม่อัปเดตทันทีจะเสี่ยงต่อ ช่องโหว่ร้ายแรง แต่ในความเป็นจริงส่วนใหญ่ไม่เป็นเช่นนั้น
    ซอฟต์แวร์จำนวนมากไม่ได้ดีพลอยต่อเนื่อง แต่ให้ลูกค้าติดตั้งเวอร์ชันใหม่เอง จึงอัปเดตกันเป็นรอบหลายสัปดาห์หรือหลายเดือน
    สิ่งสำคัญคือ การเฝ้าติดตาม dependencies และตรวจสอบช่องโหว่ที่ถูกเปิดเผย เมื่อประเมินแล้วว่าผลิตภัณฑ์ได้รับผลกระทบจริง ค่อยอัปเดต dependency นั้นทันที

    • ทั้ง ecosystem ยังขาด วัฒนธรรมการอัปเดตแบบคัดเลือก ลักษณะนี้
      พอมีเวอร์ชันใหม่ออกมาก็มักมีความเชื่อว่าต้องอัปเดตวันนี้ทันที
      การไม่ทบทวนการเปลี่ยนแปลงจริง ๆ แล้วใช้แนวคิดแบบ “เดี๋ยวหลังจากนี้จะยิ่งยาก งั้นทำตอนนี้เลย” เป็นวิธีที่ไม่มีประสิทธิภาพ
      การพยายามอยู่แถวหน้าสุดของหมายเลขเวอร์ชันอาจ ส่งผลเสีย ต่อความปลอดภัยด้วยซ้ำ
    • ปัญหาในโลกจริงคือทีมความปลอดภัยของบริษัทใหญ่หลายแห่งบังคับใช้นโยบาย “zero CVE”
      บริษัทของเรากำหนดว่าถ้าสแกนเนอร์พบช่องโหว่ระดับวิกฤต ต้องอัปเดตภายใน 7 วัน
      ถ้าเกินกำหนดจะถือว่าผิดข้อกำหนดและเข้าสู่กระบวนการที่ซับซ้อน ดังนั้นคนส่วนใหญ่จึงอัปเดตทุกอย่างทันทีไปเลย
    • ผู้คนกลัว 0-day แต่ปัญหาส่วนใหญ่ในโลกจริงเกิดจาก ช่องโหว่ที่ไม่ได้แพตช์นานหลายร้อยวัน
    • ประเด็นสำคัญคือแอปรับ อินพุตที่ไม่รู้ที่มา จากภายนอกหรือไม่
      แอปอย่างเบราว์เซอร์ที่มีอินพุตจากภายนอกจำนวนมากควรอัปเดตบ่อย แต่กรณีอย่างแอปพยากรณ์อากาศที่มีอินพุตจำกัดจะปลอดภัยกว่าค่อนข้างมาก
    • กลยุทธ์แบบ “อัปเดตเมื่อจำเป็นเท่านั้น” ฟังดูดีในทางทฤษฎี แต่ในทางปฏิบัติต้นทุนในการประเมินแต่ละช่องโหว่ให้เข้ากับผลิตภัณฑ์นั้นสูงเกินไป
      สู้ทำการอัปเดตเป็นประจำแล้วเสริมด้วย มาตรการป้องกัน supply chain attack จะมีประสิทธิภาพกว่า
  • โมเดลแบบ Debian stable ที่ดิสทริบิวชันจัดการ dependency กลางและอัปเกรดทั้งชุดทุก ๆ หลายปี ดูสมเหตุสมผลขึ้นเรื่อย ๆ
    บาง ecosystem เคลื่อนตัวเร็วเกินไป หรือระบบแพ็กเกจของแต่ละดิสทริบิวชันยังอ่อนแอ
    ตัวอย่างเช่น การติดตั้งไลบรารี Node.js ผ่าน apt แล้วนำมาใช้ในโปรเจ็กต์ยังคงทำได้ยาก

    • อย่าสับสนระหว่าง “ความเคลื่อนไหว” กับ “การลงมือทำ”
      ecosystem ที่เคลื่อนไหวเร็วโดยไม่มีการเปลี่ยนแปลงเชิงรากฐานไม่ได้ถือว่าสุขภาพดี
      JS แทบไม่มีความก้าวหน้าที่เป็นรูปธรรมในช่วง 3 ปีที่ผ่านมา แต่ถ้าจะ build โปรเจ็กต์ที่มีอายุ 3 ปีขึ้นมาใหม่กลับต้องเจอ ความเจ็บปวดระดับรีไรต์
    • เมื่อดู ผลการค้นหาแพ็กเกจ node บน Debian จะเห็นว่ามีอยู่บ้างแต่ไม่ครบถ้วน
      ดิสทริบิวชันอย่าง Arch บางครั้งไม่มีเลย
    • สำหรับ Rust สามารถทำงานได้เพียงแค่ใช้คลังแพ็กเกจของ Debian ก็เพียงพอ
    • โมเดลเวอร์ชันเสถียรมีภาระตรงที่แอปต้องรองรับทั้งเวอร์ชันเก่าและเวอร์ชันใหม่พร้อมกัน
  • มีสมมติฐานว่าการกำหนด ช่วงคูลดาวน์ ให้กับการอัปเดต dependency เพื่อ ป้องกัน supply chain attack ดีกว่าการใช้เวอร์ชันล่าสุดทันทีเพื่อป้องกัน 0-day
    นี่คือการเปรียบเทียบระหว่างความน่าจะเป็นที่การอัปเดตจะนำช่องโหว่ใหม่เข้ามา กับความน่าจะเป็นที่จะซ่อมช่องโหว่เดิม
    ตามเกณฑ์ของ SemVer เวอร์ชันแพตช์ค่อนข้างปลอดภัยกว่า จึงอาจใช้แนวทางให้คูลดาวน์สั้นกว่าได้
    เช่น เมื่อจาก 2.3.4 มี 2.4.0 ออกมา หากไม่มีฟีเจอร์เร่งด่วน อาจรอจน 2.4.1 ออกก่อนจะดีกว่า

    • ถ้าเป็น 0-day ที่ถูกเปิดเผยจะมี security advisory ออกมา ดังนั้นเครื่องมืออย่าง Dependabot จะข้ามคูลดาวน์และแพตช์ทันที
      ช่องโหว่ส่วนใหญ่ไม่ได้มาจากการโจมตีโดยเจตนา แต่เกิดจาก บั๊กทั่วไป
    • ค่าเริ่มต้นย่อมตั้งอยู่บนสมมติฐานเสมอ และเมื่อมีข้อมูลใหม่ก็ปรับเปลี่ยนได้
  • นโยบายที่จำกัด จำนวนและความซับซ้อน ของ dependency เป็นแนวทางที่ทรงพลังยิ่งกว่า
    แทนที่จะเพิ่มไลบรารีแบบ “ทำได้ทุกอย่าง” ควรเพิ่มเฉพาะ dependency ที่เล็กและมีจุดประสงค์ชัดเจน
    นอกจากนี้ หากไลบรารีมี เวอร์ชัน LTS ที่รวมเฉพาะ security patch ก็จะช่วยให้จัดการได้ง่ายขึ้น

    • แม้จะมีการพูดถึงแนวคิดนี้บ่อย แต่ในทางปฏิบัติ การนำโค้ดที่ผ่านการพิสูจน์แล้วกลับมาใช้ มีประสิทธิภาพกว่ามาก
      การลงมือเขียนใหม่เองอาจเป็นความสิ้นเปลือง จึงอยากรู้ตัวอย่างที่ชัดเจนของ “everything library” ที่เป็นปัญหา
    • supply chain attack ส่วนใหญ่เกิดขึ้นบน พื้นผิวการโจมตีด้าน social engineering
      หากคุณไว้ใจนักพัฒนาคนเดียวกันผ่านหลายไลบรารี สิ่งที่สำคัญกว่าจำนวนแพ็กเกจคือ ความสัมพันธ์แห่งความไว้วางใจ
      ความซับซ้อนมีความสัมพันธ์กับช่องโหว่ แต่ไม่ใช่สาเหตุโดยตรง
    • การมาของ เครื่องมือ AI ทำให้ต้นทุนของการเขียน dependency ที่ไม่ใช่แกนหลักขึ้นมาเองลดลง
      ตอนนี้จึงเลือกโดยคำนึงถึงการบำรุงรักษาระยะยาวได้ ไม่ใช่ดูแค่ความเร็วระยะสั้น
    • dependency ที่แตกย่อยมากเกินไปอาจกลับเพิ่มทั้งจำนวนและ ภาระในการ build
    • การที่ไลบรารีระดับล่างยังมี dependency อื่นต่ออีกเป็นสิ่งที่ยากจะให้เหตุผลรองรับ
      ในโลกของ C++ จุดนี้บางครั้งกลายเป็นจุดแข่งขันด้วย
  • แรงกดดันให้ต้องอัปเดตเป็นเวอร์ชันล่าสุดทุกครั้ง มีที่มาจากความเชื่อผิด ๆ ว่า ซอฟต์แวร์จะดีขึ้นเสมอ
    ในความเป็นจริง มันอาจเป็นเพียงการเปลี่ยนจากบั๊กที่รู้จักอยู่แล้ว ไปเป็น บั๊กใหม่ที่ยังไม่รู้จัก
    การติดตาม issue ที่เปิดเผยไว้และแพตช์เฉพาะเมื่อจำเป็นเป็นแนวทางที่สมเหตุสมผล

    • ตัวอย่างเช่นในกรณีของ log4shell นั้น log4j 1.x ไม่ได้รับผลกระทบ แต่บั๊กถูกนำเข้ามาใน 2.x
      นั่นคือกรณีที่เวอร์ชันเก่ากลับปลอดภัยกว่า
    • ในอดีตช่วงห่างระหว่าง release ยาวกว่า จึงเห็นการยกระดับคุณภาพชัดเจน แต่ปัจจุบันการเปลี่ยนแปลงส่วนใหญ่เป็นแค่ การเปลี่ยนแปลงชายขอบ
      อาจเป็นเพราะเรากำลังใช้ซอฟต์แวร์ที่เสถียรมากพออยู่แล้วก็ได้
  • ถ้าทุกคนบอกว่า “รออีกนิดดีกว่า” สุดท้ายอาจกลายเป็น โศกนาฏกรรมของทรัพยากรร่วม ที่ไม่มีใครลุกขึ้นมาตรวจสอบก่อน
    ยิ่งรอนาน หนี้ทางเทคนิค ก็ยิ่งสะสม ดังนั้นจึงต้องมีทั้งการอัปเดตแบบค่อยเป็นค่อยไปและมาตรการบรรเทาอย่าง zero trust และ monitoring

    • การ รอประมาณหนึ่งสัปดาห์ หลังมีเวอร์ชันใหม่ ไม่ถือเป็นหนี้ทางเทคนิคก้อนใหญ่
      ในช่วงนั้นสแกนเนอร์ด้านความปลอดภัยก็สามารถตรวจพบช่องโหว่ได้แล้ว
    • supply chain attack ระยะหลังถูกตรวจพบได้เพราะ มีเวลาให้ผู้ดูแลโครงการตอบสนอง ไม่ใช่เพราะผู้บริโภคได้รับผลกระทบ
    • ต่อให้จำนวนผู้ใช้ฝั่งผู้บริโภคลดลง ก็ยังช่วยซื้อเวลาให้นักวิจัยและผู้ดูแลได้วิเคราะห์
      หากผู้โจมตีอัปโหลดรีลีสโดยไม่ได้รับอนุญาต บางครั้งก็จะถูกจับได้ทันที
    • ระบบขนาดใหญ่อย่างไรก็ต้องใช้ gradual rollout อยู่แล้ว จึงเป็นไปไม่ได้ที่จะอัปเดตทั้งระบบทันที
  • แนวคิดเรื่องคูลดาวน์นั้นดี แต่ก็มีความเสี่ยงที่ผู้โจมตีจะใช้ประโยชน์จากมันเพื่อสร้าง ความเร่งด่วนปลอม
    โดยอ้างว่าเป็น “security patch ด่วน” เพื่อหลอกให้ติดตั้งก่อนเวลา ทั้งที่เวอร์ชันนั้นอาจเป็นอันตรายจริง
    จึงต้องเตรียมรับมือการโจมตีแบบ กดดันทางจิตวิทยา เช่นนี้

    • หากผู้โจมตีปล่อย exploit พร้อม รวมการแก้บั๊กมาด้วย ก็อาจล่อให้นักพัฒนาฝ่าฝืนคูลดาวน์และติดตั้งได้
    • จึงมีคำถามว่า “จะสร้างเสียงรบกวนแบบนั้นได้อย่างไร?” — หมายถึงข้อสงสัยว่าผู้โจมตีจะชักนำกระแสความเห็นได้อย่างไร
  • อีกเหตุผลหนึ่งของคูลดาวน์คือการ ให้เวลาผู้ดูแลโครงการรับรู้ด้วยตัวเองว่าถูกเจาะแล้ว
    ผู้โจมตีมักเลือกจังหวะที่ผู้ดูแลไม่อยู่ เช่น ช่วงลาพักร้อน งานคอนเฟอเรนซ์ หรือวันหยุดนักขัตฤกษ์
    หลายโครงการมีผู้ดูแลเพียงหนึ่งหรือสองคน จึงทำให้ช่วงเวลาที่ต่างกันนี้สำคัญมาก

  • ทั้งหมดนี้ขึ้นอยู่กับลักษณะของโปรเจ็กต์และ พื้นผิวการโจมตี
    ยุคที่เพียงแค่ทำตาม “best practice” แบบสำเร็จรูปควรจบลงได้แล้ว
    ความปลอดภัยเป็นเหมือน กีฬาปะทะ ที่ต้องคิดเชิงวิพากษ์กับรายละเอียดทุกวัน

  • ยังมี ข้อจำกัดของคูลดาวน์ ในมุมที่ว่าแค่ปล่อยเวลาให้ผ่านไปไม่ได้แปลว่าจะปลอดภัยขึ้น
    หากไม่มีใครตรวจโค้ดเลย ต่อให้ผ่านไปหนึ่งสัปดาห์ความเสี่ยงก็ยังเท่าเดิม
    วิธีอย่าง gradual rollout อาจมีประสิทธิภาพมากกว่า
    โดยให้ผู้ใช้แต่ละรายตั้งค่า delay factor ของตนเอง ฝั่งที่รับความเสี่ยงได้สูงจะเจอปัญหาก่อน
    ระหว่างนั้นฝั่งที่เหลือก็ได้รับการปกป้อง
    อัปเดตที่อันตรายจะถูกนำออกจากคิว ทำให้ผู้ใช้ที่หน่วงเวลาไว้ไม่ต้องเจอมันเลย

 
aer0700 2025-11-23

ช่วงนี้บางทีก็สับสนเหมือนกันว่า ระหว่างการลงแรงเพื่อประดิษฐ์ล้อขึ้นมาใหม่กับการพยายามจัดการ dependency tetris แบบไหนพอรับมือได้มากกว่ากัน
ถ้า If for while ผิดไป ก็แค่แก้โค้ดของตัวเอง แต่พอเป็น dependency tetris แล้วจู่ ๆ ไม่รู้ว่าล้อตัวไหนบิดเบี้ยว ก็ทั้งดีบักยากด้วย