หมวดหมู่ OWASP: MASVS-PLATFORM: การโต้ตอบระหว่างแพลตฟอร์ม
ภาพรวม
บริดจ์แบบเนทีฟหรือบางครั้งเรียกว่าบริดจ์ JavaScript เป็นกลไกที่
อำนวยความสะดวกในการสื่อสารระหว่าง WebView และโค้ด Android แบบเนทีฟ
โดยใช้เมธอด addJavascriptInterface
ซึ่งช่วยให้การสื่อสารแบบ 2 ทางระหว่างโค้ด JavaScript ที่ทำงานใน WebView กับโค้ด Java ของแอปพลิเคชัน Android เมธอด addJavascriptInterface
จะแสดงออบเจ็กต์ Java ต่อเฟรมทั้งหมดของ WebView และเฟรมใดก็ตามจะเข้าถึงชื่อออบเจ็กต์และเรียกใช้เมธอดในออบเจ็กต์นั้นได้ อย่างไรก็ตาม แอปพลิเคชันจะไม่มีกลไกในการ
ยืนยันต้นทางของเฟรมการเรียกใช้ภายใน WebView ซึ่งช่วยเพิ่มความปลอดภัย
ความกังวลเนื่องจากความน่าเชื่อถือของเนื้อหายังคงไม่ชัดเจน
นอกจากนี้ คุณยังใช้บริดจ์เนทีฟกับช่องทางข้อความ HTML ได้โดยใช้ WebViewCompat.postWebMessage
หรือ WebMessagePort.postMessage
ของ Android เพื่อสื่อสารกับ 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 สามารถใช้ภายในแอปพลิเคชันเพื่อแสดงเนื้อหาเว็บเป็นส่วนหนึ่งของเลย์เอาต์กิจกรรม การใช้บริดจ์แบบเนทีฟภายใน WebView โดยใช้เมธอด addJavascriptInterface
อาจทำให้เกิดปัญหาด้านความปลอดภัย เช่น สคริปต์ข้ามเว็บไซต์ (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 ในการรักษาความปลอดภัยเครือข่าย
config ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบของ 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