1 คะแนน โดย GN⁺ 2023-12-23 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • พบ ช่องโหว่ฟิชชิง ที่สามารถแสดงลิงก์และพรีวิวให้ดูเหมือนเป็นเว็บไซต์ปกติในข้อความ WhatsApp แต่เมื่อคลิกจริงจะพาไปยังเว็บไซต์ของผู้โจมตี
  • สาเหตุคือโครงสร้างที่ส่งลิงก์ในข้อความและข้อมูลพรีวิวแยกจากกัน และสามารถทำให้เกิด ความไม่สอดคล้องของพรีวิว ได้ด้วยการลบ matchedText
  • อักขระ U+202E Right-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 ได้
  • เนื่องจากต้องให้ดูเหมือนเริ่มต้นด้วย 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
  • หลังจากนั้นลบ 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 ความคิดเห็น

 
GN⁺ 2023-12-23
ความคิดเห็นบน Hacker News
  • เป็นการผสมผสานการนำฟีเจอร์ไปใช้ผิดทางที่ค่อนข้างฉลาด แต่โดยรวมแล้ว ผลกระทบด้านความปลอดภัย น่าจะถือว่าต่ำ
    อย่างดีที่สุดก็แค่ทำให้ผู้รับเปิดลิงก์ในเบราว์เซอร์ได้ ดังนั้นถ้าไม่ใช่ผู้โจมตีอย่างตำรวจหรือหน่วยข่าวกรอง ก็มักต้องมีการโจมตีต่อเนื่อง เช่น ใช้ประโยชน์จากซอฟต์แวร์ที่ยังไม่ได้แพตช์บนอุปกรณ์
    ถ้าพูดให้ถูกทางเทคนิค คงเรียกสิ่งนี้ว่า clickjacking ได้ยาก ปกติ clickjacking หมายถึงเทคนิคที่เฉพาะเจาะจงมาก คือการนำเฟรม HTML ที่มองไม่เห็นมาซ้อนทับบนคอนเทนต์อื่น
    https://owasp.org/www-community/attacks/Clickjacking
    https://portswigger.net/web-security/clickjacking

    • ผมก็ไม่เรียกสิ่งนี้ว่า clickjacking เหมือนกัน clickjacking จริง ๆ คือเทคนิคที่ทำให้เหยื่อทำการกระทำเกี่ยวกับบัญชีโดยไม่รู้ตัว และแค่เปิดลิงก์ที่ไม่ได้ตั้งใจจะเปิดนั้นไม่ได้ร้ายแรงเท่ากัน
    • ถ้าลิงก์นั้นแสดง หน้าล็อกอินที่เหมือน Instagram ทุกประการ ผมก็สงสัยว่าจะมีผู้ใช้สักกี่เปอร์เซ็นต์ที่หลังจากเผลอเชื่อพรีวิวใน WhatsApp แล้วจะกลับมาตรวจ URL อีกครั้ง
  • ทุกคนมัวแต่โฟกัสที่ อักขระขวาไปซ้าย ของ UTF แต่ Meta อย่างน้อยก็ควรยอมรับปัญหาที่ URL ในพรีวิวอาจต่างจาก URL ในข้อความ
    เข้าใจว่านี่เป็นพฤติกรรมเพื่อขยาย URL แบบย่อ แต่ก็น่าจะมีทางเลี่ยงที่ฉลาดซึ่ง Meta และ WhatsApp สามารถนำไปใช้ได้แน่ ๆ

    • ไม่ใช่ ในระบบ เข้ารหัสแบบปลายทางถึงปลายทาง พรีวิวต้องถูกสร้างที่ฝั่งผู้ส่งหรือผู้รับ ถ้าผู้รับสร้างพรีวิว IP ก็จะรั่ว สุดท้ายก็ต้องเอาฟีเจอร์พรีวิวออก
  • 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 ทั้งหมด เพื่อไม่ให้คนที่ไม่รู้จักภาษาพวกนั้นต้องเสี่ยงโดยไม่ได้ประโยชน์อะไรเลย

    • นอกเหนือจากระบบปฏิบัติการแล้ว วิดเจ็ตของ OS ทุกตัวที่แสดงข้อความควรมีตัวเลือกแบบนั้น รวมถึง TextView ของ Android ด้วย
      ค่าเริ่มต้นควรปิด ช่องทางเลี่ยงข้อความสองทิศทาง ทั้งหมด เว้นแต่นักพัฒนาจะตรวจสอบและอนุญาตช่วงข้อความใดช่วงหนึ่งอย่างชัดเจน
      มันไม่สมเหตุสมผลที่จะทำให้สแต็กการเรนเดอร์ข้อความทั้งหมดเปราะบางโดยปริยาย ในนามของการคำนึงถึงประชากรโลกน้อยกว่า 1%
  • น่าผิดหวังที่ Meta ไม่แก้ปัญหานี้ และตัดสินใจว่าจะไม่จ่าย bug bounty ให้กับนักวิจัยคนนี้ด้วย

    • เมื่อต้นปีนี้ผมรายงานปัญหาคล้ายกันไปยัง Google แต่ถูกปฏิเสธด้วยเหตุผลว่า “เกิดขึ้นได้ด้วย social engineering เท่านั้น” และ “เราเห็นว่าการแก้ไขเรื่องนี้ไม่ได้ทำให้ผู้ใช้เปราะบางน้อยลงอย่างมีนัยสำคัญ”
      ผมจะไม่ลงรายละเอียดที่นี่ แต่จากวิธีที่ Google Search เขียน URL ใหม่เป็นบางครั้ง ทำให้ผู้โจมตีสามารถหลอก URL จริงได้
      ทางที่ดีคืออย่าเชื่อ URL ที่แสดงในเว็บไซต์และแอปเด็ดขาด
    • คงยุ่งเกินไปกับการส่งคำขู่ทางกฎหมายไปยังโปรเจกต์ OSS ล่ะมั้ง
    • บางทีอาจไม่ได้ระบุชัดเจนว่าต้องการให้แก้อะไร เช่น ต้องการให้บล็อกอักขระ RTL และ Meta อาจตีความว่าให้แก้ URL ทุกแบบที่อาจทำให้เข้าใจผิด ซึ่งแทบเป็นไปไม่ได้
    • น่าจะแก้แหละ แค่ไม่ให้รางวัลกับ bounty hunter เท่านั้น
  • ประเด็นที่ว่า “เป็นไปตามที่คาดไว้เลย ลิงก์กับพรีวิวถูกส่งแยกกัน!” นั่นแหละคือ ปัญหาการออกแบบ UI ที่ใหญ่กว่า ทำไมผู้ใช้ทั่วไปต้องเปรียบเทียบลิงก์กับพรีวิวเพื่อความปลอดภัยด้วย

    • เป็นการประนีประนอมด้านความปลอดภัย หากต้องการให้มีฟีเจอร์ที่มีประโยชน์อย่างพรีวิวลิงก์ ก็มีตัวเลือกอยู่ไม่กี่แบบ
      1. สร้างที่ฝั่งผู้ส่ง ข้อเสียคือปลอมแปลงได้
      2. สร้างที่ฝั่งผู้รับ ข้อเสียคือ IP ของผู้รับรั่ว
      3. สร้างผ่านบุคคลที่สาม ข้อเสียคือข้อมูลรั่วไปยังบุคคลที่สาม
        โดยรวมแล้วผมคิดว่าข้อ 1 ดีที่สุด ผู้ส่งก็สามารถ “ปลอม” ข้อความทั้งหมดของตัวเองได้อยู่แล้ว และการใส่พรีวิวเป็นส่วนหนึ่งของข้อความก็ไม่ได้ต่างกันมาก
        ปัญหาตรงนี้คือมันไม่ชัดเจนว่าคอนเทนต์นี้มาจากผู้ส่ง มันถูกแสดงเหมือนกรอบข้อความแยกต่างหาก ดังนั้นผู้ใช้ 99% น่าจะไม่รู้ว่าคอนเทนต์นั้นมาจากผู้ส่ง
        อีกอย่าง สุดท้าย URL ก็เป็นหัวใจของเรื่องอยู่ดี ถ้าคุณคลิก URL ที่ผู้โจมตีควบคุม ผู้โจมตีก็สามารถแสดงอะไรก็ได้ตามต้องการในพรีวิว ดังนั้นประโยชน์จากการบังคับให้พรีวิวเป็น “ของจริง” จึงน้อยมาก
        ข้อ 3 ก็อาจใช้ได้ โดยเฉพาะถ้าทำแบบ double-blind เช่น ให้เชื่อมต่อไปยังฝ่ายหนึ่ง แล้วฝ่ายนั้นส่งต่อไปยังอีกฝ่ายหนึ่ง แบบนี้ฝ่ายแรกเห็น IP และฝ่ายที่สองเห็นปลายทาง แต่ตราบใดที่ไม่สมรู้ร่วมคิดกัน ก็จะไม่มีฝ่ายใดเห็นทั้งสองอย่างพร้อมกัน
        เพียงแต่ประโยชน์ค่อนข้างน้อยเมื่อเทียบกับการต้องสร้างและดูแลโครงสร้างพื้นฐานระดับนั้น
  • ชอบที่ท้ายบทความจัดหมวดหมู่สิ่งนี้เป็น reverse engineering

  • นี่ไม่ใช่ clickjacking clickjacking คือการที่ผู้โจมตีดักคลิก ทำให้ผู้ใช้คลิกเป้าหมายอื่นจริง ๆ ที่ไม่ได้ตั้งใจหรือไม่รู้ตัว
    codepoint RTL ที่ทำให้ข้อความไหลจากขวาไปซ้ายเป็นฟีเจอร์ด้าน internationalization และการใช้มันทำให้คนสับสนไม่ใช่ช่องโหว่ใหม่