การโจมตี Meltdown ที่เริ่มมีรายงานในสัปดาห์นี้เปิดทางให้แฮกเกอร์ที่สามารถรันโปรแกรมบนเครื่องของเหยื่อ สามารถอ่านข้อมูลบนหน่วยความจำได้ทั้งหมด แม้จะไม่มีสิทธิ์อ่านหน่วยความจำส่วนนั้นๆ เช่น หน่วยความจำของเคอร์เนล และโปรเซสอื่นๆ
การสาธิตที่ชัดเจนที่สุดคงเป็นการขโมยรหัสผ่านที่ผู้ใช้พิมพ์บนโปรแกรมอื่นดังวิดีโอต่อไปนี้
Speculative Execution
กระบวนการโจมตี Meltdown อาศัยเทคนิคการออกแบบซีพียูเพื่อให้ทำงานได้เร็วขึ้นที่ชื่อว่า speculative execution เป็นการรันคำสั่งถัดไปทันที แม้ว่าตามโปรแกรมแล้วจะต้องรอเงื่อนไขก่อนหน้า โดยลองดูจากโค้ดตัวอย่างของ Project Zero
ขณะที่โค้ดอ่านค่าตัวแปร untrusted_offset_from_caller
ในบรรทัดที่ 6 ก่อนจะตรวจสอบเงื่อนไข if ในบรรทัดที่ 7 ในซีพียูยุคใหม่ บรรทัดที่ 8 ที่เป็นการอ่านค่าจากหน่วยความจำจะเริ่มทำงานไปทันทีโดยไม่สนใจว่าการตรวจสอบเงื่อนไข if เป็นจริงหรือไม่
ที่ผู้ออกแบบซีพียูออกแบบให้ทำเช่นนี้ เป็นการเตรียมข้อมูลมาไว้ล่วงหน้า เนื่องจากการเรียกข้อมูลจากหน่วยความจำอาจใช้เวลานาน (ประมาณ 400-500 CPU cycle) หากเงื่อนไข if ไม่เป็นจริง ซีพียูจะล้างข้อมูลออกเหมือนไม่เคยเกิดขึ้น ตัวโปรแกรมจะไม่เคยรับรู้ว่ามีการอ่านค่าในหน่วยความจำขึ้นมาแล้วและไม่สามารถเขียนโค้ดใดๆ เพื่อพิจารณาค่าในหน่วยความจำที่ซีพียูล้างออกไปนั้นได้
กระบวนการเช่นนี้ทำให้ซีพียูสามารถทำงานได้เต็มที่ขึ้นอย่างมาก ประสิทธิภาพรวมโดยรวมสูงขึ้นระดับ 10% ขึ้นไป มันเป็นเทคนิคที่ใช้งานกันมาเป็นเวลานาน และมีอธิบายอยู่ในหนังสือเรียนสถาปัตยกรรมคอมพิวเตอร์ใหม่ๆ
การโจมตี FLUSH+RELOAD
เมื่อปี 2014 Yuval Yarom และ Katrina Falkner นักวิจัยจากมหาวิทยาลัย Adelaide นำเสนอการ โจมตีที่ชื่อว่า FLUSH+RELOAD ที่เปิดให้โปรเซสของแฮกเกอร์ที่รันบนเครื่องเดียวกับเหยื่อ สามารถอ่านพฤติกรรมและคาดเดาข้อมูลในโปรเซสของเหยื่อได้ โดยสาธิตการอ่านกุญแจ PGP ออกมาจากโปรแกรม GnuPG ที่กำลังเซ็นเอกสารอยู่
การโจมตี FLUSH+RELOAD อาศัยพฤติกรรมของระบบปฎิบัติการยุคใหม่ ที่หากโปรแกรมมีการเรียกใช้ไบนารีเดียวกัน เช่น ไลบรารีเดียวกันหรือไบนารีของตัวโปรแกรมเดียวกัน (แม้จะเรียกใช้โดยผู้ใช้คนละคนที่ไม่มีสิทธิ์อ่านข้อมูลข้ามกัน) ตัวระบบปฎิบัติการก็จะโหลดไบนารีนั้นๆ ขึ้นไปยังหน่วยความจำเพียงครั้งเดียว และแชร์ร่วมกันระหว่างผู้ใช้ทั้งหมด เพื่อประหยัดหน่วยความจำ และทำให้กระบวนการโหลดโปรแกรมโดยทั่วไปเร็วขึ้น
นอกจากพฤติกรรมของระบบปฎิบัติการ FLUSH+RELOAD ยังอาศัยคำสั่ง CLFLUSH (Flush Cache Line) ที่โปรแกรมสามารถสั่งยกเลิกแคชของหน่วยความจำตำแหน่งใดๆ ได้ ทำให้เมื่อโปรเซสอื่นต้องการใช้หน่วยความจำตำแหน่งเดียวกัน ต้องโหลดใหม่จากหน่วยความจำ
กระบวนการโจมตีของ FLUSH+RELOAD คือการสั่ง CLFLUSH หน่วยความจำที่เป็นโค้ดที่เหยื่อกำลังจะรันออกจากแคชทั้งหมด แล้วทดสอบอ่านหน่วยความจำตำแหน่งนั้นอีกครั้งภายหลัง หากอ่านได้เร็วแสดงว่าเหยื่อเคยรันโค้ดในส่วนนั้นมาแล้ว
ภาพตัวอย่างจากรายงาน FLUSH+RELOAD ภาพ (A) เริ่มต้นด้วยแฮกเกอร์ล้างโค้ดส่วนที่ต้องการดูว่าเหยื่อเรียกหรือไม่ออกจากแคช หลังจากช่วงเวลาหนึ่งแฮกเกอร์ก็เรียกหน่วยความจำส่วนนั้นด้วยตัวเอง เมื่อใช้เวลานาน (สีส้ม) จึงรู้ได้ว่าเหยื่อไม่เคยรันโค้ดส่วนนั้นในช่วงเวลาที่รอ ภาพ (B) แสดงถึงกรณีที่เหยื่อรันโค้ดส่วนนั้น เมื่อแฮกเกอร์เรียกอ่านหน่วยความจำก็จะอ่านได้เร็วเพราะโค้ดอยู่ในแคชอยู่แล้ว
แม้ว่า FLUSH+RELOAD จะน่าสนใจ แต่กระบวนการโจมตียังจำกัด แฮกเกอร์ต้องเข้าใจพฤติกรรมของโปรแกรมอย่างชัดเจนเพื่อหาพฤติกรรมที่ต้องการ โดยไม่สามารถไปอ่านหน่วยความจำของเหยื่อได้โดยตรง
ซีพียูเอเอ็มดีไม่ได้รับผลกระทบจากการโจมตี FLUSH+RELOAD เนื่องจากพฤติกรรมของคำสั่ง CLFLUSH บนชิปเอเอ็มดีนั้นต่างออกไป แม้จะล้างแคชออกจาก L1 ไปแล้วแต่ก็ไม่ได้ล้างออกจาก L2/L3 ทำให้การสังเกตระยะเวลาแคชทำได้ยากกว่า
การโจมตี Meltdown
การโจมตี Meltdown มุ่งไปที่การอ่านหน่วยความจำที่โปรเซสไม่ได้รับอนุญาต เช่นหน่วยความจำของเคอร์เนล ที่ปกติแล้วหากโปรแกรมพยายามอ่านหน่วยความจำในตำแหน่งเหล่านั้น ระบบปฎิบัติการจะปิดการทำงานของโปรแกรมทันที
อย่างไรก็ดี ในระดับของซีพียูแล้ว เมื่อมีการอ้างอิงข้อมูลในหน่วยความจำตัวซีพียูจะพยายามอ่านข้อมูลเหล่านั้นมารอไว้ โดยไม่สนใจว่าตัวโปรเซสมีสิทธิ์อ่านข้อมูลเหล่านั้นจริงหรือไม่ เพราะถ้าอ่านไม่ได้จริงก่อนตัวโปรแกรมจะดึงค่าไปใช้งานได้ ระบบปฎิบัติการก็จะปิดโปรแกรมก่อนอยู่ดี
Meltdown อาศัยพฤติกรรมนี้ด้วยการสร้างโค้ดที่ โหลดหน่วยความจำโดยอาศัยข้อมูลในตำแหน่งที่ไม่มีสิทธิ์อ่านเพื่อสร้างกระบวนการส่งข้อมูลออกไปภายนอกโปรเซสที่พยายามอ่านข้อมูลนั้น
ดูโค้ดตัวอย่างจาก Project Zero โค้ดที่สอง ต่อไปนี้
โค้ดพยายามเข้าถึงหน่วยความจำส่วนที่ไม่ได้รับอนุญาต โดยอาศัยตัวแปร untrusted_offset_from_caller
เมื่อค่าตำแหน่งผิดไป หากโหลดหน่วยความจำจากคำสั่ง value = arr1->data[untrusted_offset_from_caller]
ขึ้นมาจริง ระบบปฎิบัติการก็จะปิดโปรแกรมลง เนื่องจากละเมิดการจำกัดสิทธิ์การเข้าถึงหน่วยความจำ
อย่างไรก็ดี เนื่องจากซีพียูพยายามรันคำสั่งไปล่วงหน้า ค่าในหน่วยความจำนี้จะถูกอ่านขึ้นมา และถูกคำนวณต่อไปโดยที่ตัวโปรแกรมจริงๆ ยังไม่รับรู้ และคำนวณหาค่าตัวแปร index2
(บรรทัดที่ 11) ต่อไปทันที หากค่าในตัวแปร value
มีบิตสุดท้ายเป็น 0 ค่า
index2
จะมีค่าเป็น 0x200 หากเป็น 1 จะเป็น 0x300
หลังจากนั้นกระบวนการรันคำสั่งล่วงหน้าจะโหลดหน่วยความจำตามบรรทัดที่ 13 ขึ้นมารอเอาไว้
เนื่องจากค่าตัวแปร untrusted_offset_from_caller
เป็นค่าที่ไม่ถูกต้อง เช่น ค่าใหญ่เกินไปมากจนเกินขอบเขตหน่วยความจำซอฟต์แวร์ ทำให้ตัวโปรแกรมเหมือนไม่เคยรันโค้ดบรรทัดที่ 9-15 แต่อย่างใด แต่เนื่องจากระบบการรันคำสั่งล่วงหน้าของซีพียูได้รันคำสั่งเหล่านี้ไปแล้ว (และทิ้งผลลัพธ์ทั้งหมดไป) ทำให้หน่วยความจำของ arr2->data
ถูกโหลดขึ้นแคชทิ้งเอาไว้
การโจมตี Meltdown อาศัยพฤติกรรมนี้ สร้างโปรแกรมที่หลอกล่อให้ซีพียูโหลดหน่วยความจำในส่วนที่ไม่ได้รับอนุญาตขึ้นมาดูค่าซ้ำๆ ไปเรื่อยๆ แล้วค่อยๆ สังเกตุพฤติกรรมเพื่ออ่านค่าในหน่วยความจำส่วนที่ไม่ได้รับอนุญาตให้อ่าน
กระบวนการนี้เป็นกระบวนการที่ช้า Project Zero รายงานว่าสามารถอ่านหน่วยความจำเคอร์เนลได้ด้วยอัตรา 2 KB/s ขณะที่ทีมวิจัยจาก Graz University of Technology สามารถปรับปรุงโดยใช้ชุดคำสั่ง TSX ของอินเทลจนเร่งความเร็วการอ่านหน่วยความจำได้ถึง 503 KB/s
คนทั่วไปควรทำอย่างไรเพื่อรับมือกับ Meltdown
สำหรับผู้ใช้ทั่วไป เพียงแค่รออัพเดตแพตช์จากผู้ผลิตก็สามารถป้องกันตนเองจาก Meltdown ได้เช่นเดียวกับช่องโหว่อื่นทั่วไป
อย่างไรก็ดีแพตช์ที่ออกมาจะกระทบต่องานบางประเภทมากเป็นพิเศษ โดยเฉพาะงานฐานข้อมูลอย่าง PostgreSQL ทางลดผลกระทบหากใช้ซีพียูรุ่นใหม่ๆ ที่มีฟีเจอร์ PCID (Process-Context Identifiers) จะช่วยลดผลกระทบไปได้มาก รายงานทดสอบ PostgreSQL ระบุว่าหากใช้ PCID สามารถลดผลกระทบจาก 23% เหลือ 17% ในการทดสอบที่แย่ที่สุด (อีกการทดสอบหนึ่งเมื่อเปิด PCID ผลกระทบอยู่ที่ 7%)
Phoronix ทดสอบงานรูปแบบต่างๆ ที่ได้รับผลกระทบจากแพตช์ KPTI ที่แก้การโจมตี Meltdown พบว่า เกมนั้นแทบไม่มีผลกระทบใดๆ รวมไปถึง งานตกแต่งรูปภาพ (ทดสอบด้วย Darktable) โดยทั่วไปแล้วสำหรับผู้ใช้เดสก์ทอปคงแทบไม่มีอะไรต้องกังวล
Comments
ภาพมาไม่ครบครับ
pre-execute นี่ตั้งแต่สมัย Pentium รุ่นแรกๆเลย
แล้ว Intel/AMD จะชะลอการออก CPU รุ่นใหม่เพื่อออกแบบแก้ช่องโหว่นี้ก่อนมั๊ยเนี่ย?
คำสั่งถัดๆ ??
ทางลด?
โปแกรม => โปรแกรม
ตัวตัว => ตัว
ใน ?
บรรทัดที่ 10 => บรรทัดที่ 11
ใน ?
แก้ไขและป้องกันยากมากๆ
ขออนุญาตถามในฐานะ User ธรรมดานะครับแพทช์ที่ออกมา จะกระทบ MS Access มากไม๊ครับ
windows มี patch ออกมาตั้งแต่พุธที่แล้ว ผมว่าคนทั่วไปไม่รู้สึกถึงความแตกต่างหรือไม่รู้แม้กระทั่งว่าได้ patch ไปแล้วด้วยซ้ำมั้งครับ ขนาดผมรู้ ผมยังไม่รู้สึกว่าช้าลงเลยด้วยซ้ำ อยากรู้ว่าช้าลงมากมั้ยก็ต้องลอง benchmark ดูถึงจะเห็นความแตกต่างแล้วก็จะเกิดอาการจิตตกตามมา
ขอบคุณครับ ของผม Core 2 Duo ปี 2008 ไม่รู้ได้แพทช์หรือยังกลัวเห็น benchmark แล้วจิตตกครับ ใช้ไปแบบไม่รู้อะไรท่าจะดีกว่า XD
แล้วค่อยๆ สังเกตุพฤติกรรม -> สังเกต
cpu รุ่นใหม่(Gen ใหม่) จะมีปํญหานี้ไหมเนี่ย
นั่นซิ ผมควรซื้อคอมใหม่ช่วงไหนดี เพราะไม่รู้ว่าคอมที่ออกมาจะได้รับการแก้ไขปัญหานี้ด้วยไหม และเมื่อไหร่
มีคนบอก Intel แจ้งบอกผู้ถือหุ้นว่าจะออกรุ่นแก้ไข "ภายในปีนี้" แต่ไม่มี Source ที่แน่นอน
โอเคครับ
ข่าวพวกนี้น่าจะทำให้หลายคนชะลอการซื้อ CPU ใหม่ๆลงบ้างละ
ถ้าปัญหา Meltdown นี่คงไม่มีการแก้ปัญหาโดยตรงเร็วๆ นี้ครับ กระบวนการออกแบบซีพียูมันนานกว่าที่เราเห็นมาก แต่ละรอบ 2-5 ปี ที่เราเห็นออกถี่ๆ นี่คือมันเป็น batch ไล่กันมา
การแก้โดยซอฟต์แวร์ (แยก page table ของ kernel ออกไป) ก็ทำให้ปัญหาหายไปแล้ว ผมเองเชื่อว่าอนาคตซอฟต์แวร์ต่างๆ จะปรับแต่งพฤติกรรมการทำงานให้เข้ากับพฤติกรรมของเคอร์เนลที่เปลี่ยนไป โดยรวมปัญหาในระยะยาวก็น่าจะลดลง
lewcpe.com , @wasonliw
Update ทั้งของ Windows + BIOS ประสิทธิิภาพของ SSD ลดลงเยอะอยู่นะ
https://static.techspot.com/articles-info/1556/bench/950_Atto.png
สำหรับเล่นเกมใช้งานทั่วไปคงไม่ค่อยมีผลอะไร แต่พวกเซิฟเวอร์นี่หนักเลย
ทำไมอัพเดท Bios ละลดลงเยอะมาก ทั้งๆที่ควรจะเร็วกว่าระดับ OS สิ ?
อัพเดทของ BIOS มันมี code ที่ไปปรับพฤติกรรมการเดาว่า if จะออกหัวหรือก้อยของ cpu อยู่ครับปกติเวลาเช็คว่ามีสิทธิ์อ่าน memory ตรงไหนมั้ยผลลัพธ์เกือบทุกครั้งคืออ่านได้ มันก็เลยเผลอไปทำคำสั่งต่อไปตลอด ที่ปรับใหม่ทำให้พฤติกรรมมันคาดเดาได้ยากขึ้น คนเจาะจะได้เดายากขึ้น ผลที่ตามมาก็คือเดาผิดเยอะขึ้นก็เลยทำงานช้าลงครับ
ขอบคุณครับกระจ่างละ
เล่นเจาะตรงส่วน pre-fetch ถ้าไปปิดมัน หรือทำงานได้ยากขึ้น มันก็ลดประสิทธิภาพโดยรวมอยู่แล้ว แต่แปลกใจที่ AMD ไม่ได้ทำแบบเดียวกัน? เลยช้ากว่าตั้งแต่แรก?(อันนี้แซวนะครับ เดี๋ยวแฟนๆจะโกรธ)
ก็เลยกลายเป็นว่าหลอกให้ pre-fetch ได้ แต่ก็ยังเดาได้ยากว่าข้อมูลที่ fetch มาใช่ข้อมูลเป้าหมายรึเปล่า ต่างจากของ intel ที่ flush ออกจาก cache หมดเลย เวลาดึงได้เร็วเลยเดาได้ว่าข้อมูลนั้นเป้าหมายวางไว้อยู่แล้วครับ
หลังแพทช์แล้วอยากให้ลองวัดความเร็ว CPU Intel กับ AMD สักหน่อยว่าความเร็วจะใกล้เคียงกันไม๊
เครื่องที่ใช้ i5 4300U ได้แพทช์แล้ว แต่เครื่องที่ใช้ i7 6700HQ ยังไม่ได้ ไม่แน่ใจว่าเพราะเจนใหม่ๆ มันป้องกันอยู่แล้วรึเปล่า?
มันโดนทุกเจนฯ และเห็นเขาว่ารุ่นที่เก่าที่สุดที่ได้รับผลกระทบนี่อาจจะถึง Pentium Pro ที่วางขายวันที่ 1 พ.ย. 1995 เลยมั้งครับ
ขอบคุณที่เขียนบทความอธิบายรูปแบบการโจมตีนี้ครับ
สงสัยเรื่อง speculative execution ครับ ถ้าเกิด มันเสี่ยงต่อ error
เช่น if b != 0 then c = a/b อย่างนี้ ถ้าทำ speculative execution มันจะไม่ error เหรอครับถ้า b เป็น 0