- ซื้อ กล้อง Tapo มาเพื่อสังเกตสุนัขในบ้าน แต่สุดท้ายกลับกลายเป็นการอธิบายย้อนกลับถึง หลักการทำงานของอุปกรณ์และแอปของ TP-Link โดยไม่คาดคิด
- ใช้เทคนิคหลากหลาย เช่น MITM, การ decompile APK, การสร้างสคริปต์ถอดรหัส เพื่อวิเคราะห์ กระบวนการ onboarding และโครงสร้างการสื่อสารของ API ที่เข้ารหัส
- จากการค้นพบ รหัสผ่านผู้ดูแลระบบเริ่มต้น และกระบวนการ derive session key จึงสามารถถอดรหัสข้อความที่เข้ารหัสได้ และพบปัญหาการซิงก์ที่ไม่น่าเชื่อถือระหว่างอุปกรณ์กับบัญชีคลาวด์
- วิเคราะห์ ลำดับขั้น onboarding ทั้งหมด แล้วทำขั้นตอนเรียกใช้ API สำคัญ การสร้างบัญชี การเปลี่ยนรหัสผ่าน และการเชื่อมต่อ Wi-Fi ให้เป็นอัตโนมัติด้วยสคริปต์ Bash
- ชี้ให้เห็น ช่องโหว่ของการออกแบบความปลอดภัยในเฟิร์มแวร์ Tapo, การทำ encryption ที่ไม่ประณีตนัก, การซิงก์บัญชีที่ไม่สม่ำเสมอ ซึ่งเป็นลักษณะที่พบได้ในอุปกรณ์ IoT ราคาประหยัด
ภาพรวมของโปรเจกต์
- ผู้เขียนซื้อ กล้อง Tapo ราคาประหยัด มาใช้เพื่อดูสุนัขภายในบ้าน
- ระหว่างใช้งาน ด้วย ความยุ่งยากในการตั้งค่า และข้อมูลออนไลน์ที่มีอยู่น้อย จึงเกิดแรงจูงใจให้ขุดลึกถึงหลักการทำงานของผลิตภัณฑ์
- เมื่อเจอปัญหาที่ไม่คาดคิดกับการเชื่อมต่อ frigate และการเปิดใช้งาน 2way audio จึงเริ่มสนใจวิธี onboarding โดยตรง ที่ไม่ต้องพึ่งการเชื่อมต่อคลาวด์
การวิเคราะห์โครงสร้าง onboarding และการยืนยันตัวตน
- เพื่อวิเคราะห์ขั้นตอนการเชื่อมต่อของกล้อง Tapo ผู้เขียนใช้ MITM proxy และเครื่องมือ dynamic hooking อย่าง frida เพื่อดักทราฟฟิกระหว่างแอปกับกล้อง
- แอปเวอร์ชันใหม่มักมีความสามารถต้านการหลบเลี่ยง เช่น การไม่ใช้พร็อกซีและ certificate pinning ดังนั้นวิธีที่ใช้เครื่องมือแบบ dynamic จึงได้ผล
- หลังตั้งค่าสภาพแวดล้อมสำหรับ bypass เหล่านี้แล้ว ก็สามารถยืนยันขั้นตอน การล็อกอินด้วยบัญชีผู้ดูแลระบบเริ่มต้น ใน flow การ onboarding ของกล้องได้อย่างชัดเจน
- พบว่า API สำหรับล็อกอินเริ่มต้น ทำงานด้วย รหัสผ่านเริ่มต้น เฉพาะของอุปกรณ์ ซึ่งแยกจากรหัสผ่านของบัญชีคลาวด์
โครงสร้างการเข้ารหัสและการค้นหารหัสผ่านเริ่มต้น
- จากการ decompile APK (ใช้ JADX) และวิเคราะห์โค้ด ทำให้ได้ รหัสผ่านเริ่มต้น ของบัญชี
admin(TPL075526460603) - แม้จะเปลี่ยนรหัสผ่านคลาวด์แล้ว แต่กล้องที่เชื่อมต่ออยู่ก่อนหน้านี้กลับไม่รับรู้การเปลี่ยนแปลง จึงยืนยันได้ว่าการ ซิงก์รหัสผ่านระหว่างแอปกับกล้องไม่แม่นยำ
- เมื่อทราบรหัสผ่านเริ่มต้นแล้ว ผู้เขียนจึง implement logic สำหรับ derive session key (
lsk,ivb) เพื่อให้สามารถถอดรหัส ข้อความ API ที่เข้ารหัส ได้แบบเรียลไทม์
การทำสคริปต์ mitmproxy และการวิเคราะห์ API
- อ้างอิงจากโปรเจกต์โอเพนซอร์ส PyTapo แล้ววิเคราะห์ ลำดับ API ของขั้นตอน onboarding ของ Tapo จริงอย่างละเอียด
- ผ่านสคริปต์
tapo_decrypt_pretty.pyสามารถทำสิ่งต่อไปนี้ได้- ตรวจจับ login handshake
- ดึง session key
- ถอดรหัส API ที่เข้ารหัส พร้อมแสดงผลให้อ่านง่ายและบันทึกเป็น JSON
- จากรายการเรียกใช้ API ทั้งหมดใน onboarding ได้คัดเฉพาะขั้นตอนสำคัญที่มีความหมายมาสร้างเป็น workflow อัตโนมัติ
- ดึงรายการ Wi-Fi (
scanApList) - เปิดใช้งานบัญชี RTSP/ONVIF
- เปลี่ยนรหัสผ่านผู้ดูแลระบบ
- เชื่อมต่อ Wi-Fi
- ดึงรายการ Wi-Fi (
การทำงานอัตโนมัติและผลลัพธ์
- จัดทำสคริปต์ Bash (
tapo_onboard.sh) ให้รันขั้นตอน onboarding ทั้งหมดข้างต้น โดยอัตโนมัติ- ล็อกอินด้วย admin เริ่มต้น
- เลือกและเชื่อมต่อ Wi-Fi
- ลบโลโก้ออกจากฟีดกล้อง
- อนุญาตการใช้งาน RTSP/ONVIF
- รีเซ็ตรหัสผ่านผู้ดูแลระบบ
- จากโครงสร้างเฟิร์มแวร์ของกล้อง พบลักษณะและช่องโหว่ต่อไปนี้
- บาง API ใช้ แฮช SHA-256 แต่บางส่วนยังคงใช้วิธีเข้ารหัสแบบเก่าอย่าง MD5
- มี public key อยู่ 2 ชุด และไม่ชัดเจนว่าควรใช้คีย์ใดในสถานการณ์ไหน
- การ ซิงก์รหัสผ่าน ระหว่างแอปกับอุปกรณ์ไม่มีเสถียรภาพอย่างมาก
บทสรุปและความเห็น
- โครงสร้างความปลอดภัยของเฟิร์มแวร์และ API ของกล้อง Tapo ให้ความรู้สึกว่าเป็น การออกแบบแบบแก้ขัดและยังไม่ประณีต
- เป็นประสบการณ์ที่ทำให้ได้สัมผัสทางอ้อมถึง ช่องโหว่ด้านความปลอดภัย และความไม่สมบูรณ์ของระบบ onboarding ในอุปกรณ์ IoT ราคาประหยัด
- ส่วนเป้าหมายสูงสุดของโปรเจกต์อย่างการเช็กดูสุนัขนั้นสำเร็จ โดยพบว่าสุนัขมักนอนอยู่บนโซฟาหรือไม่ก็บนเตียง
2 ความคิดเห็น
CVE-2022-37255 ได้ 7.5 คะแนนนะ
ความคิดเห็นบน Hacker News
รู้สึกทึ่งที่มีคนใช้สคริปต์ Frida ของฉัน สคริปต์นั้นดูได้ที่นี่ และก็ดีใจที่มันดูเหมือนจะใช้งานได้ดีในสภาพแวดล้อมจริง ถ้ามีส่วนไหนที่เพิ่มหรือแก้ไขไปก็อยากฟัง
เผื่อใครสนใจ ถ้าจะใช้เสียงสองทางใน frigate ต้องใช้การตั้งค่า go2rtc แบบ
tapo://กับสตรีมหลักแทนrtsp://ทั่วไป เพราะ TP-Link ให้เสียงสองทางผ่าน API ของตัวเองเท่านั้น แต่พอตั้งแบบนี้ ONVIF (การควบคุมแพน/ทิลต์กล้องผ่านเครื่องมือโอเพนซอร์ส) จะใช้ไม่ได้ ทำให้ค่อนข้างยุ่ง ถ้าจะใช้ทั้งสองอย่างพร้อมกันต้องทำเวิร์กโฟลว์แบบหนักหน่วงคือ หยุดการอ่านสตรีมtapo://→ รันไคลเอนต์ onvif/ปรับแพน·ทิลต์ → ปิด onvif → รีสตาร์ตtapo://คิดว่าความปลอดภัยของ IoT โดยรวมเละเทะมาก และสิ่งที่น่ากังวลเป็นพิเศษคือเราเตอร์สำหรับผู้บริโภคเป็นกล่องดำที่ตรวจสอบไม่ได้แต่กลับจัดการทราฟฟิกทั้งหมดของเครือข่าย คนส่วนใหญ่ไม่รู้ด้วยซ้ำว่าเฟิร์มแวร์เราเตอร์ของตัวเองไม่ได้อัปเดตมาหลายปีและมีช่องโหว่ที่รู้กันอยู่แล้ว ฉันคิดว่าโมเดลความเชื่อถือของซัพพลายเชนสำหรับฮาร์ดแวร์เครือข่ายมันพังหมดแล้ว
รู้สึกว่าบล็อกโพสต์นี้เขียนได้ดีมาก ทุกวันนี้งานเขียนสไตล์นี้หลายชิ้นมักสร้างโดย LLM และอ่านแล้วฝืด แต่บทความนี้สร้างสมดุลได้ดีระหว่างความเป็นเทคนิคกับความอ่านสบาย ซึ่งน่าประทับใจ (แม้จะรู้ว่าภาพปกสร้างโดย AI แต่ฉันคิดว่านั่นไม่เกี่ยวกับแก่นของบทความ)
สงสัยว่าเราจะยังใช้เครื่องมืออย่าง Frida หรือ mitmproxy กับแอป Android ต่อไปได้หรือไม่ และอยากรู้ว่าปีหน้าถ้าข้อกำหนดเรื่องการเซ็นลายเซ็นมีผลแล้วจะเกิดอะไรขึ้น
อ้างอิงที่เกี่ยวข้องอีกอย่างคือ The Tapo C200 Research Project และ PyTapo: Python library for Tapo cameras
อีกแหล่งข้อมูลที่เกี่ยวข้องคือ (การถอดรหัสเฟิร์มแวร์ TP-Link และการวิเคราะห์บูตโหลดเดอร์ของกล้องคลาวด์ C210 V2) อยู่ที่นี่
เดาว่าสาเหตุที่สุนัขของ OP ย้ายจากบนเตียงลงไปนอนที่พื้น อาจเป็นเพราะหม้อน้ำทำความร้อนเปิดอยู่หรือเปล่า น่าจะต้องมีข้อมูลจากเซ็นเซอร์เพิ่มเติม
รู้สึกว่าเดี๋ยวนี้การเจอรหัสผ่านแอดมินแบบฮาร์ดโค้ดไม่ใช่เรื่องน่าตกใจอะไรแล้ว
อยากได้แหล่งอ้างอิงที่รวบรวมรุ่นของกล้อง tapo ที่รองรับ rtsp โดย c210 ใช้งานได้โอเคพอสมควร (แต่จับภาพผ่านคลาวด์ไม่ได้) และตอนนี้ใช้งานร่วมกับ frigate อยู่ วันนี้เพิ่งซื้อ c402 (รุ่นใช้นอกอาคาร) มา แต่เสียดายที่ใน advanced settings ไม่มี camera account จุดเด่นคือราคาถูก แต่รู้สึกว่าฟังก์ชันไม่ค่อยเป็นมาตรฐานเดียวกัน ถ้ามีกล้องนอกอาคารดี ๆ ราคาประหยัด รองรับสตรีม rtsp และติดแผงโซลาร์ได้ด้วย ก็อยากได้คำแนะนำ
rtsp://ก็อาจยังใช้แหล่งสตรีมtapo://ของ go2rtc ได้ ฉันทิ้งการตั้งค่า frigate ของตัวเองไว้เป็นตัวอย่างที่นี่