Jump to content
  • Entries

    16114
  • Comments

    7952
  • Views

    86384057

Contributors to this blog

  • HireHackking 16114

About this blog

Hacking techniques include penetration testing, network security, reverse cracking, malware analysis, vulnerability exploitation, encryption cracking, social engineering, etc., used to identify and fix security flaws in systems.

Source: https://bugs.chromium.org/p/project-zero/issues/detail?id=958

The following code in frameworks/opt/net/wifi/service/jni/com_android_server_wifi_WifiNative.cpp doesn't validate the parameter params.num_bssid, and then copies that number of elements into a stack-allocated wifi_bssid_hotlist_params structure. I don't think this can be reached from an untrusted_app context; but it can be reached from a context with system_api_service access; so a compromised platform app or one of several lower privileged system services (bluetooth, nfc etc.).

static jboolean android_net_wifi_setHotlist(
        JNIEnv *env, jclass cls, jint iface, jint id, jobject ap)  {

    JNIHelper helper(env);
    wifi_interface_handle handle = getIfaceHandle(helper, cls, iface);
    ALOGD("setting hotlist on interface[%d] = %p", iface, handle);

    wifi_bssid_hotlist_params params;
    memset(&params, 0, sizeof(params));

    params.lost_ap_sample_size = helper.getIntField(ap, "apLostThreshold");

    JNIObject<jobjectArray> array = helper.getArrayField(
            ap, "bssidInfos", "[Landroid/net/wifi/WifiScanner$BssidInfo;");
    params.num_bssid = helper.getArrayLength(array);

    if (params.num_bssid == 0) {
        ALOGE("setHotlist array length was 0");
        return false;
    }

    for (int i = 0; i < params.num_bssid; i++) { // <--- no validation on num_bssid
        JNIObject<jobject> objAp = helper.getObjectArrayElement(array, i);

        JNIObject<jstring> macAddrString = helper.getStringField(objAp, "bssid");
        if (macAddrString == NULL) {
            ALOGE("Error getting bssid field");
            return false;
        }

        ScopedUtfChars chars(env, macAddrString);
        const char *bssid = chars.c_str();
        if (bssid == NULL) {
            ALOGE("Error getting bssid");
            return false;
        }
        parseMacAddress(bssid, params.ap[i].bssid); // <--- params.ap has 128 elements.

        mac_addr addr;
        memcpy(addr, params.ap[i].bssid, sizeof(mac_addr));

        char bssidOut[32];
        snprintf(bssidOut, sizeof(bssidOut), "%0x:%0x:%0x:%0x:%0x:%0x", addr[0],
                 addr[1], addr[2], addr[3], addr[4], addr[5]);

        ALOGD("Added bssid %s", bssidOut);

        params.ap[i].low = helper.getIntField(objAp, "low");
        params.ap[i].high = helper.getIntField(objAp, "high");
    }

See attached for a POC which causes a crash before the function with the corrupted stack frame returns and checks the stack cookie.

LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA
[---------------------------------------------------------------------REGISTERS----------------------------------------------------------------------]
*X0   0x80000000 <-- 0x0
*X1   0x0
*X2   0x707882c3e0 <-- u'c0:1d:b3:3f:01:...'
*X3   0x3
*X4   0x709bf05fc0 <-- stp    x28, x27, [sp, #-0x60]!
*X5   0x709c1f07b0 (art::gJniNativeInterface) <-- 0x0
*X6   0x709bf27034 <-- cbz    x2, #0x709bf27040 /* u'b' */
*X7   0x284801ff284800ff
*X8   0xc01d0142c01d0229
*X9   0x1
*X10  0xc01d0142c01d0141
*X11  0x7082dff4e8 <-- 0x41013fb31dc0
 X12  0x0
*X13  0x0
*X14  0x0
*X15  0x33511e057221be
*X16  0x709f0035a0 (pthread_getspecific@got.plt) --> 0x709efaad5c (pthread_getspecific) <-- movz   w8, #0x8000, lsl #16
*X17  0x709efaad5c (pthread_getspecific) <-- movz   w8, #0x8000, lsl #16
*X18  0x0
*X19  0x707882c3e0 <-- u'c0:1d:b3:3f:01:...'
*X20  0x7082dfe0a0 --> 0x70833c1470 --> 0x7083381c0c (android::JNIObject<_jobject*>::~JNIObject()) <-- adrp   x2, #0x70833c2000
*X21  0x7082dfe0b8 --> 0x70833c1490 --> 0x7083381c70 (android::JNIObject<_jstring*>::~JNIObject()) <-- adrp   x2, #0x70833c2000
*X22  0x7082dfe078 <-- 0x0
*X23  0xb1da807287fa8cf
*X24  0x709f00e86c (je_tsd_tsd) <-- 0xa880000000
*X25  0x7082dfe8d8 <-- u'c0:1d:b3:3f:1:4...'
*X26  0x200011
*X27  0x7082dfe0d0 <-- 0x100000000001
*X28  0x707882c3e0 <-- u'c0:1d:b3:3f:01:...'
*SP   0x70815310f0 <-- 0x0
*PC   0x709efaada8 (pthread_getspecific+76) <-- ldr    x10, [x10, #0xe0]
[------------------------------------------------------------------------CODE------------------------------------------------------------------------]
 => 0x709efaada8L <pthread_getspecific+76>    ldr    x10, [x10, #0xe0]
    0x709efaadacL <pthread_getspecific+80>    cmp    x10, x9
    0x709efaadb0L <pthread_getspecific+84>    b.ne   #pthread_getspecific+56       <0x709efaad94>
...
    0x709efaad94L <pthread_getspecific+56>    mov    x0, xzr
    0x709efaad98L <pthread_getspecific+60>    str    xzr, [x8]
    0x709efaad9cL <pthread_getspecific+64>    ret    

    0x709efaada0L <pthread_getspecific+68>    add    x10, x10, x8, lsl #4
    0x709efaada4L <pthread_getspecific+72>    add    x8, x10, #0xe8
 => 0x709efaada8L <pthread_getspecific+76>    ldr    x10, [x10, #0xe0]
    0x709efaadacL <pthread_getspecific+80>    cmp    x10, x9
    0x709efaadb0L <pthread_getspecific+84>    b.ne   #pthread_getspecific+56       <0x709efaad94>
[------------------------------------------------------------------------CODE------------------------------------------------------------------------]
155	in bionic/libc/bionic/pthread_key.cpp
[-----------------------------------------------------------------------STACK------------------------------------------------------------------------]
00:0000| sp  0x70815310f0 <-- 0x0
...
04:0020|     0x7081531110 --> 0x3f800000 <-- 0x0
05:0028|     0x7081531118 <-- 0x0
...
[---------------------------------------------------------------------BACKTRACE----------------------------------------------------------------------]
>  f 0       709efaada8 pthread_getspecific+76
   f 1       709efd2394 je_free+68
   f 2       709efd2394 je_free+68
   f 3       709efd2394 je_free+68
   f 4       709efd2394 je_free+68
   f 5       7083387d10
   f 6       7083387d10
   f 7       7083387d10
Program received signal SIGSEGV (fault address 0x1d0142c01d0221)
pwndbg> bt
#0  pthread_getspecific (key=<optimized out>) at bionic/libc/bionic/pthread_key.cpp:160
#1  0x000000709efd2394 in je_tsd_wrapper_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
#2  je_tsd_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
#3  je_tsd_fetch () at external/jemalloc/include/jemalloc/internal/tsd.h:614
#4  je_free (ptr=0x707882c3e0) at external/jemalloc/src/jemalloc.c:1932
#5  0x0000007083387d10 in _JNIEnv::ReleaseStringUTFChars (utf=0x707882c3e0 "c0:1d:b3:3f:01:"..., string=0x200011, this=0x7091fd2b00) at libnativehelper/include/nativehelper/jni.h:851
#6  ScopedUtfChars::~ScopedUtfChars (this=<synthetic pointer>, __in_chrg=<optimized out>) at libnativehelper/include/nativehelper/ScopedUtfChars.h:45
#7  android::android_net_wifi_setHotlist (env=0x7091fd2b00, cls=<optimized out>, iface=<optimized out>, id=0x690a3633, ap=<optimized out>) at frameworks/opt/net/wifi/service/jni/com_android_server_wifi_WifiNative.cpp:799
#8  0x000000709b1a084c in ?? ()

Fixed in https://source.android.com/security/bulletin/2016-12-01.html


Proof of Concept:
https://gitlab.com/exploit-database/exploitdb-bin-sploits/-/raw/main/bin-sploits/40945.zip