Shopify pays $15,250 bug bounty for a Christmas Eve vulnerability

This one had the potential for a holiday nightmare: A security researcher reported a critical vulnerability to the Canadian e-commerce company Shopify late on Christmas Eve last year. Instead, Shopify fixed the bug within 12 hours and paid out $15,250 to a bug bounty hunter who goes by the handle Cache-Money. The bug potentially allowed an attacker to bypass Shopify’s email verification process and ultimately gain access to an online store they didn’t own. For a platform whose entire reason to exist is to host stores and protect retailers, any threat of hijackings is a big deal. “We tracked down the bug to a race condition in the logic for changing and verifying email addresses,” Shopify’s security team explained on the platform HackerOne, which handles Shopify’s bounty program, including communication and payment with researchers. A race condition is a situation in programming where the result depends on a certain sequence of events. Vulnerabilities can result if a […]

The post Shopify pays $15,250 bug bounty for a Christmas Eve vulnerability appeared first on Cyberscoop.

Continue reading Shopify pays $15,250 bug bounty for a Christmas Eve vulnerability

Are memcpy() based race conditions exploitable?

Let’s say I have the following pseudocode in the trusted part of a sandbox which prevent untrusted code calling mprotect() and mmap() and ptrace() directly (mutext isn’t in accessible memory)

//src and dest are user controlled but must be valid.
TrustedPart_for_safe_jit(mutext, uint8_t *src,uint8_t *dest, uint32_t size) // in the current case, *dest targets a PROT_NONE memory region
{
    MutexLock(mutext);
    ValidateOpcodes(src,size); // uses calls to mmap on size internally. Contains many loops : this is the longest part.
    unwriteprotect(dest,size); // calls many sandbox’s internal functions

    SafeMemcpy(src,dest,size); // THIS IS the function which contains the race condition

    asm("mfence");
    unEXECprotect(dest,size); // involve write protecting as well as allowing reading
    MutexUnlock(mutext);
}

SafeMemcpy(uint8_t *src,uint8_t *dest, uint32_t size) // the data to be copied cannot exceed 128Mb
{
    if(!CheckUserTarget(dest,size) {
        uint8_t *src_ptr=src;
        uint8_t *dest_ptr=dest;
        uint8_t *end_ptr=des+size;
        while (dest_ptr < end_ptr) { // that loop should execute very fast
            *(uint32_t *) dest_ptr = *(uint32_t *) src_ptr;
            dest_ptr += 4;
            src_ptr += 4;
        }
    }
}

That part is responsible for allowing untrusted code to use ᴊɪᴛ compilation.
The point is untrusted thread aren’t suspended.

As you know, when 2 threads use memcpy() with the same destination, they generate random data. In that case, such data could potentially contains instructions like int 0x80.

Things I thought so far :

  • Write data to a file and read it with the read system call through the sandbox. If the memory is still write protected the program doesn’t crash. This would involve looping and even if the data to be copied can be 128Mb large I’m not sure it would works because of syscall overhead.
    An Alternative would be to create code several times and try reading with several timing, but I have no idea on how to select the initial timing window.
  • Use futex… But I couldn’t found if futex can be used to check the value of non allocated memory. I’m also unsure if the thread could wake up before memory become write protected.

So, is it possible to plan for memcpy race conditions ?

Continue reading Are memcpy() based race conditions exploitable?

Are memcpy() based race conditions exploitable for causing remote code execution?

Let’s say I have the following pseudocode in the trusted part of a sandbox which prevent untrusted code calling mprotect() and mmap() and ptrace() directly (mutext isn’t accessible from sandboxed memory)

//src and dest are user controlled but must be valid.
TrustedPart_for_safe_jit(void * mutext, uint8_t *src,uint8_t *dest, uint32_t size) // in the current case, *dest targets a PROT_NONE memory region
{
    MutexLock(mutext);
    ValidateOpcodesOrCrash(src,size); // uses calls to mmap on size internally. Contains many loops : this is the longest part.
    unwriteprotect(dest,size); // calls many sandbox’s internal functions

    SafeMemcpy(src,dest,size); // THIS IS the function which contains the race condition

    asm("mfence");
    unEXECprotect(dest,size); // involve write protecting as well as allowing reading
    MutexUnlock(mutext);
}

SafeMemcpy(uint8_t *src,uint8_t *dest, uint32_t size) // the data to be copied cannot exceed 128Mb
{
    if(!CheckUserTarget(dest,size) {
        uint8_t *src_ptr=src;
        uint8_t *dest_ptr=dest;
        uint8_t *end_ptr=des+size;
        while (dest_ptr < end_ptr) { // that loop should execute very fast
            *(uint32_t *) dest_ptr = *(uint32_t *) src_ptr;
            dest_ptr += 4;
            src_ptr += 4;
        }
    }
}

That part is responsible for allowing untrusted code to use ᴊɪᴛ compilation.
The point is untrusted thread aren’t suspended.

As you know, when 2 threads use memcpy() with the same destination, they generate random data. In that case, such data could potentially contains instructions like int 0x80, thus allowing to escape the sandbox.

Things I thought to so far :

  • Write data to a file and read it with the read system call through the sandbox. If the memory is still write protected the program doesn’t crash. This would involve looping and even if the data to be copied can be 128Mb large I’m not sure it would works because of syscall overhead.
    An Alternative would be to create code several times and try reading with several timing, but I have no idea on how to select the initial timing window.
  • Use futex… But I couldn’t found if futex can be used to check the value of non allocated memory. I’m also unsure if the thread could wake up before memory become write protected.

So, is it possible to plan for memcpy race conditions ?

Continue reading Are memcpy() based race conditions exploitable for causing remote code execution?