ช่องโหว่ Clickjacking บน WhatsApp ทำให้โจมตีฟิชชิงได้
(00xbyte.github.io)- พบ ช่องโหว่ฟิชชิง ที่สามารถแสดงลิงก์และพรีวิวให้ดูเหมือนเป็นเว็บไซต์ปกติในข้อความ WhatsApp แต่เมื่อคลิกจริงจะพาไปยังเว็บไซต์ของผู้โจมตี
- สาเหตุคือโครงสร้างที่ส่งลิงก์ในข้อความและข้อมูลพรีวิวแยกจากกัน และสามารถทำให้เกิด ความไม่สอดคล้องของพรีวิว ได้ด้วยการลบ
matchedText - อักขระ
U+202ERight-To-Left Override สามารถกลับทิศทางการแสดงผลของ URL ทำให้โดเมนจริง ดูเหมือนเป็นโดเมนปกติ ได้ - ผู้โจมตีสามารถเตรียม mirror domain ของเป้าหมายที่ต้องการปลอมตัว จากนั้นคงพรีวิวของเว็บไซต์ต้นฉบับไว้และเปลี่ยนเฉพาะค่า
textเพื่อหลอกเหยื่อ - Meta ระบุว่าสามารถปรับตรรกะการ normalize URL แบบไดนามิกได้ และผู้ใช้ควรคัดลอกลิงก์ไปตรวจสอบที่อยู่จริงก่อนคลิก
จุดที่พรีวิวลิงก์กับลิงก์จริงใน WhatsApp แยกจากกัน
- นักวิจัยต้องการตรวจสอบว่าเมื่อผู้รับข้อความ WhatsApp เรนเดอร์พรีวิวลิงก์แล้วจะเกิด HTTP request หรือไม่ จึงส่งลิงก์
webhook.siteให้เพื่อน - พบว่า HTTP request เกิดขึ้นเพียงครั้งเดียวจากฝั่งผู้ส่งเท่านั้น และยืนยันได้ว่าฝั่งผู้รับไม่ได้เรนเดอร์ลิงก์แยกต่างหาก
- จากพฤติกรรมนี้จึงสันนิษฐานว่าในข้อความ WhatsApp มีการส่ง ลิงก์และข้อมูลพรีวิว ไปพร้อมกัน และทดลองว่าทำให้สองส่วนนี้ต่างกันได้หรือไม่
Issue #1: ความไม่สอดคล้องของพรีวิวลิงก์
- ผู้วิจัยพยายามแก้ไขข้อความใน WhatsApp Web โดยตรงผ่านพร็อกซี แต่ด้วย E2EE ของ WhatsApp ทำให้การดัดแปลงแบบง่ายด้วยเครื่องมืออย่าง Burp Suite ทำได้ยาก
- จึงเปลี่ยนไปวาง breakpoint ใน JavaScript ก่อนที่ข้อความที่เข้ารหัสจะถูกส่งผ่าน WebSocket เพื่อดู message object
- ใน message object มีพร็อพเพอร์ตีของเนื้อหาลิงก์และข้อมูลพรีวิวแยกกันอยู่
text: เนื้อหาข้อความcanonicalURL: โดเมนที่แสดงด้านล่างพรีวิวmatchedText: ค่าที่ดูเหมือนใช้เปรียบเทียบกับcanonicalURLและทดสอบว่าค่านี้ปรากฏอยู่ในtextหรือไม่
- หากเปลี่ยน
textเป็นgoogle.comใน message object ที่เดิมใช้สำหรับinstagram.comพรีวิวจะหายไปและเหลือเพียงลิงก์ Google - แต่เมื่อ ลบพร็อพเพอร์ตี
matchedTextออก ก็สามารถสร้าง ข้อความที่ลิงก์จริงกับพรีวิวไม่ตรงกัน ได้
Issue #2: การอำพรางการแสดงลิงก์ด้วย U+202E
- เพื่อไม่ให้เนื้อหาลิงก์จริงถูกเปิดเผย ผู้วิจัยจึงทำ fuzzing เพื่อดูว่าอักขระ Unicode สามารถเปลี่ยนการแสดงข้อความได้หรือไม่
U+202Eคืออักขระ Right-To-Left Override ที่ทำให้ข้อความ แสดงผลย้อนลำดับ ต่อหน้าผู้ใช้- หากใช้
U+202Eอย่างเดียว รูปลักษณ์ของลิงก์จะดูแปลกจนมีโอกาสถูกคลิกต่ำ จึงต้องจัดสตริงที่กลับด้านให้ดูเหมือน URL ปกติ
วิธีประกอบ mirror URL
- เป้าหมายคือสร้าง URL ที่เมื่อกลับด้านแล้วจะดูเหมือน
https://instagram.com - หากกลับสตริงแบบตรงไปตรงมา จะได้
moc.margatsni//:sttphแต่ TLD อย่าง.margatsniไม่สามารถจดทะเบียนได้ - วิธีแก้คือใช้ TLD ที่จดทะเบียนได้จริงให้ดูเหมือนเป็น subdomain
- ตัวอย่างเช่น ใช้ TLD ของเนเธอร์แลนด์
.nlจะสามารถสร้างสตริงที่ดูเหมือนln.instagram.comได้
- ตัวอย่างเช่น ใช้ TLD ของเนเธอร์แลนด์
- เนื่องจากต้องให้ดูเหมือนเริ่มต้นด้วย
https://จึงเติม path ที่ถูกต้องอย่าง//:sptthต่อท้าย - ผลลัพธ์คือ
https://moc.margatsni.nl//:sptthซึ่งเมื่อใช้ร่วมกับU+202Eจะสามารถดูเหมือนhttps://ln.instagram.com//:sptthได้ - นักวิจัยเรียกเทคนิคนี้ว่า 2K2E
ลำดับการโจมตี
- ผู้โจมตีซื้อ mirror domain ของเว็บไซต์ที่ต้องการปลอมตัว
- ตัวอย่าง: หากต้องการให้ดูเหมือน
ln.instagram.comก็จะซื้อmoc.margatsni.nl
- ตัวอย่าง: หากต้องการให้ดูเหมือน
- จากนั้นสร้างข้อความที่มีลิงก์โดเมนต้นฉบับเพื่อดึงพรีวิวของเว็บไซต์นั้นมาก่อน
- ใน object ตัวอย่าง
text,matchedText,canonicalUrlล้วนเป็นhttps://instagram.com/ - รวมถึงค่าที่เกี่ยวข้องกับพรีวิวอย่าง
description,title,jpegThumbnail,thumbnailDirectPath
- ใน object ตัวอย่าง
- หลังจากนั้นลบ
matchedTextออก แล้วเปลี่ยนค่าtextเป็นรูปแบบ\u202ehttps://moc.margatsni.nl//:sptth - ข้อความสุดท้ายจะแสดงพรีวิวของ Instagram แต่เมื่อคลิกจะพาไปยังโดเมนที่ผู้โจมตีเตรียมไว้
การตอบสนองของ Meta และการเปรียบเทียบกับแพลตฟอร์มอื่น
- Meta ตอบว่าเนื่องจากต้องรองรับหลายแพลตฟอร์มและหลายสภาพแวดล้อม วิธี normalize URL ของแต่ละแพลตฟอร์มอาจต่างจากตรรกะฝั่งเซิร์ฟเวอร์
- บริษัทยังระบุว่ามีระบบที่สามารถปรับตรรกะการ normalize URL แบบไดนามิกได้ หากพบสแปมหรือการใช้งานในทางที่ผิดจริง
- ผู้วิจัยประเมินว่า Meta ดูเหมือนจะไม่ได้พยายามแก้ปัญหาด้านความปลอดภัยนี้อย่างจริงจังนัก แต่จะตอบสนองเมื่อระบบตรวจจับว่าเป็นสแปมเท่านั้น
- X, TikTok และ Pinterest มีการ sanitize อักขระ
U+202Eอยู่แล้ว จึงต่างจาก WhatsApp
วิธีลดความเสี่ยงที่ผู้ใช้ตรวจสอบได้เอง
- ลิงก์บน WhatsApp ไม่ควรเชื่อถือจากหน้าตาที่แสดงเพียงอย่างเดียว
- เพื่อหลีกเลี่ยงฟิชชิงแบบ 2K2E ผู้ใช้ควรคัดลอกลิงก์ก่อนคลิก แล้วตรวจสอบที่อยู่จริงจากพรีวิวในคลิปบอร์ด
- พรีวิวในคลิปบอร์ดอาจแสดงที่อยู่ลิงก์ในสภาพที่อักขระ
U+202Eถูกจัดการแล้ว - ต่อมานักวิจัยยังพบว่ามีบริการอื่นที่ไม่มีการ sanitize อย่างเหมาะสมและจึงเสี่ยงต่อ 2K2E เช่นกัน
1 ความคิดเห็น
ความคิดเห็นบน Hacker News
เป็นการผสมผสานการนำฟีเจอร์ไปใช้ผิดทางที่ค่อนข้างฉลาด แต่โดยรวมแล้ว ผลกระทบด้านความปลอดภัย น่าจะถือว่าต่ำ
อย่างดีที่สุดก็แค่ทำให้ผู้รับเปิดลิงก์ในเบราว์เซอร์ได้ ดังนั้นถ้าไม่ใช่ผู้โจมตีอย่างตำรวจหรือหน่วยข่าวกรอง ก็มักต้องมีการโจมตีต่อเนื่อง เช่น ใช้ประโยชน์จากซอฟต์แวร์ที่ยังไม่ได้แพตช์บนอุปกรณ์
ถ้าพูดให้ถูกทางเทคนิค คงเรียกสิ่งนี้ว่า clickjacking ได้ยาก ปกติ clickjacking หมายถึงเทคนิคที่เฉพาะเจาะจงมาก คือการนำเฟรม HTML ที่มองไม่เห็นมาซ้อนทับบนคอนเทนต์อื่น
https://owasp.org/www-community/attacks/Clickjacking
https://portswigger.net/web-security/clickjacking
ทุกคนมัวแต่โฟกัสที่ อักขระขวาไปซ้าย ของ UTF แต่ Meta อย่างน้อยก็ควรยอมรับปัญหาที่ URL ในพรีวิวอาจต่างจาก URL ในข้อความ
เข้าใจว่านี่เป็นพฤติกรรมเพื่อขยาย URL แบบย่อ แต่ก็น่าจะมีทางเลี่ยงที่ฉลาดซึ่ง Meta และ WhatsApp สามารถนำไปใช้ได้แน่ ๆ
clickjacking คือการที่ผู้ใช้คิดว่ากำลังกดองค์ประกอบหนึ่ง แต่จริง ๆ แล้วโดยทั่วไปมีองค์ประกอบอื่นที่มักโปร่งใสวางทับอยู่และดัก event การคลิกไป
หากให้โฟกัสกับเลเยอร์ด้านล่างที่มองเห็น แล้วตรวจจับการเกิด event
onblurผู้โจมตีก็จะรู้ได้ว่ามีการคลิก แม้ผู้ใช้จะไม่ได้รับ event นั้นก็ตามสิ่งที่ OP พบเจ๋งดี แต่ไม่ใช่ clickjacking ผมเองก็เคยใช้ อักขระ RTL ทำให้ไฟล์สกรีนเซฟเวอร์ ซึ่งใน Windows ก็คือไฟล์ executable ทั่วไปที่ต่างกันแค่นามสกุล ดูเหมือนเอกสาร Word มาก่อน น่าจะตั้งใจแกล้งเพื่อนหรือครู แต่จำเหตุผลไม่ค่อยได้แล้ว
OP ก้าวไปอีกขั้นด้วยการหาวิธีทำให้การแสดงผลเปลี่ยนไปในอีกระบบหนึ่ง นี่จึงไม่ใช่ clickjacking เพราะผู้ใช้ไม่ได้สับสนว่ากำลังคลิกองค์ประกอบใด แต่สับสนว่าลิงก์จะพาไปที่ไหน และหน้า Wikipedia ที่ลิงก์ไว้ตอนต้นบทความก็ยืนยันเช่นนั้น
ผมไม่เคยเห็น clickjacking ถูกนำไปใช้จริง แต่รู้สึกว่าวิธีที่ OP พบนี้สามารถถูกนำไปใช้ในทางร้ายได้
พูดตามตรง ผมเลิกคาดหวังไปนานแล้วว่าผู้ใช้จะแยกแยะโดเมนปลายทางเมื่อคลิกลิงก์ได้ คนส่วนใหญ่ไม่เข้าใจแนวคิดนี้เลย ส่วนที่เหลือก็ยังแยกได้ยาก
แม้แต่คนที่คิดว่าตัวเองแยกออก ก็ยังหมดแรงเมื่อทุกลิงก์พาไปยังที่อย่าง
sendgrid.tld/j3ovi3bfogobbledypoop93jnri2oเรากำลังฝึกให้ผู้คนกดลิงก์ขยะน่าสงสัยที่ถูกทำให้อ่านยากเพื่อการติดตามทุกวัน แต่ไม่มีใครสนใจเป็นแฮ็กที่เจ๋ง ปัญหาจริง ๆ ไม่ใช่ WhatsApp หรืออักขระ Unicode แบบย้อนทิศทาง แต่คือ URL นั้นเข้าใจยาก
แค่ตัวอย่างง่าย ๆ อย่าง
visa.securesite.comก็หลอกคนได้มากมายแล้ว ยังไม่เห็นทางออกที่ดีในอนาคตอันใกล้ความสับสนทั่วไปเกี่ยวกับชื่อโฮสต์และโดเมนเป็นปัญหาที่ยากกว่า แต่เบราว์เซอร์ต่าง ๆ ก็พยายามลดผลกระทบอยู่บ้าง เช่น เน้นส่วนชื่อโดเมนให้เด่นขึ้น เช่นเดียวกับเทคนิคฟิชชิงส่วนใหญ่ สุดท้าย passkey น่าจะเป็นสิ่งที่ทำให้มันจบลง
RTL เป็นแหล่งของช่องโหว่ด้านความปลอดภัยมหาศาลมาตลอดช่วงที่มันมีอยู่ ไม่เข้าใจว่าทำไมระบบปฏิบัติการจึงไม่มีการตั้งค่าให้ปิด RTL ทั้งหมด เพื่อไม่ให้คนที่ไม่รู้จักภาษาพวกนั้นต้องเสี่ยงโดยไม่ได้ประโยชน์อะไรเลย
TextViewของ Android ด้วยค่าเริ่มต้นควรปิด ช่องทางเลี่ยงข้อความสองทิศทาง ทั้งหมด เว้นแต่นักพัฒนาจะตรวจสอบและอนุญาตช่วงข้อความใดช่วงหนึ่งอย่างชัดเจน
มันไม่สมเหตุสมผลที่จะทำให้สแต็กการเรนเดอร์ข้อความทั้งหมดเปราะบางโดยปริยาย ในนามของการคำนึงถึงประชากรโลกน้อยกว่า 1%
น่าผิดหวังที่ Meta ไม่แก้ปัญหานี้ และตัดสินใจว่าจะไม่จ่าย bug bounty ให้กับนักวิจัยคนนี้ด้วย
ผมจะไม่ลงรายละเอียดที่นี่ แต่จากวิธีที่ Google Search เขียน URL ใหม่เป็นบางครั้ง ทำให้ผู้โจมตีสามารถหลอก URL จริงได้
ทางที่ดีคืออย่าเชื่อ URL ที่แสดงในเว็บไซต์และแอปเด็ดขาด
ประเด็นที่ว่า “เป็นไปตามที่คาดไว้เลย ลิงก์กับพรีวิวถูกส่งแยกกัน!” นั่นแหละคือ ปัญหาการออกแบบ UI ที่ใหญ่กว่า ทำไมผู้ใช้ทั่วไปต้องเปรียบเทียบลิงก์กับพรีวิวเพื่อความปลอดภัยด้วย
โดยรวมแล้วผมคิดว่าข้อ 1 ดีที่สุด ผู้ส่งก็สามารถ “ปลอม” ข้อความทั้งหมดของตัวเองได้อยู่แล้ว และการใส่พรีวิวเป็นส่วนหนึ่งของข้อความก็ไม่ได้ต่างกันมาก
ปัญหาตรงนี้คือมันไม่ชัดเจนว่าคอนเทนต์นี้มาจากผู้ส่ง มันถูกแสดงเหมือนกรอบข้อความแยกต่างหาก ดังนั้นผู้ใช้ 99% น่าจะไม่รู้ว่าคอนเทนต์นั้นมาจากผู้ส่ง
อีกอย่าง สุดท้าย URL ก็เป็นหัวใจของเรื่องอยู่ดี ถ้าคุณคลิก URL ที่ผู้โจมตีควบคุม ผู้โจมตีก็สามารถแสดงอะไรก็ได้ตามต้องการในพรีวิว ดังนั้นประโยชน์จากการบังคับให้พรีวิวเป็น “ของจริง” จึงน้อยมาก
ข้อ 3 ก็อาจใช้ได้ โดยเฉพาะถ้าทำแบบ double-blind เช่น ให้เชื่อมต่อไปยังฝ่ายหนึ่ง แล้วฝ่ายนั้นส่งต่อไปยังอีกฝ่ายหนึ่ง แบบนี้ฝ่ายแรกเห็น IP และฝ่ายที่สองเห็นปลายทาง แต่ตราบใดที่ไม่สมรู้ร่วมคิดกัน ก็จะไม่มีฝ่ายใดเห็นทั้งสองอย่างพร้อมกัน
เพียงแต่ประโยชน์ค่อนข้างน้อยเมื่อเทียบกับการต้องสร้างและดูแลโครงสร้างพื้นฐานระดับนั้น
ชอบที่ท้ายบทความจัดหมวดหมู่สิ่งนี้เป็น reverse engineering
นี่ไม่ใช่ clickjacking clickjacking คือการที่ผู้โจมตีดักคลิก ทำให้ผู้ใช้คลิกเป้าหมายอื่นจริง ๆ ที่ไม่ได้ตั้งใจหรือไม่รู้ตัว
codepoint RTL ที่ทำให้ข้อความไหลจากขวาไปซ้ายเป็นฟีเจอร์ด้าน internationalization และการใช้มันทำให้คนสับสนไม่ใช่ช่องโหว่ใหม่