webview的工作、内存泄漏、漏洞以及缓存机制原理原理+方案解决

分析一段appium的日志来分析webview的工作原理,文章尾部附有自动化脚本及完整日志:

解析:

获取上下文列表

服务端发送命令adb shell cat /proc/net/unix获取域套接字列表。那什么是域套接字呢? 域套接字:是unix系统里进程与进程之间通信的一种方式。客户端想要与服务端想要连接,必须有共同的套接字和相应的服务端的端口号。套接字会一直处于监听状态,监听客户端发来的请求。 adb shell cat /proc/net/unix是获取手机端的套接字,这些套接字是用来监听外界发来的请求 adb shell cat /proc/net/unix |grep webview显示webview的套接字,其中套接字最后的数字就是进程ID

获取到webview的进程后,通过命令adb shell ps |grep 9986查询出来该进程对应的应用

匹配chromedrvier

这里是将现存的chromediver进程杀掉,并查找可以匹配webview版本的chromedriver,如果没有相对应的版本此处会报错。

查看本地和手机端的tcp连接映射关系

adb forward --list adb forward 命令是查看本地和手机端端tcp连接的映射关系

结果显示本地的57973端口和手机端的webview端口进行通信 adb forward tcp:8888 tcp:9999建立本地8888端口和手机端9999端口的映射 adb forward --remove tcp:8888删除8888端口 更多adb forward的使用方法参考:adb |grep forward 注意看:日志上是将这个映射关系给抹除了,目的是防止该进程没有被正常关闭时影响接下来的操作。

扫描二维码关注公众号,回复: 14607853 查看本文章

启动chromedriver

这里启动起来了chromedriver,占用的是8000端口(日志没截全,可以去看文章开头的全量日志)监听的本地的5037端口,为啥占用的是8000?在日志第303行,因为我们的脚本中没有指定端口,所以appium默认选择了一个空闲的8000端口。

创建session

这里的session是指的appium server和chromedriver之间通信的session,

转发请求,将appium server的请求转发给chromedriver

Proxying [GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/source] to [GET http://127.0.0.1:8000/wd/hub/session/ed7fb83742cae3d1847485e4a02ad001/source>] with body: {}

这条命令可以看出来,appium server对发到4723端口的操作,转发到了8000端口,并且session_id是appium. server 和chromedriver之间的session,本质上就是appium做了个代理,把请求进行了一次转发。

以上是我对appium 在做webview进行自动化测试时的总结,以上如有疏漏烦请各位指出,以期共同进步。

完整日志:

脚本及appium日志如下: 自动化脚本:

from appium import webdriver
from appium.webdriver.common.mobileby import MobileBy
from appium.webdriver.common.touch_action import TouchAction

class TestDemoTwo:

    def setup(self):
        caps = {
            "platformName": "android",
            "deviceName": "test",
            "appPackage": "io.appium.android.apis",
            "appActivity": "io.appium.android.apis.ApiDemos",
            "noReset": "true"
        }
    
        self.driver = webdriver.Remote("http://localhost:4723/wd/hub", caps)
        self.driver.implicitly_wait(10)
    
    def teardown(self):
        pass
    
    def test_webview(self):
        view = "WebView"
        self.driver.find_element(MobileBy.XPATH, "//*[@text='Views']").click()
        # print(self.driver.contexts)
        self.driver.find_element(MobileBy.ANDROID_UIAUTOMATOR,
                                 f'new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("{view}").instance(0));').click()
        # 打印上下文
        print(self.driver.contexts)
        # 定位元素及操作
        self.driver.find_element(MobileBy.XPATH, '//*[@resource-id="i am a link"]').click()
        print(self.driver.contexts)
        # 切换上下文
        self.driver.switch_to.context(self.driver.contexts[-1])
        # self.driver.find_element(MobileBy.XPATH)
        # self.driver.find_element(MobileBy.XPATH, "//*[contains(@text,'other')]").get_attribute("text")
        print(self.driver.page_source)
​

appium日志:

2021-10-10 08:00:36:303 [Appium] Welcome to Appium v1.15.1
2021-10-10 08:00:36:306 [Appium] Non-default server args:
2021-10-10 08:00:36:307 [Appium]   sessionOverride: true
2021-10-10 08:00:36:308 [Appium]   logFile: appium1.log
2021-10-10 08:00:36:428 [Appium] Appium REST http interface listener started on 0.0.0.0:4723
2021-10-10 08:00:51:282 [HTTP] --> POST /wd/hub/session
2021-10-10 08:00:51:283 [HTTP] {"capabilities":{"firstMatch":[{"platformName":"android","appium:deviceName":"test","appium:appPackage":"io.appium.android.apis","appium:appActivity":"io.appium.android.apis.ApiDemos","appium:noReset":"true"}]},"desiredCapabilities":{"platformName":"android","deviceName":"test","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":"true"}}
2021-10-10 08:00:51:288 [W3C] Calling AppiumDriver.createSession() with args: [{"platformName":"android","deviceName":"test","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":"true"},null,{"firstMatch":[{"platformName":"android","appium:deviceName":"test","appium:appPackage":"io.appium.android.apis","appium:appActivity":"io.appium.android.apis.ApiDemos","appium:noReset":"true"}]}]
2021-10-10 08:00:51:290 [BaseDriver] Event 'newSessionRequested' logged at 1633852851289 (16:00:51 GMT+0800 (中国标准时间))
2021-10-10 08:00:51:305 [Appium] 
2021-10-10 08:00:51:305 [Appium] ======================================================================
2021-10-10 08:00:51:306 [Appium]   DEPRECATION WARNING:
2021-10-10 08:00:51:306 [Appium] 
2021-10-10 08:00:51:307 [Appium]   The 'automationName' capability was not provided in the desired 
2021-10-10 08:00:51:308 [Appium]   capabilities for this Android session
2021-10-10 08:00:51:308 [Appium] 
2021-10-10 08:00:51:309 [Appium]   Setting 'automationName=UiAutomator2' by default and using the 
2021-10-10 08:00:51:310 [Appium]   UiAutomator2 Driver
2021-10-10 08:00:51:311 [Appium] 
2021-10-10 08:00:51:311 [Appium]   The next major version of Appium (2.x) will **require** the 
2021-10-10 08:00:51:312 [Appium]   'automationName' capability to be set for all sessions on all 
2021-10-10 08:00:51:313 [Appium]   platforms
2021-10-10 08:00:51:314 [Appium] 
2021-10-10 08:00:51:314 [Appium]   In previous versions (Appium <= 1.13.x), the default was 
2021-10-10 08:00:51:315 [Appium]   'automationName=UiAutomator1'
2021-10-10 08:00:51:315 [Appium] 
2021-10-10 08:00:51:315 [Appium]   If you wish to use that automation instead of UiAutomator2, please 
2021-10-10 08:00:51:316 [Appium]   add 'automationName=UiAutomator1' to your desired capabilities
2021-10-10 08:00:51:317 [Appium] 
2021-10-10 08:00:51:317 [Appium]   For more information about drivers, please visit 
2021-10-10 08:00:51:317 [Appium]   http://appium.io/docs/en/about-appium/intro/ and explore the 
2021-10-10 08:00:51:318 [Appium]   'Drivers' menu
2021-10-10 08:00:51:318 [Appium] 
2021-10-10 08:00:51:318 [Appium] ======================================================================
2021-10-10 08:00:51:318 [Appium] 
2021-10-10 08:00:51:828 [Appium] Appium v1.15.1 creating new AndroidUiautomator2Driver (v1.37.2) session
2021-10-10 08:00:51:833 [BaseDriver] W3C capabilities and MJSONWP desired capabilities were provided
2021-10-10 08:00:51:833 [BaseDriver] Creating session with W3C capabilities: {
2021-10-10 08:00:51:833 [BaseDriver]   "alwaysMatch": {
2021-10-10 08:00:51:834 [BaseDriver]     "platformName": "android",
2021-10-10 08:00:51:834 [BaseDriver]     "appium:deviceName": "test",
2021-10-10 08:00:51:834 [BaseDriver]     "appium:appPackage": "io.appium.android.apis",
2021-10-10 08:00:51:834 [BaseDriver]     "appium:appActivity": "io.appium.android.apis.ApiDemos",
2021-10-10 08:00:51:835 [BaseDriver]     "appium:noReset": "true"
2021-10-10 08:00:51:835 [BaseDriver]   },
2021-10-10 08:00:51:835 [BaseDriver]   "firstMatch": [
2021-10-10 08:00:51:835 [BaseDriver]     {}
2021-10-10 08:00:51:836 [BaseDriver]   ]
2021-10-10 08:00:51:836 [BaseDriver] }
2021-10-10 08:00:51:848 [BaseDriver] Capability 'noReset' changed from string to boolean. This may cause unexpected behavior
2021-10-10 08:00:51:855 [BaseDriver] Session created with session id: b76bb00a-43bc-4155-bd6a-ccaa3eb865b2
2021-10-10 08:00:51:857 [UiAutomator2] Starting 'io.appium.android.apis' directly on the device
2021-10-10 08:00:51:904 [ADB] Found 3 'build-tools' folders under '/Users/yujin/Library/Android/sdk' (newest first):
2021-10-10 08:00:51:904 [ADB]     /Users/yujin/Library/Android/sdk/build-tools/29.0.3
2021-10-10 08:00:51:905 [ADB]     /Users/yujin/Library/Android/sdk/build-tools/29.0.2
2021-10-10 08:00:51:905 [ADB]     /Users/yujin/Library/Android/sdk/build-tools/28.0.3
2021-10-10 08:00:51:905 [ADB] Using 'adb' from '/Users/yujin/Library/Android/sdk/platform-tools/adb'
2021-10-10 08:00:51:906 [AndroidDriver] Retrieving device list
2021-10-10 08:00:51:906 [ADB] Trying to find a connected android device
2021-10-10 08:00:51:907 [ADB] Getting connected devices...
2021-10-10 08:00:51:932 [ADB] Connected devices: [{"udid":"emulator-5554","state":"device"}]
2021-10-10 08:00:51:933 [AndroidDriver] Using device: emulator-5554
2021-10-10 08:00:51:934 [ADB] Using 'adb' from '/Users/yujin/Library/Android/sdk/platform-tools/adb'
2021-10-10 08:00:51:935 [ADB] Setting device id to emulator-5554
2021-10-10 08:00:51:936 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell getprop ro.build.version.sdk'
2021-10-10 08:00:51:960 [ADB] Current device property 'ro.build.version.sdk': 23
2021-10-10 08:00:51:960 [ADB] Device API level: 23
2021-10-10 08:00:51:961 [AndroidDriver] No app sent in, not parsing package/activity
2021-10-10 08:00:51:964 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 wait-for-device'
2021-10-10 08:00:51:976 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell echo ping'
2021-10-10 08:00:51:995 [AndroidDriver] Pushing settings apk to device...
2021-10-10 08:00:51:996 [ADB] Getting install status for io.appium.settings
2021-10-10 08:00:51:997 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package io.appium.settings'
2021-10-10 08:00:52:047 [ADB] 'io.appium.settings' is installed
2021-10-10 08:00:52:049 [ADB] Getting package info for 'io.appium.settings'
2021-10-10 08:00:52:049 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package io.appium.settings'
2021-10-10 08:00:52:081 [ADB] Using 'apkanalyzer' from '/Users/yujin/Library/Android/sdk/tools/bin/apkanalyzer'
2021-10-10 08:00:52:081 [ADB] Starting '/Users/yujin/Library/Android/sdk/tools/bin/apkanalyzer' with args ["manifest","print","/usr/local/lib/node_modules/appium/node_modules/io.appium.settings/apks/settings_apk-debug.apk"]
2021-10-10 08:00:57:066 [ADB] The version name of the installed 'io.appium.settings' is greater or equal to the application version name ('2.14.2' >= '2.14.2')
2021-10-10 08:00:57:067 [ADB] There is no need to install/upgrade '/usr/local/lib/node_modules/appium/node_modules/io.appium.settings/apks/settings_apk-debug.apk'
2021-10-10 08:00:57:068 [ADB] Getting IDs of all 'io.appium.settings' processes
2021-10-10 08:00:57:068 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell 'pgrep --help; echo $?''
2021-10-10 08:00:57:101 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell pgrep -f io\.appium\.settings'
2021-10-10 08:00:57:130 [AndroidDriver] io.appium.settings is already running. There is no need to reset its permissions.
2021-10-10 08:00:57:130 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell appops set io.appium.settings android:mock_location allow'
2021-10-10 08:00:58:217 [Logcat] Starting logcat capture
2021-10-10 08:00:58:313 [ADB] Getting install status for io.appium.uiautomator2.server
2021-10-10 08:00:58:315 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package io.appium.uiautomator2.server'
2021-10-10 08:00:58:390 [ADB] 'io.appium.uiautomator2.server' is installed
2021-10-10 08:00:58:393 [ADB] Getting package info for 'io.appium.uiautomator2.server'
2021-10-10 08:00:58:395 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package io.appium.uiautomator2.server'
2021-10-10 08:00:58:446 [ADB] Starting '/Users/yujin/Library/Android/sdk/tools/bin/apkanalyzer' with args ["manifest","print","/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v4.3.0.apk"]
2021-10-10 08:01:01:855 [ADB] The version name of the installed 'io.appium.uiautomator2.server' is greater or equal to the application version name ('4.3.0' >= '4.3.0')
2021-10-10 08:01:01:856 [UiAutomator2] io.appium.uiautomator2.server installation state: sameVersionInstalled
2021-10-10 08:01:01:857 [ADB] Checking app cert for /usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v4.3.0.apk
2021-10-10 08:01:01:860 [ADB] Using 'apksigner' from '/Users/yujin/Library/Android/sdk/build-tools/29.0.3/apksigner'
2021-10-10 08:01:01:861 [ADB] Starting '/Users/yujin/Library/Android/sdk/build-tools/29.0.3/apksigner' with args '["verify","--print-certs","/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v4.3.0.apk"]'
2021-10-10 08:01:03:145 [ADB] apksigner stdout: Signer #1 certificate DN: [email protected], CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
2021-10-10 08:01:03:145 [ADB] Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc
2021-10-10 08:01:03:146 [ADB] Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81
2021-10-10 08:01:03:147 [ADB] Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87
2021-10-10 08:01:03:147 [ADB] 
2021-10-10 08:01:03:147 [ADB] '/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v4.3.0.apk' is already signed.
2021-10-10 08:01:03:148 [ADB] Getting install status for io.appium.uiautomator2.server.test
2021-10-10 08:01:03:148 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package io.appium.uiautomator2.server.test'
2021-10-10 08:01:03:189 [ADB] 'io.appium.uiautomator2.server.test' is installed
2021-10-10 08:01:03:189 [ADB] Checking app cert for /usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-debug-androidTest.apk
2021-10-10 08:01:03:190 [ADB] Starting '/Users/yujin/Library/Android/sdk/build-tools/29.0.3/apksigner' with args '["verify","--print-certs","/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-debug-androidTest.apk"]'
2021-10-10 08:01:04:340 [ADB] apksigner stdout: Signer #1 certificate DN: [email protected], CN=Android, OU=Android, O=Android, L=Mountain View, ST=California, C=US
2021-10-10 08:01:04:340 [ADB] Signer #1 certificate SHA-256 digest: a40da80a59d170caa950cf15c18c454d47a39b26989d8b640ecd745ba71bf5dc
2021-10-10 08:01:04:341 [ADB] Signer #1 certificate SHA-1 digest: 61ed377e85d386a8dfee6b864bd85b0bfaa5af81
2021-10-10 08:01:04:341 [ADB] Signer #1 certificate MD5 digest: e89b158e4bcf988ebd09eb83f5378e87
2021-10-10 08:01:04:343 [ADB] 
2021-10-10 08:01:04:343 [ADB] '/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-debug-androidTest.apk' is already signed.
2021-10-10 08:01:04:343 [UiAutomator2] Server packages are not going to be (re)installed
2021-10-10 08:01:04:350 [UiAutomator2] Waiting up to 30000ms for services to be available
2021-10-10 08:01:04:351 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell pm list instrumentation'
2021-10-10 08:01:04:718 [UiAutomator2] Instrumentation target 'io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner' is available
2021-10-10 08:01:04:718 [UiAutomator2] Forwarding UiAutomator2 Server port 6790 to 8200
2021-10-10 08:01:04:719 [ADB] Forwarding system: 8200 to device: 6790
2021-10-10 08:01:04:721 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 forward tcp:8200 tcp:6790'
2021-10-10 08:01:04:738 [UiAutomator2] No app capability. Assuming it is already on the device
2021-10-10 08:01:04:739 [UiAutomator2] Performing shallow cleanup of automation leftovers
2021-10-10 08:01:04:770 [UiAutomator2] No obsolete sessions have been detected (Error: socket hang up)
2021-10-10 08:01:04:770 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am force-stop io.appium.uiautomator2.server.test'
2021-10-10 08:01:05:311 [UiAutomator2] Starting UIAutomator2 server 4.3.0
2021-10-10 08:01:05:312 [UiAutomator2] Using UIAutomator2 server from '/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-v4.3.0.apk' and test from '/usr/local/lib/node_modules/appium/node_modules/appium-uiautomator2-server/apks/appium-uiautomator2-server-debug-androidTest.apk'
2021-10-10 08:01:05:312 [UiAutomator2] Waiting up to 30000ms for UiAutomator2 to be online...
2021-10-10 08:01:05:313 [ADB] Creating ADB subprocess with args: ["-P",5037,"-s","emulator-5554","shell","am","instrument","-w","io.appium.uiautomator2.server.test/androidx.test.runner.AndroidJUnitRunner"]
2021-10-10 08:01:06:069 [Instrumentation] io.appium.uiautomator2.server.test.AppiumUiAutomator2Server:
2021-10-10 08:01:06:326 [WD Proxy] Matched '/status' to command name 'getStatus'
2021-10-10 08:01:06:328 [WD Proxy] Proxying [GET /status] to [GET http://localhost:8200/wd/hub/status] with no body
2021-10-10 08:01:06:335 [WD Proxy] Got an unexpected response with status undefined: {"code":"ECONNRESET"}
2021-10-10 08:01:07:341 [WD Proxy] Matched '/status' to command name 'getStatus'
2021-10-10 08:01:07:343 [WD Proxy] Proxying [GET /status] to [GET http://localhost:8200/wd/hub/status] with no body
2021-10-10 08:01:07:398 [WD Proxy] Got response with status 200: {"sessionId":"None","value":{"ready":true,"message":"UiAutomator2 Server is ready to accept commands"}}
2021-10-10 08:01:07:399 [UiAutomator2] The initialization of the instrumentation process took 2087ms
2021-10-10 08:01:07:401 [WD Proxy] Matched '/session' to command name 'createSession'
2021-10-10 08:01:07:403 [WD Proxy] Proxying [POST /session] to [POST http://localhost:8200/wd/hub/session] with body: {"capabilities":{"firstMatch":[{"platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"android","deviceName":"test","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true},"platformName":"android","deviceName":"emulator-5554","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true,"deviceUDID":"emulator-5554"}],"alwaysMatch":{}}}
2021-10-10 08:01:07:420 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","capabilities":{"firstMatch":[{"platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"android","deviceName":"test","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true},"platformName":"android","deviceName":"emulator-5554","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true,"deviceUDID":"emulator-5554"}],"alwaysMatch":{}}}}
2021-10-10 08:01:07:420 [WD Proxy] Determined the downstream protocol as 'W3C'
2021-10-10 08:01:07:437 [WD Proxy] Proxying [GET /appium/device/info] to [GET http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/appium/device/info] with no body
2021-10-10 08:01:07:462 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"androidId":"eeccdb17137abe38","manufacturer":"Netease","model":"MuMu","brand":"Android","apiVersion":"23","platformVersion":"6.0.1","carrierName":"","realDisplaySize":"720x1280","displayDensity":280,"networks":[{"type":1,"typeName":"WIFI","subtype":0,"subtypeName":"","isConnected":true,"detailedState":"CONNECTED","state":"CONNECTED","extraInfo":""u4b3zvSCE43"","isAvailable":true,"isFailover":false,"isRoaming":false,"capabilities":{"transportTypes":"NET_CAPABILITY_SUPL","networkCapabilities":"","linkUpstreamBandwidthKbps":1048576,"linkDownBandwidthKbps":1048576,"signalStrength":-55,"networkSpecifier":null,"SSID":null}}],"locale":"zh_CN","timeZone":"Asia/Shanghai"}}
2021-10-10 08:01:07:463 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys window'
2021-10-10 08:01:07:500 [AndroidDriver] Screen already unlocked, doing nothing
2021-10-10 08:01:07:502 [UiAutomator2] Starting 'io.appium.android.apis/io.appium.android.apis.ApiDemos and waiting for 'io.appium.android.apis/io.appium.android.apis.ApiDemos'
2021-10-10 08:01:07:503 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am start -W -n io.appium.android.apis/io.appium.android.apis.ApiDemos -S -a android.intent.action.MAIN -c android.intent.category.LAUNCHER -f 0x10200000'
2021-10-10 08:01:09:768 [WD Proxy] Proxying [GET /appium/device/pixel_ratio] to [GET http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/appium/device/pixel_ratio] with body: {}
2021-10-10 08:01:09:838 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":1.75}
2021-10-10 08:01:09:840 [WD Proxy] Matched '/appium/device/system_bars' to command name 'getSystemBars'
2021-10-10 08:01:09:841 [WD Proxy] Proxying [GET /appium/device/system_bars] to [GET http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/appium/device/system_bars] with body: {}
2021-10-10 08:01:09:861 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"statusBar":42}}
2021-10-10 08:01:09:862 [WD Proxy] Matched '/window/current/size' to command name 'getWindowSize'
2021-10-10 08:01:09:862 [WD Proxy] Proxying [GET /window/current/size] to [GET http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/window/current/size] with body: {}
2021-10-10 08:01:09:872 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"height":1280,"width":720}}
2021-10-10 08:01:09:873 [Appium] New AndroidUiautomator2Driver session created successfully, session b76bb00a-43bc-4155-bd6a-ccaa3eb865b2 added to master session list
2021-10-10 08:01:09:874 [BaseDriver] Event 'newSessionStarted' logged at 1633852869874 (16:01:09 GMT+0800 (中国标准时间))
2021-10-10 08:01:09:875 [W3C (b76bb00a)] Cached the protocol value 'W3C' for the new session b76bb00a-43bc-4155-bd6a-ccaa3eb865b2
2021-10-10 08:01:09:879 [W3C (b76bb00a)] Responding to client with driver.createSession() result: {"capabilities":{"platform":"LINUX","webStorageEnabled":false,"takesScreenshot":true,"javascriptEnabled":true,"databaseEnabled":false,"networkConnectionEnabled":true,"locationContextEnabled":false,"warnings":{},"desired":{"platformName":"android","deviceName":"test","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true},"platformName":"android","deviceName":"emulator-5554","appPackage":"io.appium.android.apis","appActivity":"io.appium.android.apis.ApiDemos","noReset":true,"deviceUDID":"emulator-5554","deviceApiLevel":23,"platformVersion":"6.0.1","deviceScreenSize":"720x1280","deviceScreenDensity":280,"deviceModel":"MuMu","deviceManufacturer":"Netease","pixelRatio":1.75,"statBarHeight":42,"viewportRect":{"left":0,"top":42,"width":720,"height":1238}}}
2021-10-10 08:01:09:884 [HTTP] <-- POST /wd/hub/session 200 18599 ms - 867
2021-10-10 08:01:09:884 [HTTP] 
2021-10-10 08:01:09:889 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/timeouts
2021-10-10 08:01:09:890 [HTTP] {"implicit":10000}
2021-10-10 08:01:09:893 [W3C (b76bb00a)] Calling AppiumDriver.timeouts() with args: [null,null,null,null,10000,"b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:09:943 [BaseDriver] W3C timeout argument: {"implicit":10000}}
2021-10-10 08:01:09:944 [BaseDriver] Set implicit wait to 10000ms
2021-10-10 08:01:09:945 [W3C (b76bb00a)] Responding to client with driver.timeouts() result: null
2021-10-10 08:01:09:947 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/timeouts 200 57 ms - 14
2021-10-10 08:01:09:948 [HTTP] 
2021-10-10 08:01:09:957 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element
2021-10-10 08:01:09:958 [HTTP] {"using":"xpath","value":"//*[@text='Views']"}
2021-10-10 08:01:09:961 [W3C (b76bb00a)] Calling AppiumDriver.findElement() with args: ["xpath","//*[@text='Views']","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:09:963 [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
2021-10-10 08:01:09:964 [BaseDriver] Waiting up to 10000 ms for condition
2021-10-10 08:01:09:966 [WD Proxy] Matched '/element' to command name 'findElement'
2021-10-10 08:01:09:966 [WD Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element] with body: {"strategy":"xpath","selector":"//*[@text='Views']","context":"","multiple":false}
2021-10-10 08:01:10:283 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"ELEMENT":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2","element-6066-11e4-a52e-4f735466cecf":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2"}}
2021-10-10 08:01:10:284 [W3C (b76bb00a)] Responding to client with driver.findElement() result: {"element-6066-11e4-a52e-4f735466cecf":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2","ELEMENT":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2"}
2021-10-10 08:01:10:285 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element 200 329 ms - 137
2021-10-10 08:01:10:286 [HTTP] 
2021-10-10 08:01:10:291 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2/click
2021-10-10 08:01:10:291 [HTTP] {"id":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2"}
2021-10-10 08:01:10:294 [W3C (b76bb00a)] Calling AppiumDriver.click() with args: ["f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:10:295 [WD Proxy] Matched '/element/f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2/click' to command name 'click'
2021-10-10 08:01:10:296 [WD Proxy] Proxying [POST /element/f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2/click] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element/f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2/click] with body: {"element":"f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2"}
2021-10-10 08:01:11:397 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":null}
2021-10-10 08:01:11:400 [W3C (b76bb00a)] Responding to client with driver.click() result: null
2021-10-10 08:01:11:402 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/f2eed02a-5ae0-47bb-8a7d-cf9a10f242c2/click 200 1110 ms - 14
2021-10-10 08:01:11:402 [HTTP] 
2021-10-10 08:01:11:405 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element
2021-10-10 08:01:11:405 [HTTP] {"using":"-android uiautomator","value":"new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("WebView").instance(0));"}
2021-10-10 08:01:11:406 [W3C (b76bb00a)] Calling AppiumDriver.findElement() with args: ["-android uiautomator","new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("WebView").instance(0));","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:11:407 [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
2021-10-10 08:01:11:407 [BaseDriver] Waiting up to 10000 ms for condition
2021-10-10 08:01:11:408 [WD Proxy] Matched '/element' to command name 'findElement'
2021-10-10 08:01:11:408 [WD Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element] with body: {"strategy":"-android uiautomator","selector":"new UiScrollable(new UiSelector().scrollable(true).instance(0)).scrollIntoView(new UiSelector().text("WebView").instance(0));","context":"","multiple":false}
2021-10-10 08:01:20:730 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"ELEMENT":"4010cba7-b08f-494c-a543-24a1d871b8d1","element-6066-11e4-a52e-4f735466cecf":"4010cba7-b08f-494c-a543-24a1d871b8d1"}}
2021-10-10 08:01:20:731 [W3C (b76bb00a)] Responding to client with driver.findElement() result: {"element-6066-11e4-a52e-4f735466cecf":"4010cba7-b08f-494c-a543-24a1d871b8d1","ELEMENT":"4010cba7-b08f-494c-a543-24a1d871b8d1"}
2021-10-10 08:01:20:734 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element 200 9326 ms - 137
2021-10-10 08:01:20:734 [HTTP] 
2021-10-10 08:01:20:737 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/4010cba7-b08f-494c-a543-24a1d871b8d1/click
2021-10-10 08:01:20:738 [HTTP] {"id":"4010cba7-b08f-494c-a543-24a1d871b8d1"}
2021-10-10 08:01:20:739 [W3C (b76bb00a)] Calling AppiumDriver.click() with args: ["4010cba7-b08f-494c-a543-24a1d871b8d1","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:20:740 [WD Proxy] Matched '/element/4010cba7-b08f-494c-a543-24a1d871b8d1/click' to command name 'click'
2021-10-10 08:01:20:741 [WD Proxy] Proxying [POST /element/4010cba7-b08f-494c-a543-24a1d871b8d1/click] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element/4010cba7-b08f-494c-a543-24a1d871b8d1/click] with body: {"element":"4010cba7-b08f-494c-a543-24a1d871b8d1"}
2021-10-10 08:01:21:503 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":null}
2021-10-10 08:01:21:504 [W3C (b76bb00a)] Responding to client with driver.click() result: null
2021-10-10 08:01:21:506 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/4010cba7-b08f-494c-a543-24a1d871b8d1/click 200 768 ms - 14
2021-10-10 08:01:21:508 [HTTP] 
2021-10-10 08:01:21:511 [HTTP] --> GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts
2021-10-10 08:01:21:512 [HTTP] {}
2021-10-10 08:01:21:518 [W3C (b76bb00a)] Calling AppiumDriver.getContexts() with args: ["b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:21:520 [AndroidDriver] Getting a list of available webviews
2021-10-10 08:01:21:521 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell cat /proc/net/unix'
2021-10-10 08:01:21:608 [AndroidDriver] Not checking whether webviews have active pages; use the 'ensureWebviewsHavePages' cap to turn this check on
2021-10-10 08:01:21:611 [AndroidDriver] Found webviews: []
2021-10-10 08:01:21:612 [AndroidDriver] Available contexts: ["NATIVE_APP"]
2021-10-10 08:01:21:613 [W3C (b76bb00a)] Responding to client with driver.getContexts() result: ["NATIVE_APP"]
2021-10-10 08:01:21:617 [HTTP] <-- GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts 200 106 ms - 24
2021-10-10 08:01:21:618 [HTTP] 
2021-10-10 08:01:21:623 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element
2021-10-10 08:01:21:624 [HTTP] {"using":"xpath","value":"//*[@resource-id="i am a link"]"}
2021-10-10 08:01:21:627 [W3C (b76bb00a)] Calling AppiumDriver.findElement() with args: ["xpath","//*[@resource-id="i am a link"]","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:21:630 [BaseDriver] Valid locator strategies for this request: xpath, id, class name, accessibility id, -android uiautomator
2021-10-10 08:01:21:631 [BaseDriver] Waiting up to 10000 ms for condition
2021-10-10 08:01:21:634 [WD Proxy] Matched '/element' to command name 'findElement'
2021-10-10 08:01:21:636 [WD Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element] with body: {"strategy":"xpath","selector":"//*[@resource-id="i am a link"]","context":"","multiple":false}
2021-10-10 08:01:22:194 [WD Proxy] Got an unexpected response with status 404: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters","stacktrace":"io.appium.uiautomator2.common.exceptions.ElementNotFoundException: An element could not be located on the page using the given search parameters\n\tat io.appium.uiautomator2.handler.FindElement.findElement(FindElement.java:102)\n\tat io.appium.uiautomator2.handler.FindElement.safeHandle(FindElement.java:72)\n\tat io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:38)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:252)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:242)\n\tat io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:44)\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)\n\tat io.netty.channel.AbstractChannelHandlerCon...
2021-10-10 08:01:22:195 [W3C] Matched W3C error code 'no such element' to NoSuchElementError
2021-10-10 08:01:22:196 [BaseDriver] Waited for 565 ms so far
2021-10-10 08:01:22:697 [WD Proxy] Matched '/element' to command name 'findElement'
2021-10-10 08:01:22:698 [WD Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element] with body: {"strategy":"xpath","selector":"//*[@resource-id="i am a link"]","context":"","multiple":false}
2021-10-10 08:01:23:948 [WD Proxy] Got an unexpected response with status 404: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"error":"no such element","message":"An element could not be located on the page using the given search parameters","stacktrace":"io.appium.uiautomator2.common.exceptions.ElementNotFoundException: An element could not be located on the page using the given search parameters\n\tat io.appium.uiautomator2.handler.FindElement.findElement(FindElement.java:102)\n\tat io.appium.uiautomator2.handler.FindElement.safeHandle(FindElement.java:72)\n\tat io.appium.uiautomator2.handler.request.SafeRequestHandler.handle(SafeRequestHandler.java:38)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleRequest(AppiumServlet.java:252)\n\tat io.appium.uiautomator2.server.AppiumServlet.handleHttpRequest(AppiumServlet.java:242)\n\tat io.appium.uiautomator2.http.ServerHandler.channelRead(ServerHandler.java:44)\n\tat io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:366)\n\tat io.netty.channel.AbstractChannelHandlerCon...
2021-10-10 08:01:23:948 [W3C] Matched W3C error code 'no such element' to NoSuchElementError
2021-10-10 08:01:23:949 [BaseDriver] Waited for 2318 ms so far
2021-10-10 08:01:24:455 [WD Proxy] Matched '/element' to command name 'findElement'
2021-10-10 08:01:24:456 [WD Proxy] Proxying [POST /element] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element] with body: {"strategy":"xpath","selector":"//*[@resource-id="i am a link"]","context":"","multiple":false}
2021-10-10 08:01:24:714 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":{"ELEMENT":"eea82ab1-38d9-41c0-be30-edf8637af535","element-6066-11e4-a52e-4f735466cecf":"eea82ab1-38d9-41c0-be30-edf8637af535"}}
2021-10-10 08:01:24:716 [W3C (b76bb00a)] Responding to client with driver.findElement() result: {"element-6066-11e4-a52e-4f735466cecf":"eea82ab1-38d9-41c0-be30-edf8637af535","ELEMENT":"eea82ab1-38d9-41c0-be30-edf8637af535"}
2021-10-10 08:01:24:717 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element 200 3094 ms - 137
2021-10-10 08:01:24:718 [HTTP] 
2021-10-10 08:01:24:724 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/eea82ab1-38d9-41c0-be30-edf8637af535/click
2021-10-10 08:01:24:724 [HTTP] {"id":"eea82ab1-38d9-41c0-be30-edf8637af535"}
2021-10-10 08:01:24:726 [W3C (b76bb00a)] Calling AppiumDriver.click() with args: ["eea82ab1-38d9-41c0-be30-edf8637af535","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:24:728 [WD Proxy] Matched '/element/eea82ab1-38d9-41c0-be30-edf8637af535/click' to command name 'click'
2021-10-10 08:01:24:729 [WD Proxy] Proxying [POST /element/eea82ab1-38d9-41c0-be30-edf8637af535/click] to [POST http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a/element/eea82ab1-38d9-41c0-be30-edf8637af535/click] with body: {"element":"eea82ab1-38d9-41c0-be30-edf8637af535"}
2021-10-10 08:01:24:782 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":null}
2021-10-10 08:01:24:787 [W3C (b76bb00a)] Responding to client with driver.click() result: null
2021-10-10 08:01:24:790 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/element/eea82ab1-38d9-41c0-be30-edf8637af535/click 200 65 ms - 14
2021-10-10 08:01:24:790 [HTTP] 
2021-10-10 08:01:24:794 [HTTP] --> GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts
2021-10-10 08:01:24:795 [HTTP] {}
2021-10-10 08:01:24:800 [W3C (b76bb00a)] Calling AppiumDriver.getContexts() with args: ["b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:24:802 [AndroidDriver] Getting a list of available webviews
2021-10-10 08:01:24:802 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell cat /proc/net/unix'
2021-10-10 08:01:24:907 [AndroidDriver] Not checking whether webviews have active pages; use the 'ensureWebviewsHavePages' cap to turn this check on
2021-10-10 08:01:24:910 [AndroidDriver] WEBVIEW_2632 mapped to pid 2632
2021-10-10 08:01:24:911 [AndroidDriver] Getting process name for webview
2021-10-10 08:01:24:912 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps'
2021-10-10 08:01:25:026 [AndroidDriver] Parsed pid: '2632' pkg: 'io.appium.android.apis' from
2021-10-10 08:01:25:026 [AndroidDriver]     USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAME
2021-10-10 08:01:25:026 [AndroidDriver]     u0_a45    2632  291   1136340 120932          0 7f80807c0ea8 S io.appium.android.apis
2021-10-10 08:01:25:027 [AndroidDriver] Returning process name: 'io.appium.android.apis'
2021-10-10 08:01:25:030 [AndroidDriver] Found webviews: ["WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:030 [AndroidDriver] Available contexts: ["NATIVE_APP","WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:031 [W3C (b76bb00a)] Responding to client with driver.getContexts() result: ["NATIVE_APP","WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:036 [HTTP] <-- GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts 200 241 ms - 57
2021-10-10 08:01:25:036 [HTTP] 
2021-10-10 08:01:25:042 [HTTP] --> GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts
2021-10-10 08:01:25:043 [HTTP] {}
2021-10-10 08:01:25:044 [W3C (b76bb00a)] Calling AppiumDriver.getContexts() with args: ["b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:25:047 [AndroidDriver] Getting a list of available webviews
2021-10-10 08:01:25:047 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell cat /proc/net/unix'
2021-10-10 08:01:25:109 [AndroidDriver] Not checking whether webviews have active pages; use the 'ensureWebviewsHavePages' cap to turn this check on
2021-10-10 08:01:25:111 [AndroidDriver] WEBVIEW_2632 mapped to pid 2632
2021-10-10 08:01:25:112 [AndroidDriver] Getting process name for webview
2021-10-10 08:01:25:113 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps'
2021-10-10 08:01:25:146 [AndroidDriver] Parsed pid: '2632' pkg: 'io.appium.android.apis' from
2021-10-10 08:01:25:147 [AndroidDriver]     USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAME
2021-10-10 08:01:25:147 [AndroidDriver]     u0_a45    2632  291   1139548 124380          0 7f808082cc1a S io.appium.android.apis
2021-10-10 08:01:25:147 [AndroidDriver] Returning process name: 'io.appium.android.apis'
2021-10-10 08:01:25:148 [AndroidDriver] Found webviews: ["WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:148 [AndroidDriver] Available contexts: ["NATIVE_APP","WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:149 [W3C (b76bb00a)] Responding to client with driver.getContexts() result: ["NATIVE_APP","WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:154 [HTTP] <-- GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/contexts 200 108 ms - 57
2021-10-10 08:01:25:155 [HTTP] 
2021-10-10 08:01:25:158 [HTTP] --> POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/context
2021-10-10 08:01:25:159 [HTTP] {"name":"WEBVIEW_io.appium.android.apis"}
2021-10-10 08:01:25:161 [W3C (b76bb00a)] Calling AppiumDriver.setContext() with args: ["WEBVIEW_io.appium.android.apis","b76bb00a-43bc-4155-bd6a-ccaa3eb865b2"]
2021-10-10 08:01:25:164 [AndroidDriver] Getting a list of available webviews
2021-10-10 08:01:25:165 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell cat /proc/net/unix'
2021-10-10 08:01:25:186 [AndroidDriver] Not checking whether webviews have active pages; use the 'ensureWebviewsHavePages' cap to turn this check on
2021-10-10 08:01:25:187 [AndroidDriver] WEBVIEW_2632 mapped to pid 2632
2021-10-10 08:01:25:187 [AndroidDriver] Getting process name for webview
2021-10-10 08:01:25:188 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell ps'
2021-10-10 08:01:25:223 [AndroidDriver] Parsed pid: '2632' pkg: 'io.appium.android.apis' from
2021-10-10 08:01:25:224 [AndroidDriver]     USER      PID   PPID  VSIZE  RSS   WCHAN              PC  NAME
2021-10-10 08:01:25:224 [AndroidDriver]     u0_a45    2632  291   1139548 124380          0 7f808082cc1a S io.appium.android.apis
2021-10-10 08:01:25:224 [AndroidDriver] Returning process name: 'io.appium.android.apis'
2021-10-10 08:01:25:225 [AndroidDriver] Found webviews: ["WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:225 [AndroidDriver] Available contexts: ["NATIVE_APP","WEBVIEW_io.appium.android.apis"]
2021-10-10 08:01:25:226 [AndroidDriver] Connecting to chrome-backed webview context 'WEBVIEW_io.appium.android.apis'
2021-10-10 08:01:25:238 [AndroidDriver] A port was not given, using random free port: 8000
2021-10-10 08:01:25:239 [AndroidDriver] Automated Chromedriver download is disabled. Use 'chromedriver_autodownload' server feature to enable it
2021-10-10 08:01:25:239 [AndroidDriver] Before starting chromedriver, androidPackage is 'io.appium.android.apis'
2021-10-10 08:01:25:240 [Chromedriver] Changed state to 'starting'
2021-10-10 08:01:25:245 [Chromedriver] Found 1 executable in '/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac'
2021-10-10 08:01:25:294 [Chromedriver] The following Chromedriver executables were found:
2021-10-10 08:01:25:294 [Chromedriver]     '/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver__mumu_2.42' (version '2.42', minimum Chrome version '68.0.3440')
2021-10-10 08:01:25:295 [ADB] Getting package info for 'com.google.android.webview'
2021-10-10 08:01:25:295 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package com.google.android.webview'
2021-10-10 08:01:25:324 [ADB] Getting package info for 'com.android.webview'
2021-10-10 08:01:25:325 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell dumpsys package com.android.webview'
2021-10-10 08:01:25:354 [Chromedriver] Found Chrome bundle 'com.android.webview' version '68.0.3440'
2021-10-10 08:01:25:357 [Chromedriver] Found 1 Chromedriver executable capable of automating Chrome '68.0.3440'.
2021-10-10 08:01:25:358 [Chromedriver] Choosing the most recent, '/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver__mumu_2.42'.
2021-10-10 08:01:25:358 [Chromedriver] If a specific version is required, specify it with the `chromedriverExecutable`desired capability.
2021-10-10 08:01:25:359 [Chromedriver] Set chromedriver binary as: /usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver__mumu_2.42
2021-10-10 08:01:25:360 [Chromedriver] Killing any old chromedrivers, running: pkill -15 -f "/usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver__mumu_2.42.*--port=8000"
2021-10-10 08:01:25:428 [Chromedriver] No old chromedrivers seem to exist
2021-10-10 08:01:25:428 [Chromedriver] Cleaning any old adb forwarded port socket connections
2021-10-10 08:01:25:429 [ADB] List forwarding ports
2021-10-10 08:01:25:429 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 forward --list'
2021-10-10 08:01:25:441 [ADB] Removing forwarded port socket connection: 55916 
2021-10-10 08:01:25:441 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 forward --remove tcp:55916'
2021-10-10 08:01:25:456 [Chromedriver] Spawning chromedriver with: /usr/local/lib/node_modules/appium/node_modules/appium-chromedriver/chromedriver/mac/chromedriver__mumu_2.42 --url-base=wd/hub --port=8000 --adb-port=5037 --verbose
2021-10-10 08:01:25:477 [Chromedriver] Chromedriver version: '2.42.591059'
2021-10-10 08:01:25:478 [Chromedriver] Chromedriver v. 2.42.591059 does not fully support W3C protocol. Defaulting to MJSONWP
2021-10-10 08:01:25:479 [WD Proxy] Matched '/status' to command name 'getStatus'
2021-10-10 08:01:25:480 [WD Proxy] Proxying [GET /status] to [GET http://127.0.0.1:8000/wd/hub/status] with no body
2021-10-10 08:01:25:486 [WD Proxy] Got an unexpected response with status undefined: {"errno":-61,"code":"ECONNREFUSED","syscall":"connect","address":"127.0.0.1","port":8000}
2021-10-10 08:01:25:690 [WD Proxy] Matched '/status' to command name 'getStatus'
2021-10-10 08:01:25:691 [WD Proxy] Proxying [GET /status] to [GET http://127.0.0.1:8000/wd/hub/status] with no body
2021-10-10 08:01:25:704 [WD Proxy] Got response with status 200: {"sessionId":"","status":0,"value":{"build":{"version":"alpha"},"os":{"arch":"x86_64","name":"Mac OS X","version":"10.16.0"}}}
2021-10-10 08:01:25:705 [Chromedriver] Starting MJSONWP Chromedriver session with capabilities: {
2021-10-10 08:01:25:705 [Chromedriver]   "desiredCapabilities": {
2021-10-10 08:01:25:706 [Chromedriver]     "chromeOptions": {
2021-10-10 08:01:25:706 [Chromedriver]       "androidPackage": "io.appium.android.apis",
2021-10-10 08:01:25:707 [Chromedriver]       "androidUseRunningApp": true,
2021-10-10 08:01:25:708 [Chromedriver]       "androidDeviceSerial": "emulator-5554"
2021-10-10 08:01:25:708 [Chromedriver]     },
2021-10-10 08:01:25:708 [Chromedriver]     "loggingPrefs": {
2021-10-10 08:01:25:709 [Chromedriver]       "browser": "ALL"
2021-10-10 08:01:25:709 [Chromedriver]     }
2021-10-10 08:01:25:709 [Chromedriver]   }
2021-10-10 08:01:25:709 [Chromedriver] }
2021-10-10 08:01:25:710 [WD Proxy] Matched '/session' to command name 'createSession'
2021-10-10 08:01:25:711 [WD Proxy] Proxying [POST /session] to [POST http://127.0.0.1:8000/wd/hub/session] with body: {"desiredCapabilities":{"chromeOptions":{"androidPackage":"io.appium.android.apis","androidUseRunningApp":true,"androidDeviceSerial":"emulator-5554"},"loggingPrefs":{"browser":"ALL"}}}
2021-10-10 08:01:26:408 [Chromedriver] Webview version: 'Chrome/68.0.3440.70'
2021-10-10 08:01:26:542 [WD Proxy] Got response with status 200: {"sessionId":"ed7fb83742cae3d1847485e4a02ad001","status":0,"value":{"acceptInsecureCerts":false,"acceptSslCerts":false,"applicationCacheEnabled":false,"browserConnectionEnabled":false,"browserName":"chrome","chrome":{"chromedriverVersion":"2.42.591059 (a3d9684d10d61aa0c45f6723b327283be1ebaad8)"},"cssSelectorsEnabled":true,"databaseEnabled":false,"goog:chromeOptions":{"debuggerAddress":"localhost:57973"},"handlesAlerts":true,"hasTouchScreen":true,"javascriptEnabled":true,"locationContextEnabled":true,"mobileEmulationEnabled":false,"nativeEvents":true,"pageLoadStrategy":"normal","platform":"ANDROID","rotatable":false,"setWindowRect":false,"takesHeapSnapshot":true,"takesScreenshot":true,"unexpectedAlertBehaviour":"","version":"68.0.3440.70","webStorageEnabled":true}}
2021-10-10 08:01:26:543 [WD Proxy] Determined the downstream protocol as 'MJSONWP'
2021-10-10 08:01:26:543 [Chromedriver] Changed state to 'online'
2021-10-10 08:01:26:545 [W3C (b76bb00a)] Responding to client with driver.setContext() result: null
2021-10-10 08:01:26:547 [HTTP] <-- POST /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/context 200 1389 ms - 14
2021-10-10 08:01:26:548 [HTTP] 
2021-10-10 08:01:26:549 [HTTP] --> GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/source
2021-10-10 08:01:26:550 [HTTP] {}
2021-10-10 08:01:26:551 [W3C (b76bb00a)] Driver proxy active, passing request on via HTTP proxy
2021-10-10 08:01:26:553 [WD Proxy] Matched '/wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/source' to command name 'getPageSource'
2021-10-10 08:01:26:553 [WD Proxy] Proxying [GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/source] to [GET http://127.0.0.1:8000/wd/hub/session/ed7fb83742cae3d1847485e4a02ad001/source] with body: {}
2021-10-10 08:01:26:617 [WD Proxy] Got response with status 200: {"sessionId":"ed7fb83742cae3d1847485e4a02ad001","status":0,"value":"\u003C!DOCTYPE html>\u003Chtml xmlns="http://www.w3.org/1999/xhtml">\u003Chead>\n  \u003Ctitle>I am a page title\u003C/title>\n\u003C/head>\n\u003Cbody>\n  I am some other page content\n\n\n\u003Ciframe name="chromedriver dummy frame" src="about:blank">\u003C/iframe>\u003C/body>\u003C/html>"}
2021-10-10 08:01:26:618 [WD Proxy] Replacing sessionId ed7fb83742cae3d1847485e4a02ad001 with b76bb00a-43bc-4155-bd6a-ccaa3eb865b2
2021-10-10 08:01:26:620 [HTTP] <-- GET /wd/hub/session/b76bb00a-43bc-4155-bd6a-ccaa3eb865b2/source 200 70 ms - 305
2021-10-10 08:01:26:620 [HTTP] 
2021-10-10 08:02:26:630 [BaseDriver] Shutting down because we waited 60 seconds for a command
2021-10-10 08:02:26:631 [UiAutomator2] Deleting UiAutomator2 session
2021-10-10 08:02:26:632 [Appium] Closing session, cause was 'New Command Timeout of 60 seconds expired. Try customizing the timeout using the 'newCommandTimeout' desired capability'
2021-10-10 08:02:26:633 [Appium] Removing session b76bb00a-43bc-4155-bd6a-ccaa3eb865b2 from our master session list
2021-10-10 08:02:26:633 [AndroidDriver] Stopping chromedriver for context WEBVIEW_io.appium.android.apis
2021-10-10 08:02:26:635 [Chromedriver] Changed state to 'stopping'
2021-10-10 08:02:26:644 [WD Proxy] Proxying [DELETE /] to [DELETE http://127.0.0.1:8000/wd/hub/session/ed7fb83742cae3d1847485e4a02ad001] with no body
2021-10-10 08:02:26:648 [WD Proxy] Got response with status 200: {"sessionId":"ed7fb83742cae3d1847485e4a02ad001","status":0,"value":null}
2021-10-10 08:02:26:653 [Chromedriver] Changed state to 'stopped'
2021-10-10 08:02:26:654 [UiAutomator2] Deleting UiAutomator2 server session
2021-10-10 08:02:26:654 [WD Proxy] Matched '/' to command name 'deleteSession'
2021-10-10 08:02:26:654 [WD Proxy] Proxying [DELETE /] to [DELETE http://localhost:8200/wd/hub/session/1f7ceff4-e731-4b38-b43f-7fde4ed9268a] with no body
2021-10-10 08:02:26:749 [WD Proxy] Got response with status 200: {"sessionId":"1f7ceff4-e731-4b38-b43f-7fde4ed9268a","value":null}
2021-10-10 08:02:26:749 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 shell am force-stop io.appium.android.apis'
2021-10-10 08:02:27:454 [Instrumentation] .
2021-10-10 08:02:28:500 [Instrumentation] Time: 81.417
2021-10-10 08:02:28:501 [Instrumentation] 
2021-10-10 08:02:28:502 [Instrumentation] OK (1 test)
2021-10-10 08:02:28:523 [Logcat] Stopping logcat capture
2021-10-10 08:02:28:525 [ADB] Removing forwarded port socket connection: 8200 
2021-10-10 08:02:28:525 [ADB] Running '/Users/yujin/Library/Android/sdk/platform-tools/adb -P 5037 -s emulator-5554 forward --remove tcp:8200'
2021-10-10 08:02:28:762 [Instrumentation] The process has exited with code 0

WebView的内存泄漏怎么办?

1.不在xml中定义 Webview ,而是在需要的时候在Activity中创建,并且Context使用 getApplicationgContext()

    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 
                                         ViewGroup.LayoutParams.MATCH_PARENT);
    mWebView = new WebView(getApplicationContext());
    mWebView.setLayoutParams(params);
    mLayout.addView(mWebView);

2.在 Activity 销毁( WebView )的时候,先让 WebView 加载null内容,然后移除 WebView,再销毁 WebView,最后置空。

@Override
protected void onDestroy() {
    if (mWebView != null) {
        mWebView.loadDataWithBaseURL(null, "", "text/html", "utf-8", null);
        mWebView.clearHistory();
​
        ((ViewGroup) mWebView.getParent()).removeView(mWebView);
        mWebView.destroy();
        mWebView = null;
    }
    super.onDestroy();
}

WebView的使用漏洞 及其修复方式

WebView中,主要漏洞有三类:

1.任意代码执行漏洞
2.密码明文存储漏洞
3.域控制不严格漏洞

(一)任意代码执行漏洞

  • (1)addJavascriptInterface 接口引起远程代码执行漏洞
  1. 漏洞产生原因:
    js调用Android的其中一个方式是通过addJavascriptInterface接口进行对象映射:
​
    webView.addJavascriptInterface(new JSObject(), "myObj");
    // 参数1:Android的本地对象
    // 参数2:JS的对象
    // 通过对象映射将Android中的本地对象和JS中的对象进行关联,从而实现JS调用Android的对象和方法
    所以,漏洞产生原因是:当JS拿到android这个对象后,就可以调用这个Android对象中所有的方法,包括系统类(Java.lang.Runtime 类),
从而进行任意代码执行。(比如**我们可以执行命令获取本地设备的SD卡中的文件等信息从而造成信息泄露**)

具体获取系统类的描述:(结合 Java 反射机制)

  1. Android中的对象有一公共的方法:getClass() ;
  1. 该方法可以获取到当前类 类型Class
  1. 该类有一关键的方法: Class.forName;
  1. 该方法可以加载一个类(可加载 java.lang.Runtime 类)
  1. 而该类是可以执行本地命令的

以下是攻击的Js核心代码:

function execute(cmdArgs)  {  
    // 步骤1:遍历 window 对象
    // 目的是为了找到包含 getClass ()的对象
    // 因为Android映射的JS对象也在window中,所以肯定会遍历到
    for (var obj in window) {  
        if ("getClass" in window[obj]) {  
            // 步骤2:利用反射调用forName()得到Runtime类对象
            alert(obj);          
            return  window[obj].getClass().forName("java.lang.Runtime")  
            // 步骤3:以后,就可以调用静态方法来执行一些命令,比如访问文件的命令
            getMethod("getRuntime",null).invoke(null,null).exec(cmdArgs);  
            // 从执行命令后返回的输入流中得到字符串,有很严重暴露隐私的危险。
            // 如执行完访问文件的命令之后,就可以得到文件名的信息了。
        }  
    }  
} 

当一些 APP 通过扫描二维码打开一个外部网页时,攻击者就可以执行这段 js 代码进行漏洞攻击。在微信盛行、扫一扫行为普及的情况下,该漏洞的危险性非常大

2.解决方法

Android 4.2版本之后:Google 在Android 4.2 版本中规定对被调用的函数以 @JavascriptInterface进行注解从而避免漏洞攻击

Android 4.2版本之前:采用拦截prompt()进行漏洞修复。 具体步骤如下:

1.继承 WebView ,重写 addJavascriptInterface 方法,然后在内部自己维护一个对象映射关系的 Map ( 将需要添加的 JS 接口放入该Map中 )
2.每次当 WebView 加载页面前加载一段本地的 JS 代码,原理是:
    1) 让JS调用一Javascript方法:该方法是通过调用prompt()把JS中的信息(含特定标识,方法名称等)传递到Android端;
    2) 在Android的onJsPrompt()中 ,解析传递过来的信息,再通过反射机制调用Java对象的方法,这样实现安全的JS调用Android代码。
关于Android返回给JS的值:可通过prompt()把Java中方法的处理结果返回到Js中

具体需要加载的JS代码如下:

 javascript:(function JsAddJavascriptInterface_(){  
    // window.jsInterface 表示在window上声明了一个Js对象
    // jsInterface = 注册的对象名
    // 它注册了两个方法,onButtonClick(arg0)和onImageClick(arg0, arg1, arg2)
    // 如果有返回值,就添加上return
    if (typeof(window.jsInterface)!='undefined') {      
        console.log('window.jsInterface_js_interface_name is exist!!');}   
    else {  
        window.jsInterface = {     
            // 声明方法形式:方法名: function(参数)
            onButtonClick:function(arg0) {   
            // prompt()返回约定的字符串
            // 该字符串可自己定义
            // 包含特定的标识符MyApp和 JSON 字符串(方法名,参数,对象名等)    
                return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onButtonClick',args:[arg0]}));  
            },  
            onImageClick:function(arg0,arg1,arg2) {   
                return prompt('MyApp:'+JSON.stringify({obj:'jsInterface',func:'onImageClick',
args:[arg0,arg1,arg2]}));  
            },  
        };  
    }  
}  
)()
// 当JS调用 onButtonClick() 或 onImageClick() 时,就会回调到Android中的 onJsPrompt ()
// 我们解析出方法名,参数,对象名
// 再通过反射机制调用Java对象的方法

关于采用拦截prompt()进行漏洞修复需要注意的两点细节:

细节1:加载上述JS代码的时机

由于当 WebView 跳转到下一个页面时,之前加载的 JS 可能已经失效,所以,通常需要在以下方法中加载js:
    onLoadResource();
    doUpdateVisitedHistory();
    onPageStarted();
    onPageFinished();
    onReceivedTitle();
    onProgressChanged();

细节2:需要过滤掉 Object 类的方法

由于最终是通过反射得到Android指定对象的方法,所以同时也会得到基类的其他方法(最顶层的基类是 Object类)
为了不把 getClass()等方法注入到 JS 中,我们需要把 Object 的共有方法过滤掉,需要过滤的方法列表如下:
    getClass()
    hashCode()
    notify()
    notifyAl()
    equals()
    toString()
    wait()
  • (2)searchBoxJavaBridge_接口引起远程代码执行漏洞
  1. 产生原因
1) 在Android 3.0以下,Android系统会默认通过searchBoxJavaBridge_的Js接口给 WebView 添加一个JS映射对象:
searchBoxJavaBridge_对象
2) 该接口可能被利用,实现远程任意代码。
  1. 解决方法
删除searchBoxJavaBridge_接口
// 通过调用该方法删除接口removeJavascriptInterface();
  • (3)accessibility和 accessibilityTraversal接口引起远程代码执行漏洞
  1. 产生原因
1) 在Android 3.0以下,Android系统会默认通过searchBoxJavaBridge_的Js接口给 WebView 添加一个JS映射对象:
searchBoxJavaBridge_对象
2) 该接口可能被利用,实现远程任意代码。
  1. 解决方法
删除searchBoxJavaBridge_接口
// 通过调用该方法删除接口removeJavascriptInterface();

(二)密码明文存储漏洞

  • (1)问题分析
//WebView默认开启密码保存功能 :
mWebView.setSavePassword(true)
开启后,在用户输入密码时,会弹出提示框:询问用户是否保存密码;
如果选择”是”,密码会被明文保到 /data/data/com.package.name/databases/webview.db 中,这样就有被盗取密码的危险
  • (2)解决方案
//关闭密码保存提醒
WebSettings.setSavePassword(false) 

(三)域控制不严格漏洞

先看Android里的WebViewActivity.java:

public class WebViewActivity extends Activity {
    private WebView webView;
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_webview);
        webView = (WebView) findViewById(R.id.webView);
​
        //webView.getSettings().setAllowFileAccess(false);                    (1)
        //webView.getSettings().setAllowFileAccessFromFileURLs(true);         (2)
        //webView.getSettings().setAllowUniversalAccessFromFileURLs(true);    (3)
        Intent i = getIntent();
        String url = i.getData().toString(); //url = file:///data/local/tmp/attack.html 
        webView.loadUrl(url);
    }
 }
​
/**Mainifest.xml**/
// 将该 WebViewActivity 在Mainifest.xml设置exported属性
// 表示:当前Activity是否可以被另一个Application的组件启动
android:exported="true"
  • (1)问题分析

上述demo中:即 A 应用可以通过 B 应用导出的 Activity 让 B 应用加载一个恶意的 file 协议的 url,从而可以获取 B 应用的内部私有文件,从而带来数据泄露威胁 具体:当其他应用启动此 Activity 时, intent 中的 data 直接被当作 url 来加载(假定传进来的 url 为 file:///data/local/tmp/attack.html ),其他 APP 通过使用显式 ComponentName 或者其他类似方式就可以很轻松的启动该 WebViewActivity 并加载恶意url。 下面我们着重分析WebView中getSettings类的方法对 WebView 安全性的影响:

setAllowFileAccess()
setAllowFileAccessFromFileURLs()
setAllowUniversalAccessFromFileURLs()
  • (2) setAllowFileAccess()
// 设置是否允许 WebView 使用 File 协议,默认设置为true,即允许在 File 域下执行任意 JavaScript 代码
webView.getSettings().setAllowFileAccess(true);     

但是同时也限制了 WebView 的功能,使其不能加载本地的 html 文件,( 移动版的 Chrome 默认禁止加载 file 协议的文件 )

解决方案:

1) 对于不需要使用 file 协议的应用,禁用 file 协议;
  setAllowFileAccess(false); 
  
2) 对于需要使用 file 协议的应用,禁止 file 协议加载 JavaScript。
  setAllowFileAccess(true); 
  // 禁止 file 协议加载 JavaScript
  if (url.startsWith("file://") {
      setJavaScriptEnabled(false);
  } else {
      setJavaScriptEnabled(true);
  }
  • (3)setAllowFileAccessFromFileURLs()

设置是否允许通过 file url 加载的 Js代码读取其他的本地文件 , 在Android 4.1前默认允许 , 在Android 4.1后默认禁止

webView.getSettings().setAllowFileAccessFromFileURLs(true);

当AllowFileAccessFromFileURLs()设置为 true 时,攻击者的JS代码为 ( 通过该代码可成功读取 /etc/hosts 的内容数据 ) :

<script>
    function loadXMLDoc(){
        var arm = "file:///etc/hosts";
        var xmlhttp;
        if (window.XMLHttpRequest){
            xmlhttp=new XMLHttpRequest();
        }
        xmlhttp.onreadystatechange=function(){
            //alert("status is"+xmlhttp.status);
            if (xmlhttp.readyState==4){
                  console.log(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET",arm);
        xmlhttp.send(null);
    }
    loadXMLDoc();
</script>

解决方案:

设置setAllowFileAccessFromFileURLs(false);

当设置成为 false 时,上述JS的攻击代码执行会导致错误,表示浏览器禁止从 file url 中的 JavaScript读取其它本地文件。

  • (4) setAllowUniversalAccessFromFileURLs()

设置是否允许通过 file url 加载的 Javascript 可以访问其他的源(包括http、https等源),在Android 4.1前默认允许(setAllowFileAccessFromFileURLs()不起作用),在Android 4.1后默认禁止

webView.getSettings().setAllowUniversalAccessFromFileURLs(true);

当AllowFileAccessFromFileURLs()被设置成true时,攻击者的JS代码是:

// 通过该代码可成功读取 http://www.so.com 的内容
<script>
    function loadXMLDoc(){
        var arm = "http://www.so.com";
        var xmlhttp;
        if (window.XMLHttpRequest){
            xmlhttp=new XMLHttpRequest();
        }
        xmlhttp.onreadystatechange=function(){
            //alert("status is"+xmlhttp.status);
            if (xmlhttp.readyState==4){
                 console.log(xmlhttp.responseText);
            }
        }
        xmlhttp.open("GET",arm);
        xmlhttp.send(null);
    }
    loadXMLDoc();
</script>

解决方案:

设置setAllowUniversalAccessFromFileURLs(false);
  • (5) setJavaScriptEnabled()

设置是否允许 WebView 使用 JavaScript(默认是不允许),但很多应用(包括移动浏览器)为了让 WebView 执行 http 协议中的 JavaScript,都会主动设置为true,不区别对待是非常危险的,如下代码所示:

webView.getSettings().setJavaScriptEnabled(true);  

即使把setAllowFileAccessFromFileURLs()和setAllowUniversalAccessFromFileURLs()都设置为 false,通过 file URL 加载的 javascript仍然有方法访问其他的本地文件:符号链接跨源攻击(前提是允许 file URL 执行 javascript,即webView.getSettings().setJavaScriptEnabled(true);)

原因分析:

这一攻击能奏效的原因是:通过 javascript 的延时执行和将当前文件替换成指向其它文件的软链接就可以读取到被符号链接所指的文件。

具体攻击步骤:(在该命令执行前 xx.html 是不存在的;执行完这条命令之后,就生成了这个文件,并且将 Cookie 文件链接到了 xx.html 上。) 1. 把恶意的 js 代码输出到攻击应用的目录下,随机命名为 xx.html,修改该目录的权限; 2. 修改后休眠 1s,让文件操作完成; 3. 完成后通过系统的 Chrome 应用去打开该 xx.html 文件 4. 等待 4s 让 Chrome 加载完成该 html,最后将该 html 删除,并且使用 ln -s 命令为 Chrome 的 Cookie 文件创建软连接, 于是就可通过链接来访问 Chrome 的 Cookie

注意事项:Google 没有进行修复,只是让Chrome 最新版本默认禁用 file 协议,所以这一漏洞在最新版的 Chrome 中并不存在。   但是,在日常大量使用 WebView 的App和浏览器,都有可能受到此漏洞的影响。通过利用此漏洞,容易出现数据泄露的危险   如果是 file 协议,禁用 javascript 可以很大程度上减小跨源漏洞对 WebView 的威胁。   但并不能完全杜绝跨源文件泄露。例:应用实现了下载功能,对于无法加载的页面,会自动下载到 sd 卡中;由于 sd 卡中的文件所有应用都可以访问,于是可以通过构造一个 file URL 指向被攻击应用的私有文件,然后用此 URL 启动被攻击应用的 WebActivity,这样由于该 WebActivity 无法加载该文件,就会将该文件下载到 sd 卡下面,然后就可以从 sd 卡上读取这个文件了

文末

  • (6) 最终解决方案

1)对于不需要使用 file 协议的应用,禁用 file 协议;

// 禁用 file 协议;
webView.setAllowFileAccess(false); 
webView.setAllowFileAccessFromFileURLs(false);
webView.setAllowUniversalAccessFromFileURLs(false);

2)对于需要使用 file 协议的应用,禁止 file 协议加载 JavaScript。

// 需要使用 file 协议
webView.setAllowFileAccess(true); 
webView.setAllowFileAccessFromFileURLs(false);
webView. setAllowUniversalAccessFromFileURLs(false);
​
// 禁止 file 协议加载 JavaScript
if (url.startsWith("file://") {
    webView.setJavaScriptEnabled(false);
} else {
    webView.setJavaScriptEnabled(true);
}

猜你喜欢

转载自blog.csdn.net/m0_62167422/article/details/129391515