หมวดหมู่ OWASP: MASVS-PLATFORM: การโต้ตอบกับแพลตฟอร์ม
ภาพรวม
Native Bridge หรือที่บางครั้งเรียกว่า JavaScript Bridge เป็นกลไกที่ช่วยให้การสื่อสารระหว่าง WebView กับโค้ด Android ดั้งเดิมเป็นไปได้โดยใช้เมธอด addJavascriptInterface ซึ่งจะช่วยให้มีการสื่อสารแบบ 2 ทาง
ระหว่างโค้ด JavaScript ที่ทํางานใน WebView กับโค้ด Java ของแอปพลิเคชัน Android
เมธอด addJavascriptInterface จะแสดงออบเจ็กต์ Java
ต่อเฟรมทั้งหมดของ WebView และเฟรมใดก็ตามจะเข้าถึงชื่อออบเจ็กต์
และเรียกใช้เมธอดในออบเจ็กต์นั้นได้ อย่างไรก็ตาม ไม่มีกลไกใดที่แอปพลิเคชันจะใช้
ยืนยันแหล่งที่มาของเฟรมที่เรียกใช้ภายใน WebView ซึ่งทำให้เกิดความกังวลด้านความปลอดภัย
เนื่องจากความน่าเชื่อถือของเนื้อหายังคงไม่แน่นอน
คุณยังใช้บริดจ์เนทีฟกับช่องข้อความ HTML ได้โดยใช้ WebViewCompat.postWebMessage ของ Android หรือ WebMessagePort.postMessage เพื่อสื่อสารกับ JavaScript Window.postMessage WebViewCompat.postWebMessage และ
WebMessagePort.postMessage สามารถยอมรับข้อความ JavaScript ที่ส่งผ่าน
Window.postMessage ซึ่งจะดำเนินการภายใน WebView
ความเสี่ยงหลายประการที่เกี่ยวข้องกับบริดจ์ดั้งเดิมมีดังนี้
- บริดจ์ที่ใช้ JavascriptInterface
- เมธอด
addJavascriptInterfaceจะแทรกออบเจ็กต์ Java ที่ระบุลงในทุกเฟรมของ WebView รวมถึง iframe ซึ่งหมายความว่าเมธอดนี้อาจถูกโจมตีโดยบุคคลที่สามที่เป็นอันตรายซึ่งแทรกเฟรมลงในเว็บไซต์ที่ถูกต้อง แอปพลิเคชันที่กำหนดเป้าหมายเป็น API ระดับ 16 หรือต่ำกว่ามีความเสี่ยงที่จะถูก โจมตีเป็นพิเศษ เนื่องจากสามารถใช้วิธีนี้เพื่ออนุญาตให้ JavaScript ควบคุมแอปพลิเคชันโฮสต์ได้ - การแสดงเนื้อหาที่ผู้ใช้ระบุซึ่งไม่น่าเชื่อถือใน WebView ที่เปิดใช้บริดจ์เนทีฟ ทำให้เกิดการโจมตีแบบ Cross-site Scripting (XSS)
- เมธอด
- บริดจ์ที่ใช้ MessageChannel
- การไม่มีการตรวจสอบต้นทางในปลายทางการรับส่งข้อความหมายความว่าระบบจะยอมรับข้อความจากผู้ส่งทุกราย รวมถึงข้อความที่มีโค้ดที่เป็นอันตราย
- อาจมีการเปิดเผย Java ให้กับ JavaScript ที่กำหนดเองโดยไม่ตั้งใจ
ผลกระทบ
ผู้ไม่ประสงค์ดีอาจใช้ประโยชน์จากเมธอด addJavascriptInterface, postWebMessage และ postMessage เพื่อเข้าถึง ดัดแปลง หรือแทรกโค้ดที่ตนควบคุม
ลงใน WebView ซึ่งอาจส่งผลให้ผู้ใช้ถูกเปลี่ยนเส้นทางไปยังเว็บไซต์ที่เป็นอันตราย โหลดเนื้อหาที่เป็นอันตราย หรือมีโค้ดที่เป็นอันตรายทำงานในอุปกรณ์ ซึ่งสามารถดึงข้อมูลที่ละเอียดอ่อนหรือการโจมตีเพื่อยกระดับสิทธิ์ได้
ความเสี่ยง: ความเสี่ยงของ addJavascriptInterface
WebView จะใช้ฟังก์ชันการทำงานพื้นฐานของเบราว์เซอร์ เช่น การแสดงผลหน้าเว็บ
การนำทาง และการเรียกใช้ JavaScript WebView สามารถใช้ภายในแอปพลิเคชัน
เพื่อแสดงเนื้อหาเว็บเป็นส่วนหนึ่งของเลย์เอาต์กิจกรรม การติดตั้งใช้งาน Native Bridge ภายใน WebView โดยใช้เมธอด addJavascriptInterface อาจทำให้เกิดปัญหาด้านความปลอดภัย เช่น Cross-Site Scripting (XSS) หรืออนุญาตให้ผู้โจมตีโหลดเนื้อหาที่ไม่น่าเชื่อถือผ่านการแทรกอินเทอร์เฟซและจัดการแอปพลิเคชันโฮสต์ในลักษณะที่ไม่พึงประสงค์ ซึ่งจะเรียกใช้โค้ด Java ด้วยสิทธิ์ของแอปพลิเคชันโฮสต์
การลดปัญหา
ปิดใช้ JavaScript
ในสถานการณ์ที่ WebView ไม่ต้องใช้ JavaScript อย่าเรียกใช้ setJavaScriptEnabled ภายใน WebSettings (เช่น ขณะแสดงเนื้อหา HTML แบบคงที่) โดยค่าเริ่มต้นแล้ว ระบบจะปิดใช้การทำงานของ JavaScript ใน WebView
นำอินเทอร์เฟซ JavaScript ออกเมื่อโหลดเนื้อหาที่ไม่น่าเชื่อถือ
ตรวจสอบว่าได้นำออบเจ็กต์ออกจากอินเทอร์เฟซ JavaScript โดยการเรียกใช้
removeJavascriptInterface ก่อนที่ WebView จะโหลดเนื้อหาที่ไม่น่าเชื่อถือ เช่น ทำได้ในการเรียกใช้
shouldInterceptRequest
Kotlin
webView.removeJavascriptInterface("myObject")
Java
webView.removeJavascriptInterface("myObject");
โหลดเนื้อหาเว็บผ่าน HTTPS เท่านั้น
หากจำเป็นต้องโหลดเนื้อหาที่ไม่น่าเชื่อถือ ให้ตรวจสอบว่า WebView โหลดเนื้อหาเว็บผ่านการเชื่อมต่อที่เข้ารหัส (ดูหลักเกณฑ์เกี่ยวกับการสื่อสารแบบข้อความธรรมดาด้วย) ป้องกันไม่ให้มีการโหลดหน้าเว็บเริ่มต้นในการเชื่อมต่อที่ไม่ได้เข้ารหัสโดยตั้งค่า android:usesCleartextTraffic เป็น false ในไฟล์ AndroidManifest หรือไม่อนุญาตให้มีการเข้าชมแบบ HTTP ในค่ากำหนดความปลอดภัยของเครือข่าย ดูข้อมูลเพิ่มเติมในเอกสารประกอบของ usesCleartextTraffic
Xml
<application
android:usesCleartextTraffic="false">
<!-- Other application elements -->
</application>
หากต้องการให้มั่นใจว่าการเปลี่ยนเส้นทางและการเรียกดูแอปเพิ่มเติมจะไม่เกิดขึ้นกับการรับส่งข้อมูลที่ไม่ได้เข้ารหัส
ให้ตรวจสอบรูปแบบ HTTP ใน loadUrl หรือ
shouldInterceptRequest
Kotlin
fun loadSecureUrl(webView: WebView?, url: String?) {
webView?.let { wv -> // Ensure valid WebView and URL
url?.let {
try {
val uri = URI(url)
if (uri.scheme.equals("https", ignoreCase = true)) { // Enforce HTTPS scheme for security
wv.loadUrl(url)
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: $url")
}
} catch (e: Exception) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: $url")
}
}
}
}
Java
public void loadSecureUrl(WebView webView, String url) {
if (webView != null && url != null) { // Ensure valid WebView and URL
try {
URI uri = new URI(url);
String scheme = uri.getScheme();
if ("https".equalsIgnoreCase(scheme)) { // Enforce HTTPS scheme for security
webView.loadUrl(url);
} else {
// Log an error or handle the case where the URL is not secure
System.err.println("Attempted to load a non-HTTPS URL: " + url);
}
} catch (URISyntaxException e) {
// Handle exception for improper URL format
System.err.println("Invalid URL syntax: " + url);
}
}
}
ตรวจสอบเนื้อหาที่ไม่น่าเชื่อถือ
หากมีการโหลดลิงก์ภายนอกใน WebView ให้ตรวจสอบทั้งสคีมและโฮสต์ (โดเมนในรายการที่อนุญาต) โดเมนที่ไม่ได้อยู่ในรายการที่อนุญาตควรเปิดด้วยเบราว์เซอร์เริ่มต้นแทน
อย่าโหลดเนื้อหาที่ไม่น่าเชื่อถือ
หากเป็นไปได้ ให้โหลดเฉพาะ URL ที่กำหนดขอบเขตอย่างเคร่งครัดและเนื้อหาของนักพัฒนาแอป ลงใน WebView
อย่าเปิดเผยข้อมูลที่ละเอียดอ่อน
หากแอปพลิเคชันเข้าถึงข้อมูลที่ละเอียดอ่อนด้วย WebView ให้พิจารณาใช้วิธี clearCache เพื่อลบไฟล์ที่จัดเก็บไว้ในเครื่องก่อนที่จะใช้อินเทอร์เฟซ JavaScript นอกจากนี้ คุณยังใช้ส่วนหัวฝั่งเซิร์ฟเวอร์ เช่น no-store เพื่อ
ระบุว่าแอปพลิเคชันไม่ควรแคชเนื้อหาบางอย่างได้ด้วย
อย่าเปิดเผยฟังก์ชันการทำงานที่ละเอียดอ่อน
หากแอปพลิเคชันของคุณต้องใช้สิทธิ์ที่มีความละเอียดอ่อนหรือรวบรวมข้อมูลที่ละเอียดอ่อน โปรดตรวจสอบว่ามีการเรียกจากโค้ดภายในแอปพลิเคชันและมีการเปิดเผยข้อมูลอย่างชัดเจน ต่อผู้ใช้ หลีกเลี่ยงการใช้อินเทอร์เฟซ JavaScript สำหรับการดำเนินการที่ละเอียดอ่อนหรือข้อมูลผู้ใช้
กำหนดระดับ API เป้าหมาย 21 หรือสูงกว่า
วิธีที่ปลอดภัยวิธีหนึ่งในการใช้เมธอด addJavascriptInterface คือการกำหนดเป้าหมายเป็นระดับ API 21 ขึ้นไปโดยตรวจสอบว่ามีการเรียกใช้เมธอดนี้เมื่อเรียกใช้ในระดับ API 21 ขึ้นไปเท่านั้น ก่อน API 21 JavaScript สามารถใช้การสะท้อนเพื่อเข้าถึงฟิลด์สาธารณะของออบเจ็กต์ที่แทรก
ความเสี่ยง: ความเสี่ยงของ MessageChannel
การขาดการควบคุมต้นทางใน postWebMessage() และ postMessage() อาจทําให้ผู้โจมตีสกัดกั้นข้อความหรือส่งข้อความไปยังแฮนเดิลเนทีฟได้
การลดปัญหา
เมื่อตั้งค่า postWebMessage() หรือ postMessage() ให้อนุญาตเฉพาะข้อความจาก
โดเมนที่เชื่อถือได้โดยหลีกเลี่ยงการใช้ * เป็นต้นทางเป้าหมาย และให้
ระบุโดเมนที่คาดว่าจะส่งอย่างชัดเจนแทน
แหล่งข้อมูล
- แนวทางปฏิบัติแนะนำสำหรับ postMessage()
- เอกสารประกอบเกี่ยวกับ addJavascriptInterface
- เอกสารประกอบของ postMessage()
- เอกสารประกอบของ WebMessagePort.postMessage()
- เอกสารประกอบของ WebViewClient.shouldInterceptRequest
- เอกสารประกอบเกี่ยวกับคำแนะนำด้านความปลอดภัยที่เกี่ยวข้องกับ addJavascriptInterface
- เอกสารประกอบเกี่ยวกับ clearCache
- เอกสารประกอบเกี่ยวกับ removeJavascript
- การเปิดใช้ JavaScript ใน WebView