PHP2Shell explained in 10 minutes (A technical analysis) — Transcript
Full transcript
- 0:00PHP to shell almost broke the internet.
- 0:04PHP was vulnerable in such a critical
- 0:07way that almost every site running an
- 0:10unpatched version of PHP dating back to
- 0:135.4 is vulnerable. That version was
- 0:17released in 2012, [music]
- 0:1914 years ago. So, what are these
- 0:22critical bugs all about? Well, in this
- 0:25video, I'll break them down for you.
- 0:34If you're running PHP, you need to
- 0:37patch. If you haven't yet, then stop
- 0:39watching this video and check out our
- 0:41blog post with the actions that you need
- 0:44to take right away. The link is in the
- 0:47description. But to understand how a PHP
- 0:50bug could lead to remote code execution
- 0:53almost anywhere, we first need to look
- 0:56at how PHP workers manage requests and
- 1:00memory. A PHP worker usually handles a
- 1:04ton of HTTP requests. And each one of
- 1:07those requests gets some memory
- 1:10allocated to it for storing things like
- 1:13form fields, uploaded files, variables,
- 1:16all that kind of stuff. Now, of course,
- 1:18once a request is fully handled, then
- 1:20that memory needs to be freed, which
- 1:23means that it becomes available to be
- 1:25used by the next request, for example.
- 1:28And that cleanup mechanism is what PHP
- 1:30to shell targets. With the first
- 1:33vulnerability, the exploit makes a
- 1:35memory allocation fail while PHP is
- 1:38building a data structure. And to do
- 1:41that, the exploit drives PHP to its
- 1:44memory limits. So PHP detects that and
- 1:47aborts the operation to not exceed its
- 1:49memory. And that means that the data
- 1:51structure it was creating never fully
- 1:54gets created. But afterwards, its
- 1:56cleanup code still behaves as if that
- 1:59data structure was fully created. And at
- 2:02that point a mismatch happens. PHP
- 2:05starts treating this unfinished memory
- 2:08as a valid data structure. And that's
- 2:10kind of the basic primitive of this
- 2:12vulnerability. Because for this exploit
- 2:15to work, it needs to make sure that PHP
- 2:18is out of memory at the perfect moment.
- 2:21So you cannot just do this by performing
- 2:23a denial of service attack and
- 2:25exhausting the memory by sending a ton
- 2:27of requests. You need to do it at the
- 2:29perfect moment. And PHP does not make
- 2:32this simple because it has many limits
- 2:35that should stop you from causing PHP to
- 2:38run out of memory within a single
- 2:40request. There's for example the postmax
- 2:43size which limits the size of a post
- 2:46request. So you can't send gigabytes of
- 2:49data in a single request. Then there's
- 2:52also the max file uploads which limits
- 2:56the number of files you can upload in a
- 2:58single request and combined these should
- 3:01make it really difficult to exceed that
- 3:03memory at the perfect timing. But this
- 3:06exploit found a gap between those two
- 3:08limits and it is really really
- 3:11interesting. So one way to do this is
- 3:13with a request that looks like this. The
- 3:17server sees this as receiving a file.
- 3:20Granted, it's quite a special file
- 3:22because it doesn't have any contents and
- 3:24its file name is empty. And that's on
- 3:28purpose because when the file name is
- 3:30empty, it just so happens not to count
- 3:33towards the limit of files you can
- 3:35upload. So using this technique, you can
- 3:38upload a ton of files way past the usual
- 3:41limit. But under the hood, PHP still
- 3:44processes all of these files and stores
- 3:47their metadata in memory like the name,
- 3:50the full path, the type, and so on. And
- 3:52in this case, you'll also notice that
- 3:54the name contains this weird structure.
- 3:57Now, these are nested arrays, and they
- 3:59cause PHP to have to allocate multiple
- 4:02large objects in memory for each fake
- 4:05uploaded file. One of these files is
- 4:08okay. PHP can handle that. But once you
- 4:11start sending a request with hundreds or
- 4:14thousands of these fake files, then you
- 4:16can easily reach PHP's default 128 mgby
- 4:21memory limit. And this also explains why
- 4:24the first advice we got to potentially
- 4:26mitigate these vulnerabilities is to
- 4:28change the memory limit to minus1 making
- 4:31it much more difficult to exploit this
- 4:34vulnerability because as an attacker you
- 4:36now cannot easily predict how much
- 4:39memory is left. But of course that
- 4:41doesn't fix the root cause. It's not a
- 4:43complete fix. But that's not the only
- 4:45vulnerability in this story. there is a
- 4:48second one and the second bug is totally
- 4:51different from the first one and both
- 4:53can lead to remote code execution. Now
- 4:55in the case of the second bug, PHP keeps
- 4:58some information for the entire lifetime
- 5:00of a worker in memory and during a
- 5:03request that's long lived information
- 5:06can contain pointers to the memory of
- 5:09that request. And a pointer is simply an
- 5:12address telling PHP where some data
- 5:16lives. The exploit then tries to kill or
- 5:19cause the request to die at the exact
- 5:21moment where PHP would still free the
- 5:24request's temporary memory but fail to
- 5:27clear that pointer to that memory. And
- 5:30this means that at that point the worker
- 5:32is effectively poisoned in a way where
- 5:35it still has an address to memory that
- 5:38no longer contains valid data. And then
- 5:41when another request from the attacker
- 5:43comes into that same worker, the memory
- 5:45that this address is pointing to can be
- 5:48filled again with new and in this case
- 5:50attacker controlled data while PHP still
- 5:53thinks it contains trusted internal
- 5:56objects. And at this point the attacker
- 5:59has a stale pointer in memory that they
- 6:02may be able to influence but it's
- 6:04definitely not yet code execution. Now
- 6:07imagine that this stale pointer contains
- 6:10the address ox1234.
- 6:13When the attacker sends their first
- 6:14request, ox1234
- 6:16contains valid PHP data. But when that
- 6:20request ends, PHP frees the memory at
- 6:23that address, but the stale pointer
- 6:25survives, and that's the base primitive.
- 6:28The attacker then sends another request
- 6:30that makes PHP create many values of
- 6:33roughly the same size as the data that
- 6:36was stored at ox1234.
- 6:39And by carefully crafting requests that
- 6:41contain data that just so happens to end
- 6:44up having the same size in memory of the
- 6:46original data, the attacker can increase
- 6:49the chances that their data from the new
- 6:51request will be placed at ox1234.
- 6:55And this process is called heap
- 6:58grooming. When PHP then later follows
- 7:01that pointer, it does not know that the
- 7:03memory was freed and already reused
- 7:06again by something else. And I'm going
- 7:08to try not to further complicate things
- 7:10here, but I also need to tell you about
- 7:12another important internal structure,
- 7:15the ZV val, which is something PHP uses
- 7:18to represent values. val contains a
- 7:21value itself and then also the type
- 7:24information telling PHP whether that
- 7:26value is an integer, a string, an array,
- 7:29an object and so on. If the type says
- 7:31integer, then PHP treats ox1234
- 7:35as the number 4,660.
- 7:39But if the type says string or object,
- 7:42then PHP treats the same ox1234
- 7:45as a pointer to a memory address and
- 7:48goes there to find the string object.
- 7:51Now if the exploit can control both
- 7:53fields of a zval, then it can give PHP a
- 7:57memory address and label it as a string.
- 8:01Now if you ask PHP to read that fake
- 8:03string, that can expose memory from the
- 8:06process. And that's useful because
- 8:08modern operating systems have something
- 8:10called ASLR,
- 8:13address space layout randomization. And
- 8:16that pretty much means that all
- 8:17processes have their memory layouts
- 8:20randomized. So an attacker can know
- 8:23where things in memory are. And that's
- 8:25knowledge you need to make a working
- 8:27exploit. But by leaking process memory,
- 8:30the attackers can reveal where certain
- 8:32things live in memory and reverse
- 8:35engineer the entire memory layout for
- 8:37that process. Of course, this whole
- 8:39story is still developing and we don't
- 8:41yet have all of the information. But I
- 8:44wanted to make this video to show what
- 8:47minute little details you need to get
- 8:49right to have an exploit that works and
- 8:53works reliably. These bugs are
- 8:55incredibly complex. So many things had
- 8:58to align for them to work. And what I've
- 9:00shown here is only just the beginning.
- 9:03This is also why we're seeing so many
- 9:05vibecoded exploits being created right
- 9:07now that don't work or only work in very
- 9:10contrived lab environments. But it's
- 9:12very scary because who knows what other
- 9:15bugs are still hiding in code we've
- 9:17already tested a 100 times. and maybe
- 9:20with AI models, we'll now be able to
- 9:22find all of those bugs. But with that,
- 9:24we've also reached the end of this
- 9:26video. If you're still looking for more
- 9:28information on how to contain all of
- 9:31this, then check out the links in the
- 9:33description to our blog post and video
- 9:35detailing the actions you need to take
- 9:38right now. If you're looking for an even
- 9:40more technical breakdown of this bug and
- 9:42the continuation of how this leads to an
- 9:44RCE, then definitely check out Khalif's
- 9:47blog post. They originally identified
- 9:49the vulnerabilities and did a great deep
- 9:52dive on it as well. Thanks for watching
- 9:54and I'll see you in another video.
About this transcript
This page contains the full transcript of PHP2Shell explained in 10 minutes (A technical analysis) by Aikido Security, generated from the public captions YouTube serves with the video. The transcript has 1,513 words across 221 segments, with the original timestamps preserved so you can click any line to jump to that moment in the embedded player.
What you can do with it
Use the transcript to take notes, quote the speaker, build a study guide, generate a summary with ChatGPT or Claude via the YouTube Summary tool, or export it as a timed subtitle file with YouTube to SRT. You can also re-open it in the transcriber to translate the transcript into 100+ languages.
Free YouTube transcript tool
YouTube2Text is a free YouTube transcript generator — no signup, no daily limit. Paste any YouTube link and get the full transcript instantly, with timestamps, click-to-jump, translation to 100+ languages, AI prompts for ChatGPT, Claude, and Gemini, and exports to TXT, SRT, VTT, or Markdown.