Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize the document of Quark Script CWE-312 and CWE-798 #48

Open
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

JerryTasi
Copy link
Contributor

Detect CWE-312 in Android Application

This scenario seeks to find cleartext storage of sensitive data in the APK file.

CWE-312: Cleartext Storage of Sensitive Information

We analyze the definition of CWE-312 and identify its characteristics.

See CWE-312 for more details.

image

Code of CWE-312 in ovaa.apk

We use the ovaa.apk sample to explain the vulnerability code of CWE-312.

image

CWE-312 Detection Process Using Quark Script API

Let’s use the above APIs to show how the Quark script finds this vulnerability.

We have designed a Frida script agent.js to hook a specified method and get the arguments when the method is called. It can be found in quark-engine/quark/script/frida.

To begin with, we hook the method putString to catch its arguments. Then, we check if sensitive information like email or password is passed. Finally, we use checkClearText imported from Ares to check if the arguments are cleartext. If both YES, CWE-312 vulnerability might be caused.

image

Quark Script: CWE-312.py

image

from quark.script.frida import runFridaHook
from quark.script.ares import checkClearText

APP_PACKAGE_NAME = "oversecured.ovaa"

TARGET_METHOD = "android.app." "SharedPreferencesImpl$EditorImpl." "putString"

METHOD_PARAM_TYPE = "java.lang.String," "java.lang.String"

fridaResult = runFridaHook(
    APP_PACKAGE_NAME, TARGET_METHOD, METHOD_PARAM_TYPE, secondToWait=10
)

for putString in fridaResult.behaviorOccurList:

    firstParam = putString.firstAPI.getArguments()
    secondParam = putString.secondAPI.getArguments()

    if firstParam in ["email", "password"] and secondParam == checkClearText(
        secondParam
    ):

        print(
            "The CWE-312 vulnerability is found. "
            f'The cleartext is "{secondParam}"'
        )

Frida Script: agent.js

// -*- coding: utf-8 -*-
// This file is part of Quark-Engine - https://github.com/quark-engine/quark-engine
// See the file 'LICENSE' for copying permission.

/*global Java, send, rpc*/
function replaceMethodImplementation(targetMethod, classAndMethodName, methodParamTypes, returnType) {
    targetMethod.implementation = function () {
        let callEvent = {
            "type": "CallCaptured",
            "identifier": [classAndMethodName, methodParamTypes, returnType],
            "paramValues": []
        };

        for (const arg of arguments) {
            callEvent["paramValues"].push((arg || "(none)").toString());
        }

        send(JSON.stringify(callEvent));
        return targetMethod.apply(this, arguments);
    };
}

function watchMethodCall(classAndMethodName, methodParamTypes) {
    if (classAndMethodName == null || methodParamTypes == null) {
        return;
    }

    const indexOfLastSeparator = classAndMethodName.lastIndexOf(".");
    const classNamePattern = classAndMethodName.substring(0, indexOfLastSeparator);
    const methodNamePattern = classAndMethodName.substring(indexOfLastSeparator + 1);

    Java.perform(() => {
        const classOfTargetMethod = Java.use(classNamePattern);
        const possibleMethods = classOfTargetMethod[`${methodNamePattern}`];

        if (typeof possibleMethods === "undefined") {
            const failedToWatchEvent = {
                "type": "FailedToWatch",
                "identifier": [classAndMethodName, methodParamTypes]
            };

            send(JSON.stringify(failedToWatchEvent));
            return;
        }

        possibleMethods.overloads.filter((possibleMethod) => {
            const paramTypesOfPossibleMethod = possibleMethod.argumentTypes.map((argument) => argument.className);
            return paramTypesOfPossibleMethod.join(",") === methodParamTypes;
        }).forEach((matchedMethod) => {
            const retType = matchedMethod.returnType.name;
            replaceMethodImplementation(matchedMethod, classAndMethodName, methodParamTypes, retType);
        }
        );

    });
}

rpc.exports["watchMethodCall"] = (classAndMethodName, methodParamTypes) => watchMethodCall(classAndMethodName, methodParamTypes);

Quark Script Result

$ python3 CWE-312.py
The CWE-312 vulnerability is found. The cleartext is "[email protected]"
The CWE-312 vulnerability is found. The cleartext is "password"

Detect CWE-798 in Android Application

This scenario seeks to find hard-coded credentials in the APK file.

CWE-798: Use of Hard-coded Credentials

We analyze the definition of CWE-798 and identify its characteristics.

See CWE-798 for more details.

image

Code of CWE-798 in ovaa.apk

We use the ovaa.apk sample to explain the vulnerability code of CWE-798.

image

CWE-798 Detection Process Using Quark Script API

image

Let’s use the above APIs to show how the Quark script finds this vulnerability.

First, we design a detection rule findSecretKeySpec.json to spot on behavior using the constructor SecretKeySpec. Second, we get all the parameter values from this constructor. Then, we parse the AES key from the parameter values. Finally, we check if the AES key is hardcoded in the APK file. If the answer is YES, BINGO!!! We find hard-coded credentials in the APK file.

Quark Script: CWE-798.py

image

import re
from quark.script import runQuarkAnalysis, Rule

SAMPLE_PATH = "ovaa.apk"
RULE_PATH = "findSecretKeySpec.json"

ruleInstance = Rule(RULE_PATH)
quarkResult = runQuarkAnalysis(SAMPLE_PATH, ruleInstance)

for secretKeySpec in quarkResult.behaviorOccurList:

    firstParam = secretKeySpec.secondAPI.getArguments()[1]
    secondParam = secretKeySpec.secondAPI.getArguments()[2]

    if secondParam == "AES":
        AESKey = re.findall(r"\((.*?)\)", firstParam)[1]

        if quarkResult.isHardcoded(AESKey):
            print(f"Found hard-coded {secondParam} key {AESKey}")

Quark Rule: findSecretKeySpec.json

image

{
    "crime": "Detect APK using SecretKeySpec.",
    "permission": [],
    "api": [
        {
            "descriptor": "()[B",
            "class": "Ljava/lang/String;",
            "method": "getBytes"
        },
        {
            "descriptor": "([BLjava/lang/String;)V",
            "class": "Ljavax/crypto/spec/SecretKeySpec;",
            "method": "<init>"
        }
    ],
    "score": 1,
    "label": []
}

Quark Script Result

$ python3 CWE-798.py
Found hard-coded AES key 49u5gh249gh24985ghf429gh4ch8f23f

@zinwang zinwang requested review from zinwang and removed request for zinwang December 13, 2024 10:29
@haeter525 haeter525 self-requested a review December 16, 2024 08:30
@haeter525 haeter525 self-assigned this Dec 16, 2024
Copy link
Member

@haeter525 haeter525 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could remove CWE-312/agent.js since it's an empty file. What do you think?

@JerryTasi
Copy link
Contributor Author

That sounds great.

Copy link
Member

@haeter525 haeter525 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thank @JerryTasi.

JerryTasi and others added 5 commits December 17, 2024 15:17
mv -vn $GITHUB_WORKSPACE/CWE-*/*.js test_ground/
runs-on: ubuntu-22.04
mv -vn $GITHUB_WORKSPACE/CWE-*/*.js test_ground/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants