Mobil
WebView xavfsizligi: JavaScript ko'priklari, fayl ruxsatlari va logout'da tozalash
WebView ilova ichidagi brauzer, lekin brauzer himoyalarisiz. JavaScript ko'priklari, fayl ruxsati, aralash kontent va URL allowlist'ni qanday to'g'ri sozlash kerak.
· 10 daq. o'qish

Ko'p mobil ilovalarda kamida bitta WebView bor: to'lov sahifasi, yordam bo'limi, foydalanish shartlari, shaxsiy kabinetning bir qismi yoki butun ilova veb-sayt ustiga qurilgan "qobiq". WebView qulay, chunki veb-kodni qayta ishlatish mumkin. Lekin u oddiy brauzer emas: manzil qatori yo'q, foydalanuvchi qaysi saytda turganini ko'rmaydi, va eng muhimi — veb-sahifa ilovaning o'z kodiga ko'prik orqali ulanishi mumkin. Shu sababli ekspertizada WebView sozlamalari alohida tekshiriladi.
Bu maqolada WebView bilan bog'liq asosiy xavflarni, ularni o'zingiz qanday tekshirishni va Android, iOS va Flutter'da qanday yopishni ko'rib chiqamiz.
Muammo nimada
WebView'ning xavfi uchta narsadan kelib chiqadi: qanday kontent yuklanadi, bu kontentga nima ruxsat berilgan va sessiya ma'lumotlari qayerda qoladi.
1. JavaScript ko'priklari
Android'da addJavascriptInterface(), iOS'da WKScriptMessageHandler, Flutter'da JavaScript channel — bular veb-sahifadagi JavaScript'ga ilovaning native funksiyalarini chaqirish imkonini beradi. Masalan, Android.getToken() yoki window.webkit.messageHandlers.pay.postMessage(...).
Agar WebView faqat o'zingizning sahifangizni ochsa, bu boshqariladigan xavf. Lekin WebView'da begona sahifa ochilib qolsa (redirect, deep link parametri, reklama, sahifadagi XSS orqali), o'sha sahifa ham ko'prikka kira oladi va tokenni o'qiydi yoki native amalni bajaradi. Shuning uchun ko'prik bor WebView'da qaysi sahifalar ochilishi qat'iy nazorat qilinishi kerak.
2. Fayl ruxsatlari
Android WebView'da file:// sxemasiga ruxsat beruvchi sozlamalar bor: setAllowFileAccess, setAllowFileAccessFromFileURLs, setAllowUniversalAccessFromFileURLs. Oxirgi ikkisi yoqilsa, file:// orqali yuklangan sahifa boshqa lokal fayllarni yoki istalgan domenni o'qiy oladi. Bu ilovaning ichki fayllari (sessiya, kesh, ma'lumotlar bazasi) tashqariga chiqishiga olib kelishi mumkin. Zamonaviy Android versiyalarida bu sozlamalarning standart qiymati xavfsiz, lekin kodda ularni qo'lda yoqib qo'yish holatlari uchraydi.
3. Aralash kontent va sertifikat xatolari
https sahifa ichida http resurslar (skript, rasm, iframe) yuklansa, bu aralash kontent (mixed content). Ochiq kanaldagi skriptni tarmoqda o'zgartirish mumkin. Undan ham xavfliroq xato — onReceivedSslError ichida handler.proceed() chaqirish: bu har qanday noto'g'ri sertifikatni qabul qiladi va TLS'ni amalda o'chiradi. Bu xato ko'pincha test serveridagi o'z-o'zidan imzolangan sertifikat bilan ishlash uchun yozilib, release'da qolib ketadi.
4. Nazoratsiz navigatsiya
WebView sahifadagi har qanday havolani o'zida ochadi, agar ilova buni cheklamasa. Natijada foydalanuvchi sizning ilovangiz ichida, lekin boshqa saytda (masalan, soxta login sahifasida) bo'lishi mumkin va buni sezmaydi.
5. Logout'dan keyin qolgan ma'lumotlar
WebView o'z cookie'lari, localStorage, IndexedDB va keshini saqlaydi. Foydalanuvchi ilovadan chiqqanda native sessiya o'chiriladi, lekin WebView'dagi veb-sessiya cookie'si qoladi. Keyingi foydalanuvchi (yoki qurilmani qo'liga olgan odam) WebView'ni ochsa, oldingi akkauntga kirib qoladi. O'z ilovamizni ekspertizaga tayyorlashda biz aynan shu nuqtani yopdik: logout paytida WebView ma'lumotlari to'liq tozalanadigan qilindi.
6. Debug rejimi
WebView.setWebContentsDebuggingEnabled(true) (Android) yoki isInspectable = true (iOS) release build'da qolsa, kompyuterdan Chrome DevTools yoki Safari Web Inspector orqali WebView ichiga ulanib, DOM, cookie va so'rovlarni ko'rish mumkin.
Nega bu ekspertiza uchun muhim
OWASP MASVS'ning PLATFORM guruhida WebView'lar xavfsiz sozlanishi va ko'priklar faqat zarur bo'lganda ochilishi talab qilinadi; MASTG'da WebView uchun alohida test holatlari bor (JavaScript, fayl ruxsatlari, ko'priklar, navigatsiya). OWASP Mobile Top 10 (2024) bo'yicha bu topilmalar M4 (Insufficient Input/Output Validation), M5 (Insecure Communication — aralash kontent va SSL xatosini e'tiborsiz qoldirish), M8 (Security Misconfiguration) va M9 (Insecure Data Storage — logout'dan keyin qolgan ma'lumotlar) toifalariga tushadi.
Ekspert APK'ni dekompilyatsiya qilib, WebView sozlamalarini kodda qidiradi va dinamik tahlilda WebView'ga begona URL yuklashga urinadi. Shuning uchun bu qismni oldindan ko'rib chiqish foydali.
O'zingiz qanday tekshirasiz
Statik tekshiruv
APK'ni jadx bilan oching va qidiring:
jadx -d out app-release.apk
grep -rn "addJavascriptInterface\|setAllowFileAccess\|setAllowUniversalAccessFromFileURLs\|setAllowFileAccessFromFileURLs" out/sources
grep -rn "onReceivedSslError\|setMixedContentMode\|setWebContentsDebuggingEnabled" out/sources
grep -rn "@JavascriptInterface" out/sources
Har bir @JavascriptInterface metodini ko'rib chiqing: u nimani qaytaradi va nimani bajaradi? Token, shaxsiy ma'lumot yoki to'lov amali — xavfli belgi.
Flutter ilovalarida asosiy kod libapp.so ichida, shuning uchun manba kodingizda qidiring: addJavaScriptChannel, setJavaScriptMode, loadRequest, NavigationDelegate.
iOS'da manba kodda WKWebView, addScriptMessageHandler, allowFileAccessFromFileURLs, isInspectable qidiring. Eskirgan UIWebView umuman qolmagan bo'lishi kerak.
Dinamik tekshiruv
- WebView ochadigan har bir yo'lni sinang: deep link parametri, push-bildirishnoma, sahifadagi havola. Begona domen ochilib qolmasligi kerak.
- Test qurilmada
chrome://inspectsahifasini oching. Release ilovaning WebView'i u yerda ko'rinmasligi kerak. - Proxy (masalan, Burp Suite) orqali trafikni kuzating:
httpso'rovlar bo'lmasligi kerak. Proxy sertifikatini o'rnatmagan holda sinab ko'ring — WebView sahifani ochmasligi kerak (agar ochsa, SSL xatosi e'tiborsiz qoldirilmoqda). - Logout qiling, keyin WebView sahifasini qayta oching. Login talab qilinishi kerak.
Qanday yopiladi
Android (Kotlin)
val allowedHosts = setOf("example.uz", "pay.example.uz")
webView.settings.apply {
javaScriptEnabled = true // faqat kerak bo'lsa
allowFileAccess = false
allowContentAccess = false
@Suppress("DEPRECATION")
allowFileAccessFromFileURLs = false
@Suppress("DEPRECATION")
allowUniversalAccessFromFileURLs = false
mixedContentMode = WebSettings.MIXED_CONTENT_NEVER_ALLOW
domStorageEnabled = true
}
WebView.setWebContentsDebuggingEnabled(BuildConfig.DEBUG)
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(
view: WebView, request: WebResourceRequest
): Boolean {
val uri = request.url
val ok = uri.scheme == "https" && uri.host in allowedHosts
if (!ok) {
// begona havola tashqi brauzerda ochiladi yoki bloklanadi
return true
}
return false
}
override fun onReceivedSslError(
view: WebView, handler: SslErrorHandler, error: SslError
) {
handler.cancel() // hech qachon proceed() emas
}
}
Lokal HTML fayllarni ko'rsatish kerak bo'lsa, file:// o'rniga androidx.webkit kutubxonasidagi WebViewAssetLoader ishlating: u fayllarni https://appassets.androidplatform.net/... ko'rinishidagi manzil orqali beradi va fayl ruxsatlarini yoqish shart bo'lmaydi.
JavaScript ko'prigi kerak bo'lsa:
- uni faqat ishonchli domen yuklanganda qo'shing;
- metodlar minimal bo'lsin va maxfiy ma'lumot qaytarmasin;
- har bir chaqiruvda
webView.urlhostini tekshiring; - imkon bo'lsa,
androidx.webkitdagiaddWebMessageListenerdan foydalaning — u ruxsat berilgan origin'lar ro'yxatini qabul qiladi.
Logout'da tozalash:
fun clearWebData(context: Context, webView: WebView?) {
CookieManager.getInstance().removeAllCookies(null)
CookieManager.getInstance().flush()
WebStorage.getInstance().deleteAllData()
webView?.clearCache(true)
webView?.clearHistory()
webView?.clearFormData()
}
iOS (Swift)
let config = WKWebViewConfiguration()
config.preferences.javaScriptCanOpenWindowsAutomatically = false
let webView = WKWebView(frame: .zero, configuration: config)
#if DEBUG
if #available(iOS 16.4, *) { webView.isInspectable = true }
#endif
func webView(_ webView: WKWebView,
decidePolicyFor action: WKNavigationAction,
decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
guard let url = action.request.url,
url.scheme == "https",
let host = url.host,
["example.uz", "pay.example.uz"].contains(host) else {
decisionHandler(.cancel); return
}
decisionHandler(.allow)
}
Script message handler'da message.frameInfo.securityOrigin.host ni tekshiring va faqat ruxsat berilgan origin'dan kelgan xabarni qabul qiling. ATS (App Transport Security) istisnolarini (NSAllowsArbitraryLoads) yoqmang.
Logout'da:
let store = WKWebsiteDataStore.default()
store.removeData(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(),
modifiedSince: .distantPast) { }
Maxfiy sahifalar uchun WKWebsiteDataStore.nonPersistent() ishlatish ham mumkin — u holda ma'lumotlar diskka yozilmaydi.
Flutter (webview_flutter)
const allowedHosts = {'example.uz', 'pay.example.uz'};
final controller = WebViewController()
..setJavaScriptMode(JavaScriptMode.unrestricted) // faqat kerak bo'lsa
..setNavigationDelegate(
NavigationDelegate(
onNavigationRequest: (request) {
final uri = Uri.parse(request.url);
final ok = uri.scheme == 'https' && allowedHosts.contains(uri.host);
return ok ? NavigationDecision.navigate : NavigationDecision.prevent;
},
),
)
..loadRequest(Uri.parse('https://example.uz/help'));
JavaScript channel qo'shsangiz, xabar kelganda joriy sahifa manzilini tekshiring (await controller.currentUrl()) va channel orqali tokenni hech qachon qaytarmang.
Logout'da:
Future<void> clearWebData(WebViewController? controller) async {
await WebViewCookieManager().clearCookies();
if (controller != null) {
await controller.clearCache();
await controller.clearLocalStorage();
}
}
Android tomonida network_security_config.xml da cleartextTrafficPermitted="false" bo'lishi ham WebView'dagi http so'rovlarni to'xtatadi — bu haqda alohida maqolada yozganmiz.
Server tomonda
WebView'da ochiladigan sahifalar oddiy veb-sahifa kabi himoyalanishi kerak: CSP, HttpOnly va Secure cookie'lar, XSS'ga qarshi to'g'ri escaping. Sahifadagi XSS WebView ichida native ko'prikka kirish degani, shuning uchun bu yerda veb-xavfsizlik va mobil xavfsizlik birlashadi.
Qisqa checklist
- WebView faqat allowlist'dagi
httpsdomenlarni ochadi; qolganlari tashqi brauzerga yoki bloklanadi. -
onReceivedSslErrorichida faqatcancel();proceed()yo'q. -
MIXED_CONTENT_NEVER_ALLOW, cleartext o'chirilgan, iOS'da ATS istisnolari yo'q. - Fayl ruxsatlari o'chirilgan; lokal fayllar
WebViewAssetLoaderorqali. - JavaScript faqat kerak bo'lgan WebView'larda yoqilgan.
- JavaScript ko'priklari minimal, maxfiy ma'lumot qaytarmaydi, origin tekshiriladi.
- Release'da WebView debugging va
isInspectableo'chirilgan. - Logout'da cookie, localStorage, kesh va tarix tozalanadi.
-
UIWebViewishlatilmaydi. - WebView'da ochiladigan sahifalarda CSP va XSS himoyasi bor.
Xulosa
WebView — ilova ichidagi kichik brauzer, lekin brauzerning ko'p himoyalarisiz. Unga nima yuklanishi, yuklangan sahifa nimaga kira olishi va foydalanuvchi chiqqandan keyin nima qolishi ilova tomonidan aniq belgilanishi kerak. Allowlist, o'chirilgan fayl ruxsatlari, qat'iy TLS va logout'da to'liq tozalash — WebView bo'yicha ekspertiza topilmalarining ko'pini yopadi. Deep link orqali WebView'ga URL uzatish haqida deep link va eksport komponentlar maqolasida batafsil yozilgan.
Ilovangizdagi WebView'lar to'g'ri sozlanganini ekspertizadan oldin bilmoqchi bo'lsangiz, skanerlash uchun ariza qoldiring. Claude AI agenti kod va sozlamalarni ko'rib chiqadi, mutaxassisimiz esa topilmalarni qurilmada tekshirib, yopishda yordam beradi.


