WebView – บริดจ์ดั้งเดิม

หมวดหมู่ 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() ให้อนุญาตเฉพาะข้อความจากโดเมนที่เชื่อถือโดยหลีกเลี่ยงการใช้ * เป็นต้นทางเป้าหมาย และระบุโดเมนที่ส่งที่คาดไว้อย่างชัดเจนแทน


แหล่งข้อมูล