-
Notifications
You must be signed in to change notification settings - Fork 13.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Magento Arbitrary File Read (CVE-2024-34102) + PHP Buffer Overflow iconv() of GLIBC (CVE-2024-2961) #19544
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CC @cfreal
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
'Notes' => { | ||
'Stability' => [ CRASH_SAFE, ], | ||
'SideEffects' => [ ARTIFACTS_ON_DISK, IOC_IN_LOGS ], | ||
'Reliability' => [ REPEATABLE_SESSION, ] # Multiple sessions return after a single module run, after multiple module runs expect to get no longer receive any sessions. It doesn't seem to crash the target but it does seem to stop responding to exploit attempts after a few tries |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@cfreal: do you know what's happening here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A guess: you hang every worker? Try reproducing and then trying to reach a normal page. It may come from the fact that you don't kill the worker.
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
documentation/modules/exploit/linux/http/magento_xxe_to_glibc_buf_overflow.md
Outdated
Show resolved
Hide resolved
Co-authored-by: Julien Voisin <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modules/exploits/linux/http/magento_xxe_to_glibc_buf_overflow.rb
Outdated
Show resolved
Hide resolved
step4_use_custom_heap = chunked_chunk(step4_use_custom_heap) | ||
step4_use_custom_heap = compressed_bucket(step4_use_custom_heap) | ||
|
||
pages = ((step4 * 3) + step4_pwn + step4_custom_heap + step4_use_custom_heap + step3_overflow + (pad * PAD) + (step1 * 3) + step2_write_ptr + (step2 * 2)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess the 3 meterpreter executions are coming from the free
of the different chunks?
command = payload.encoded | ||
|
||
command = (command + "\x00").b | ||
command = command.ljust(step4_use_custom_heap_size, "\x00".b) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here we should prevent to free
(aka system
) the other chunks that contains random data.
From the original PoC:
# We make sure that the "system" command kills the current process
# to avoid other system() calls with random chunk data, leading to undefined behaviour.
...
COMMAND = self.command
COMMAND = f"kill -9 $PPID; {COMMAND}"
if self.sleep:
COMMAND = f"sleep {self.sleep}; {COMMAND}"
COMMAND = COMMAND.encode() + b"\x00"
The most elegant way would be to reset the free
to the __libc_free
instead of system
but I am not sure if we can do it in an easy way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
In the current state of affairs, it is very hard to make the process go on without crashing. That's why I kill it. Here's why.
The exploit overwrites zend_mm_heap.custom_heap
function pointers, then overwrites zend_mm_heap.use_custom_heap
to make PHP actually use the modified funcs. At this point, if we manage to make PHP call efree(some_buffer_we_control)
, we get RCE, because it calls zend_mm_heap.custom_heap.efree
(which is system@libc
). However, before this happens, PHP will want to allocate some structures (for instance, a php_stream_bucket
). We cannot avoid this. Therefore, we need to provide a way for PHP to allocate before we can reach the efree()
call. I used malloc@libc
because it was a way to get memory, not because they were the "complement" of free@libc
. Now, in the original exploit, as soon as the system()
calls comes in, the worker process gets killed before it can do nasty things. However, if we let it live, he'd have some chunks allocated on its real, PHP, heap, and others in the libc heap. We'd not know which free() function needs to be called for each.
To let the process live, we could ROP, but that would (to me) break the beauty of the exploit, which lies in its heavy compatibility.
Not quite sure I'm clear, so please ask if not!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was unable to return a session (had tried cmd/linux/http/x64/meterpreter/reverse_tcp
, cmd/unix/reverse_bash
, cmd/unix/reverse_netcat
) while prepending sleep 1; kill -9 $PPID
to the payload.
However when using cmd/unix/generic
with CMD => 'touch /tmp/vuln
with sleep 1; kill -9 $PPID
prepended, the payload gets delivered successfully and the file gets written to disk.
I meant to mention this and go back and do some investigating with a process monitor to try and deduce why I wasn't getting a session when attempting to kill the parent process/ why 3 were coming back when I wasn't though I was eager to get this posted my apologies.
I'll take a look today and let you know what I find. If I can't get it working I'll consider your more elegant solution. Thank you @dledda-r7
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jheysel-r7 just to be clear, the sleep 1
does not do anything, it's just there to induce lag and confirm the code actually triggered. Also (but I think our messages crossed) the solution suggested by @dledda-r7 would not work, sadly.
Vulnerable Application
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 the following versions of Magento and Adobe Commerce and
earlier if the PHP and glibc versions are also vulnerable:
Vulenerable PHP versions:
Vulnerable iconv() function in the GNU C Library:
Setup
The following docker-compose file can be used to test this module. There are a few things that need to be noted:
following once the container has been started:
localhost
and in order to exploit the containerrhost
mustbe set to
localhost
(settingrhost
to127.0.0.1
or your local IP address will not work for this docker-compose file)and so given this configuration
msfconsole
must be running on the same host as the container.msfconsole
from an Ubuntu 22.04 VM.Verification Steps
use
RHOST
,SRVHOST
andLHOST
optionsdaemon
user.