Google Android – WifiNative::setHotlist Stack Overflow

  • 作者: Google Security Research
    日期: 2016-12-20
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/40945/
  • 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 <-- stpx28, x27, [sp, #-0x60]!
    *X5 0x709c1f07b0 (art::gJniNativeInterface) <-- 0x0
    *X6 0x709bf27034 <-- cbzx2, #0x709bf27040 /* u'b' */
    *X7 0x284801ff284800ff
    *X8 0xc01d0142c01d0229
    *X9 0x1
    *X100xc01d0142c01d0141
    *X110x7082dff4e8 <-- 0x41013fb31dc0
     X120x0
    *X130x0
    *X140x0
    *X150x33511e057221be
    *X160x709f0035a0 (pthread_getspecific@got.plt) --> 0x709efaad5c (pthread_getspecific) <-- movz w8, #0x8000, lsl #16
    *X170x709efaad5c (pthread_getspecific) <-- movz w8, #0x8000, lsl #16
    *X180x0
    *X190x707882c3e0 <-- u'c0:1d:b3:3f:01:...'
    *X200x7082dfe0a0 --> 0x70833c1470 --> 0x7083381c0c (android::JNIObject<_jobject*>::~JNIObject()) <-- adrp x2, #0x70833c2000
    *X210x7082dfe0b8 --> 0x70833c1490 --> 0x7083381c70 (android::JNIObject<_jstring*>::~JNIObject()) <-- adrp x2, #0x70833c2000
    *X220x7082dfe078 <-- 0x0
    *X230xb1da807287fa8cf
    *X240x709f00e86c (je_tsd_tsd) <-- 0xa880000000
    *X250x7082dfe8d8 <-- u'c0:1d:b3:3f:1:4...'
    *X260x200011
    *X270x7082dfe0d0 <-- 0x100000000001
    *X280x707882c3e0 <-- u'c0:1d:b3:3f:01:...'
    *SP 0x70815310f0 <-- 0x0
    *PC 0x709efaada8 (pthread_getspecific+76) <-- ldrx10, [x10, #0xe0]
    [------------------------------------------------------------------------CODE------------------------------------------------------------------------]
     => 0x709efaada8L <pthread_getspecific+76>ldrx10, [x10, #0xe0]
    0x709efaadacL <pthread_getspecific+80>cmpx10, x9
    0x709efaadb0L <pthread_getspecific+84>b.ne #pthread_getspecific+56 <0x709efaad94>
    ...
    0x709efaad94L <pthread_getspecific+56>movx0, xzr
    0x709efaad98L <pthread_getspecific+60>strxzr, [x8]
    0x709efaad9cL <pthread_getspecific+64>ret
    
    0x709efaada0L <pthread_getspecific+68>addx10, x10, x8, lsl #4
    0x709efaada4L <pthread_getspecific+72>addx8, x10, #0xe8
     => 0x709efaada8L <pthread_getspecific+76>ldrx10, [x10, #0xe0]
    0x709efaadacL <pthread_getspecific+80>cmpx10, x9
    0x709efaadb0L <pthread_getspecific+84>b.ne #pthread_getspecific+56 <0x709efaad94>
    [------------------------------------------------------------------------CODE------------------------------------------------------------------------]
    155	in bionic/libc/bionic/pthread_key.cpp
    [-----------------------------------------------------------------------STACK------------------------------------------------------------------------]
    00:0000| sp0x70815310f0 <-- 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
    #0pthread_getspecific (key=<optimized out>) at bionic/libc/bionic/pthread_key.cpp:160
    #10x000000709efd2394 in je_tsd_wrapper_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
    #2je_tsd_get () at external/jemalloc/include/jemalloc/internal/tsd.h:609
    #3je_tsd_fetch () at external/jemalloc/include/jemalloc/internal/tsd.h:614
    #4je_free (ptr=0x707882c3e0) at external/jemalloc/src/jemalloc.c:1932
    #50x0000007083387d10 in _JNIEnv::ReleaseStringUTFChars (utf=0x707882c3e0 "c0:1d:b3:3f:01:"..., string=0x200011, this=0x7091fd2b00) at libnativehelper/include/nativehelper/jni.h:851
    #6ScopedUtfChars::~ScopedUtfChars (this=<synthetic pointer>, __in_chrg=<optimized out>) at libnativehelper/include/nativehelper/ScopedUtfChars.h:45
    #7android::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
    #80x000000709b1a084c 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