ช่องโหว่ XSS ใน LIFF SDK 2.20.0–2.31.0 อัปเดตก่อน LINE จำกัดเวอร์ชันเก่า 24 พ.ย. 2569

LIFF SDK ตั้งแต่ 2.20.0 ถึง 2.31.0 มีช่องโหว่ XSS ที่ทำงานเมื่อเปิดแอปจากลิงก์ที่ปลอมขึ้นในเบราว์เซอร์นอก LINE แก้แล้วใน 2.31.1 และ LINE จะจำกัดการใช้เวอร์ชันเก่าราว 24 พ.ย. 2569 แอปที่โหลด SDK จาก CDN edge ได้อัปเดตแล้ว ส่วนแอปที่ล็อกเวอร์ชันหรือลงจาก npm ต้องอัปเดตเอง

เผยแพร่
เวลาอ่าน
5 นาที
สรุปจาก
LINE Developers · developers.line.biz
แท็ก
#LINE#Security
ในโพสต์นี้ 6 หัวข้อ
  1. LINE ค่อย ๆ ประกาศเรื่องนี้ตลอดเดือนตุลาคม
  2. ช่องโหว่ทำงานเมื่อเปิดแอปนอก LIFF browser
  3. สิ่งที่คนร้ายทำได้คือทุกอย่างที่ JavaScript ในหน้าเราทำได้
  4. ถ้าไม่อัปเดต แอปจะใช้ไม่ได้ในเบราว์เซอร์ภายนอก
  5. วิธีอัปเดตขึ้นกับว่าแอปโหลด SDK แบบไหน
  6. 2.31.2 เปลี่ยนวิธีจัดการ ? ใน query parameter

LINE ค่อย ๆ ประกาศเรื่องนี้ตลอดเดือนตุลาคม

ใครที่ติดตามข่าวของ LIFF อาจเห็นเรื่องนี้เป็นสามสี่ประกาศแยกกัน

  • 30 ก.ย. 2569 LINE ออก LIFF 2.31.1 บอกแค่ว่าแก้บั๊กที่อาจมีผลด้านความปลอดภัย เกิดเมื่อเปิดแอปด้วย URL ที่มี query parameter ที่ปลอมขึ้นในเบราว์เซอร์ภายนอก และประกาศให้ 2.20.0 ถึง 2.31.0 เป็นเวอร์ชันที่ไม่แนะนำให้ใช้แล้ว
  • 7 ต.ค. ออก LIFF 2.31.2 ที่เปลี่ยนวิธีจัดการเครื่องหมาย ? ใน query parameter (อธิบายท้ายโพสต์)
  • 20 ต.ค. ลงประกาศฉบับเต็ม พร้อมเลข CVE และกำหนดวันจำกัดการใช้เวอร์ชันเก่า
  • 22 ต.ค. เพิ่มเติมว่าการเปิดผ่านเบราว์เซอร์ใน LINE เองก็เข้าข่ายด้วยในบางกรณี

เวอร์ชันที่มีช่องโหว่เริ่มตั้งแต่ 2.20.0 ซึ่งออกบน npm เมื่อ พ.ค. 2565 แอป LIFF ที่ทำในช่วงสี่ปีที่ผ่านมาแล้วไม่ได้อัปเดต SDK เลย จึงน่าจะอยู่ในช่วงนี้ ตอนเขียนโพสต์นี้เวอร์ชันล่าสุดบน npm คือ 2.32.0

ช่องโหว่ทำงานเมื่อเปิดแอปนอก LIFF browser

แอป LIFF หนึ่งตัวเปิดได้หลายทาง และช่องโหว่นี้ขึ้นกับว่าเปิดทางไหน ลองนึกถึงแอปเช็กยอดของร้านที่มีหน้าเว็บอยู่ที่ https://shop.example.com/liff

  • เปิดจาก LIFF URL ในแอป LINE คือลิงก์แบบ https://liff.line.me/{liffId} ที่เรามักผูกไว้กับ rich menu ลิงก์นี้เปิดแอปใน LIFF browser ซึ่งเป็นหน้าต่างที่ LINE เตรียมไว้ให้แอป LIFF โดยเฉพาะ ประกาศไม่ได้บอกว่าทางนี้เข้าข่าย
  • เปิดในเบราว์เซอร์ภายนอก อย่าง Safari หรือ Chrome เช่นลูกค้ากดลิงก์จากอีเมล หรือแอปที่เปิด withLoginOnExternalBrowser ให้ login นอก LINE ได้ ทางนี้เข้าข่าย
  • เปิด endpoint URL ตรง ๆ ในเบราว์เซอร์ของ LINE เช่นส่งลิงก์ https://shop.example.com/liff ในแชตแล้วลูกค้ากด LINE จะเปิดในเบราว์เซอร์ทั่วไปของแอป LINE ไม่ใช่ LIFF browser ประกาศวันที่ 22 ต.ค. บอกว่า LIFF นับกรณีนี้เป็นเบราว์เซอร์ภายนอกด้วย จึงเข้าข่ายเหมือนกัน

แปลว่าแม้ร้านจะตั้งใจให้ลูกค้าเข้าจาก rich menu อย่างเดียว คนร้ายก็ยังส่งลิงก์ที่ชี้มาที่โดเมนของร้านพร้อม query parameter ที่ปลอมขึ้นให้ลูกค้ากดได้อยู่ดี

สิ่งที่คนร้ายทำได้คือทุกอย่างที่ JavaScript ในหน้าเราทำได้

XSS (cross-site scripting) คือช่องโหว่ที่ทำให้โค้ด JavaScript ของคนอื่นไปรันบนโดเมนของเรา เบราว์เซอร์แยกไม่ออกว่าโค้ดนั้นไม่ใช่ของเรา จึงให้สิทธิ์เท่ากับโค้ดของแอปทุกอย่าง advisory บน GitHub ไล่ผลกระทบไว้ดังนี้

  • อ่าน access token หรือข้อมูลอื่นที่ JavaScript ในหน้านั้นเข้าถึงได้
  • อ่าน localStorage และ cookie ที่ไม่ได้ตั้ง HttpOnly
  • ทำอะไรก็ได้ในนามผู้ใช้ภายใต้สิทธิ์ที่แอปให้คนนั้น
  • เปลี่ยนสิ่งที่แสดงบนหน้าจอ หรือพาผู้ใช้ไปหน้า phishing

ถ้าแอปของเราทำ login แบบที่อธิบายไว้ในโพสต์ Login ผ่าน LINE LIFF ใน Laravel คือส่ง access token ไปให้ server ตรวจกับ LINE ช่องโหว่นี้ก็ข้ามขั้นนั้นได้ เพราะ token ที่คนร้ายขโมยไปเป็น token จริงที่ LINE ออกให้แอปเรา server ตรวจแล้วก็ผ่าน ส่วน session cookie ของ Laravel ตั้ง http_only ไว้เป็นค่าเริ่มต้น สคริปต์จึงอ่านค่าตรง ๆ ไม่ได้ แต่ยังส่ง request จากหน้านั้นในนามลูกค้าได้อยู่ การตรวจฝั่ง server จึงกันเรื่องนี้ไม่ได้ ต้องอัปเดต SDK

LINE บอกว่าตรวจสอบแล้วยังไม่พบการโจมตีที่สำเร็จหรือข้อมูลรั่วจริง และ GitHub ให้ระดับความรุนแรงไว้ที่ medium แต่ข้อมูลว่ามีช่องโหว่เปิดเผยแล้ว LINE จึงยังขอให้รีบอัปเดต รายละเอียดทางเทคนิคว่าช่องโหว่อยู่ตรงไหน LINE ยังเก็บไว้ก่อนเพื่อให้เวลาเจ้าของแอปอัปเดต

ถ้าไม่อัปเดต แอปจะใช้ไม่ได้ในเบราว์เซอร์ภายนอก

ราววันอังคารที่ 24 พ.ย. 2569 LINE จะจำกัดการใช้ SDK 2.20.0 ถึง 2.31.0 และอาจเลื่อนให้เร็วขึ้นโดยไม่แจ้งล่วงหน้า หลังจากนั้นถ้าเปิดแอปที่ยังใช้เวอร์ชันเก่าในเบราว์เซอร์ภายนอก LINE Login และฟีเจอร์อื่นของ LIFF อาจใช้ไม่ได้ จนแอปทำงานไม่ปกติ

LINE เองก็บอกว่าการจำกัดนี้ไม่ได้ปิดความเสี่ยงได้ทั้งหมด จึงไม่ควรรอให้ถึงวันนั้น

วิธีอัปเดตขึ้นกับว่าแอปโหลด SDK แบบไหน

เปิดหน้า HTML ของแอป LIFF แล้วดูว่าโหลด SDK แบบไหน ถ้าไม่แน่ใจ เปิดแอปแล้วพิมพ์ liff.getVersion() ใน console ของเบราว์เซอร์ จะเห็นเวอร์ชันที่ใช้อยู่จริง

  • CDN edge (https://static.line-scdn.net/liff/edge/2/sdk.js) ได้เวอร์ชันใหม่ไปแล้วอัตโนมัติ ไม่ต้องทำอะไร แต่ควรเช็ก liff.getVersion() อีกทีว่าได้เวอร์ชันใหม่จริง
  • CDN แบบล็อกเวอร์ชัน (.../liff/edge/versions/2.xx.x/sdk.js) เปลี่ยนเลขเวอร์ชันใน URL
  • npm อัปเดต @line/liff ให้ lockfile เปลี่ยนตาม แล้ว build และ deploy ใหม่ ถ้าแค่แก้ package.json แต่ไม่ได้ build ไฟล์ที่ผู้ใช้ได้ก็ยังเป็นเวอร์ชันเก่า
  • ก๊อปไฟล์ SDK มาเก็บไว้เอง ต้องเปลี่ยนไฟล์นั้นเป็นเวอร์ชันใหม่
<script charset="utf-8" src="https://static.line-scdn.net/liff/edge/versions/2.31.2/sdk.js"></script>

ถ้ามี cache อื่นที่เก็บ SDK หรือ bundle ตัวเก่าไว้ เช่น service worker หรือ CDN หน้าเว็บของเราเอง ให้ล้างตอน deploy ด้วย ไม่อย่างนั้นผู้ใช้บางคนจะยังได้ไฟล์เก่าอยู่

2.31.2 เปลี่ยนวิธีจัดการ ? ใน query parameter

ประกาศของ LINE แนะนำ 2.31.2 ซึ่งเป็นเวอร์ชันล่าสุดตอนนั้น เวอร์ชันนี้มีการเปลี่ยนแปลงหนึ่งที่ควรทดสอบก่อนขึ้นจริง

เวลาเปิด LIFF URL ใน LIFF browser แล้วค่าของ query parameter มีเครื่องหมาย ? อยู่ด้วย เดิม SDK จะเปลี่ยน ? เป็น & ตอนส่งต่อไปที่ endpoint ของเรา ตั้งแต่ 2.31.2 จะคง ? ไว้ตามเดิม เช่นเปิด https://liff.line.me/{liffId}/?key=foo?bar แอปจะได้ key=foo?bar แทน key=foo&bar ถ้าค่าใน URL เป็น %3F ที่ encode ไว้แล้ว ผลจะต่างไปตามว่าเปิดจากที่ไหน บน iOS ที่เปิดจากนอกแอป LINE จะเปลี่ยน ส่วน Android และ iOS ที่เปิดจากในแอป LINE เหมือนเดิม

แอปที่เก็บ URL ไว้ใน query parameter เช่น return_url ที่จำหน้าก่อนหน้าไว้ มีโอกาสโดนเรื่องนี้มากที่สุด ลองกดผ่านเส้นทางนั้นหลังอัปเดตสักรอบ ถ้าแอปไม่มีค่าแบบนี้ ก็ขึ้น 2.31.2 ได้เลย

ถ้าระบบของร้านมีแอปใน LINE ที่คนอื่นทำให้ ลองถามผู้พัฒนาว่าแอปใช้ LIFF SDK เวอร์ชันไหน และจะอัปเดตเสร็จก่อนวันที่ 24 พ.ย. หรือเปล่า รายละเอียดทั้งหมดอ่านต่อได้ที่ประกาศของ LINE ครับ

อ่านต่อ

ถูกอ้างถึงใน

ล่าสุด

ดูทั้งหมด →