Lỗ hổng bảo mật trong WebView ở các ứng dụng Android
1. WebView là gì?
Có những lần chúng ta bấm vào một đường link trên Facebook, Messenger,... sau đó trang web là đích đến của đường link đó được hiển thị cho chúng ta xem qua một giao diện ở ngay trên ứng dụng Facebook, Messenger,... Chúng ta cũng có thể tương tác với trang web đó y như khi sử dụng trình duyệt. Đó chính là nhờ WebView.
WebView là một tính năng cho phép lập trình viên có thể "nhúng" một trang web, hoặc một ứng dụng web vào trong ứng dụng của mình. WebView không có nhiều tính năng của một trình duyệt như thanh địa chỉ, dấu trang, lịch sử,... Mặc định thì WebView chỉ hiển thị giao diện web cho người dùng mà thôi.
Có những ứng dụng thậm chí sử dụng WebView là chính. Trường hợp này họ đã có sẵn ứng dụng web rồi, do đó chỉ cần mở webview trên ứng dụng Android để người dùng sử dụng như trên trình duyệt là được. Với cách này thì doanh nghiệp có thể tiết kiệm tối đa chi phí sản xuất và nâng cấp ứng dụng.
2. Lỗ hổng bảo mật trong WebView
WebView có thể xuất hiện nhiều lỗ hổng bảo mật nguy hiểm, phần lớn xuất hiện do cấu hình WebView thiếu an toàn. Những cấu hình của WebView giống như một con dao hai lưỡi vậy. Một mặt chúng mở khoá các tính năng giúp WebView có thể nâng cao trải nghiệm người dùng, mặt khác lại có thể khiến ứng dụng và dữ liệu bị tấn công bởi các tác nhân xáu.
Sau đây sẽ là danh sách những cấu hình cần chú ý, cân nhắc kỹ trước khi sử dụng.
2.1. Cấu hình setJavaScriptEnabled(true)
Đây là cấu hình cho phép WebView có thể chạy các mã JavaScript, mặc định cấu hình này được đặt là false. Nếu ứng dụng web cần sử dụng JavaScript để hoạt động thì bắt buộc phải đặt cho cấu hình này là true. Khi được đặt là true, WebView có thể bị tấn công bằng các kiểu tấn công chèn mã JavaScript (XSS). Cũng có trường hợp người dùng mở trúng một đường link dẫn tới trang web có sẵn các đoạn mã JavaScript độc hại.
2.2. Cấu hình setWebChromeClient
Như đã đề cập đến ở phần 1 thì WebView chỉ là một chức năng để hiển thị giao diện web, và nó không có nhiều tính năng của một trình duyệt. Do đó JavaScript cũng không thể chạy được một cách hoàn chỉnh. Nếu chỉ cho phép WebView chạy JavaScript thì một số hàm phục vụ tấn công XSS như alert() sẽ không thể hoạt động được.
Để WebView có thể chạy JavaScript tốt hơn thì có thể cấu hình cho nó có khả năng tương tác với JavaScript như trình duyệt. Đoạn code Java dưới đây sẽ cho WebView có cấu hình tương tự Chrome, và có thể chạy hàm alert():
webView.setWebChromeClient(new WebChromeClient() {
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result){
return super.onJsAlert(view, url, message, result);
}
});
Như vậy hàm alert đã có thể thực thi như trên các trình duyệt.
2.3. Cấu hình truy cập tệp tin trên thiết bị
Webview của Android có một số cấu hình cho phép webview truy cập và tải được các tệp tin trên thiết bị:
- setAllowContentAccess: cho phép webview tải các nội dung được chia sẻ bởi ContentProvider. Mặc định được đặt là true.
- setAllowFileAccess: cho phép WebView được quyền tải các tệp tin trong thiết bị. Mặc định được đặt là true với Android 10 (API level 29) trở xuống.
- setAllowFileAccessFromFileURLs: cho phép WebView được quyền tải tệp tin trong thiết bị qua scheme file://
- setAllowUniversalAccessFromFileURLs: cho phép WebView được quyền tải tệp tin từ mọi nguồn qua scheme file://
Ngoài ra, chỉ cấu hình truy cập tệp tin cho WebView là chưa đủ. Để WebView có thể đọc tệp tin được thì ứng dụng cũng phải được cấp quyền đọc dữ liêu trong vùng nhớ ngoài bằng cách yêu cầu quyền android.permission.READ_EXTERNAL_STORAGE trong tệp tin AndroidManifest.xml
Một lưu ý rằng, từ Android 7 trở lên thì việc truy cập tệp tin bằng Webview càng trở nên phức tạp hơn, hay còn có nghĩa là an toàn hơn. Đối với các phiên bản hệ điều hành này, để có tải tệp tin qua Webview thì cần có sự hỗ trợ của File Provider. Nếu tệp tin không được tải qua File Provider thì sẽ xuất hiện lỗi net::ERR_ACCESS_DENIED
Ở ảnh trên, mình đã mở tệp tin trong bộ nhớ của thiết bị bằng cách yêu cầu WebView truy cập đường dẫn file:///storage/emulated/0/Download/google-services.json
. Dù đã cấu hình Webview đầy đủ và cấp quyền đầy đủ, nhưng vì chạy trên Android 7 nên vẫn không thể đọc được tệp tin.
2.4. Cấu hình addJavascriptInterface
Cấu hình này cho phép các đoạn mã JavaScript chạy trong Webview có thể kết nối với mã nguồn của ứng dụng Android. Việc này được thực hiện bằng cách cho phép mã JavaScript được phép gọi các hàm Java. Đây là một tính năng hữu dụng trong việc gia tăng sự liên kết giữa nội dung trong Webview và ứng dụng.Với addJavascriptInterface, Webview không còn chỉ đóng vai trò hiển thị các nội dung trên web, mà còn có thể trao đổi dữ liệu và phối hợp nhịp nhàng với các tính năng của ứng dụng Android.
Đoạn mã nguồn cấu hình JavascriptInterface cho Webview:
// Assuming webView is your WebView instance
WebView webView = findViewById(R.id.webView);
// Create a JavaScript interface object
JavaScriptInterface jsInterface = new JavaScriptInterface(this);
// Expose the JavaScript interface object to the WebView
webView.addJavascriptInterface(jsInterface, "Android");
Đoạn mã nguồn tạo JavascriptInterface:
public class JavaScriptInterface {
@JavascriptInterface
public int addNumbers(int a, int b) {
return a + b;
}
}
Đoạn mã JavaScript chạy mã nguồn Java qua JavascriptInterface:
<script type="text/javascript">
// Call the addNumbers() method and alert the result
var result = Android.addNumbers(5, 10);
alert("Result of addition: " + result);
</script>
Một tính năng rất tiện lợi đúng không? Thế nhưng khi sử dụng thì chúng ta cần chú ý, tránh tạo JavascriptInterface cho các phương thức nhạy cảm, chứa dữ liệu quan trọng. Ứng dụng Grab trên Android và iOS từng có một lỗ hổng bảo mật được chấm điểm HIGH 7.1 chính vì lí do trên. Chi tiết về lỗ hổng bảo mật có thể đọc tại: https://hackerone.com/reports/401793
Và đó là 4 cấu hình của Webview mà chúng ta cần chú ý khi sử dụng để tránh tạo ra những lỗ hổng bảo mật. 4 cấu hình trên cũng được đề cập đến trong tài liệu Mobile Security Testing Guide của OWASP.
All rights reserved