DEV Community

Zhalok Rahman
Zhalok Rahman

Posted on

Analyzing CVE-2026-109618 Root Cause

So i want to share my analysis on CVE-2026-109618 incident

So as we all know very recently we have heard some vulnerability news about PHP engine and one of them is CVE-2026-109618: Upload-progress unserializer use-after-free, and remote process-memory disclosure

Before understanding what's going on lets have some warm up on a few things

How would you architect a file-upload handler with progress tracker?

Forget PHP, lets try to think generically. In order to architect a file upload system with progress tracking we need to do the following:

  1. Create a session and return the sessionID to the client
  2. Send the file data bytes with sessionID as metadata from the client and save the progress of the file upload workload in the session we just created at the server side.
  3. Track the progress of the file-upload workload by polling the session using the sessionID from the client side

A very simple architecture !!!

But lets focus on one term here and that is the sessionID
In PHP there is a specific dedicated pointer that refers to the sessionID string in memory and its called the PS(id). (Don't ask me why its called PS(id) please, ain't a PHP guy)

During the sessionID generation the PHP engine checks if the PS(id) holds any reference and if it does it simply uses that as the sessionID instead of generating a new one. (Also don't ask me why, ain't a PHP guy)

now lets understand another thing

How request handler execution gets memory?

Now during a request handler execution, definitely we need memory. and this memory comes from the heap segment and as we know, in order to access heap memory we need pointers. So during a request handler execution, some memory is allocated and in order to access that memory the address is stored into some pointers
Once the request execution is done then the pointers are cleaned up

Note that during a regular request handler execution, the PS(id) pointer is not used because as mentioned above this is used only during sessionID generation for file-upload with progress-tracking.

But the problem is if the execution is terminated unexpectedly then this pointer cleanup does not take place !!!

Lets understand the attack !!!

Now that we have some bare minimum understanding at the higher level, I think we are ready to have some idea about whats going on

So in this attack, the attacker first makes a progress-tracking-file-upload request (lets call it request1) that somehow overflows the memory boundaries and causing the execution to be terminated unexpectedly. And as discussed above when the execution is terminated unexpectedly the pointers does not get cleaned up.
(Again don't ask me why, ain't a PHP guy)

Now during a progress-tracker-file-upload request which terminated unexpectedly the PS(id) pointer is not cleaned and thus it is pointing to a certain segment of the memory.

Now while handling another regular request (lets call it request2), if the same chunk of memory is somehow allocated for the execution, then the footprint of that request stays there but the problem is even though the relevant pointers are cleaned the PS(id) pointer is still pointing into it. And since PS(id) was not used during regular request handling, it was not cleaned after the request handler execution.

So now that PS(id) is pointing to a memory address which has footprints for another requests which might include some credentials, if we can somehow get the values set inside the PS(id) referred memory then we can get the footprint of the previous regular request.

Now if the attacker makes another progress-tracker-file-upload request (lets call it request3) then there needs to be another sessionID created and during the creation of the sessionID the server will simply use the value of PS(id) referred memory. Because as we discussed earlier, if the PS(id) pointer has any reference then the sessionID is created from that without going through a new sessionID generation.

So now in the sessionID of the second progress-tracker-file-upload request (request3) we will have the memory footprint of the regular request (request2) because the sessionID is generated based on the value of PS(id) referred memory which was used by request2 during its execution.

Conclusion

I ain't a PHP guy as I mentioned quite a few times during this entire writing. Therefore whatever I had written is completely based on my understanding about generic system design.

From my observation I believe the root cause can be considered as a stale cache and not handling termination signals gracefully

Hope you had enjoyed !!!

Top comments (0)