{"id":49824,"date":"2026-10-23T19:37:02","date_gmt":"2026-10-23T14:07:02","guid":{"rendered":"https:\/\/www.getastra.com\/blog\/?p=49824"},"modified":"2026-10-23T19:44:29","modified_gmt":"2026-10-23T14:14:29","slug":"cve-2026-115560","status":"publish","type":"post","link":"https:\/\/www.getastra.com\/blog\/security-advisory\/cve-2026-115560\/","title":{"rendered":"CVE-2026-115560: Another PHP Session-Handler RCE"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><strong>TLDR:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>PHP disclosed a second RCE path on October 23, two days after the emergency PHP2Shell fixes.\u00a0<\/li>\n\n\n\n<li>CVE-2026-115560 is tied to session upload progress and runtime changes to the serialize handler.\u00a0<\/li>\n\n\n\n<li>Mitigation is one INI line: session.upload_progress.enabled=0.\u00a0<\/li>\n\n\n\n<li>If you already applied that after the October 21 PHP2Shell advisory, you are already covered for this one.\u00a0<\/li>\n\n\n\n<li>Preconditions are narrow but worth checking.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Two days after PHP shipped emergency patches for <a href=\"https:\/\/www.getastra.com\/blog\/security-advisory\/php2shell-php-vulnerabilities\/\" target=\"_blank\" rel=\"noreferrer noopener\">PHP2Shell<\/a> (CVE-2026-109618 and CVE-2026-109619), the project is back with another RCE advisory: CVE-2026-115560.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Looks like PHPoclypse is going to stick around till the weekend. In this blog, we break down what CVE-2026-115560 actually is, the narrow configuration that makes it exploitable, and the one-line mitigation you can apply before the weekend.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">PHP itself is calling this one \u201cunlikely,\u201d telling the world that another path to code execution exists and that the fix will arrive on the regular release train.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_CVE-2026-115560_Actually_Is\"><\/span>What CVE-2026-115560 Actually Is<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">PHP\u2019s advisory frames <strong><a href=\"https:\/\/www.php.net\/archive\/2026.php#2026-10-23-1\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">CVE-2026-115560<\/a><\/strong> as a code execution issue reachable only through a specific sequence of session-handling moves. The vulnerable surface is session.upload_progress, the built-in feature that writes upload progress data into $_SESSION so applications can show progress bars without a separate backend. It is enabled by default.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The bug fires when all of the following line up in the same request path:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>session.serialize_handler is set to <code>php_binary or php_serialize<\/code> in <code>php.ini<\/code> or an equivalent config layer<\/li>\n\n\n\n<li>The application then calls<code> ini_set('session.serialize_handler', 'php'<\/code>) at runtime, flipping the handler to the legacy format<\/li>\n\n\n\n<li>That <code>ini_set()<\/code> call happens before <code>session_start()<\/code><\/li>\n\n\n\n<li><code>session.upload_progress.enabled<\/code> is still 1<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">PHP has not published the technical root cause yet but told there is a chance for RCE.<\/p>\n\n\n\n<style>\n.ctaSaasCheckWrap{\n  padding:35px;\n  border: 6px;\n  background-image: url('https:\/\/cdn-blog.getastra.com\/2025\/08\/0737b9ac-deepblue-bg.png');\n  background-size: cover;\n  background-repeat: no-repeat;\n  position: relative;\n  background-position: right;\n  height: 275px;\n  border-radius: 10px;\n  margin: 20px 0px;\n}\n.pentestHeadingDB{\n  color: #fff;\n  font-size: 24px;\n  font-weight: 600;\n  max-width: 450px;\n}\n.ctaSaasCheckWrapHead {\n    display: flex;\n    align-items: center;\n    grid-gap: 1rem;\n}\n.ctaOneDB {\n    display: flex;\n  align-items: center;\n  padding: 1rem 1.5rem;\n  border-radius: 12px;\n  background-color: #FCBB2F;\n  text-decoration: none;\n  grid-gap: .5rem;\n  color: #000!important;\n  font-size: 18px;\n  font-weight: 500;\n  min-height: 3.75rem;\n  max-height: 3.75rem;\n  box-shadow: 0 4px 4px #00000014, 0 0 0 1px #c08e24, inset 0 -4px #0000003d;\n}\n.ctaTwo {\n    text-decoration: none;\n    background-color: #24BC94;\n    color: #ffffff !important;\n    padding: 10px 25px;\n    border-radius: 6px;\n    font-weight: 600;\n}\n.spanBoldBlue {\n    color: #3078FE;\n    font-weight: 700;\n}\n.ctaSaasCheckWrapImg{\n  position: absolute;\n  bottom: 0px;\n  right: 10px;\n  height: 250px;\n  width: 240px;\n}\n@media(max-width: 768px){\n}\n@media(max-width: 576px){\n   .pentestHeading{\n      font-size: 28px;\n    }\n   .ctaSaasCheckWrapImg{\n     display: none;\n   }\n}\n<\/style>\n\n<div class=\"ctaSaasCheckWrap\">\n<p class=\"pentestHeadingDB\">Is your PHP vulnerable to PHP2Shell? Run a free check to find out.<\/p>\n<div class=\"ctaSaasCheckWrapHead\">\n  <a class=\"ctaOneDB\" href=\"https:\/\/php2shell.getastra.com\/?\" target=\"_blank\" rel=\"noopener\">Check for Exposure<\/a>\n<\/div>\n<img decoding=\"async\" class=\"ctaSaasCheckWrapImg\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2024\/08\/96ad3cf0-girlcta.png\" alt=\"character\">\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"Mitigation_for_CVE-2026-115560\"><\/span>Mitigation for CVE-2026-115560<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">For this <strong>CVE-2026-115560<\/strong>, PHP shared the same fix as the October 21 advisory for <strong>CVE-2026-109619<\/strong>:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ini<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>session.upload_progress.enabled = 0<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set it administratively, the way PHP\u2019s advisory asks. In FPM, that\u2019s <code>php_admin_flag[session.upload_progress.enabled] = off<\/code> in your pool config. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In Apache with mod_php, it\u2019s <code>php_admin_flag session.upload_progress.enabled off<\/code>. The administrative flag matters here because application code cannot override <code>php_admin_*<\/code> with <code>ini_set()<\/code>, and <code>ini_set()<\/code> is exactly how this bug is reached.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Restart every worker after the change. Do not just reload. Then verify on the SAPI that actually serves your site, not the CLI. <code>php -i<\/code> reads the CLI config and will mislead you. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Use <code>php-fpm -i | grep session.upload_progress<\/code>, or open a <code>phpinfo()<\/code> page through the web server to confirm the setting is live where it counts.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Nothing in a typical web application depends on this feature. It only matters if you are actively rendering an upload progress UI from <code>$_SESSION<\/code>. If you are, swap to a client-side progress indicator until the routine fix ships. The browser already emits <code>progress<\/code> events on <code>XMLHttpRequest<\/code> and <code>fetch<\/code> uploads, so the replacement is straightforward.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you applied this mitigation for PHP2Shell and never rolled it back, you are done. CVE-2026-115560 does not need a second action..<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Patch Status<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><tbody><tr><td><strong>CVE<\/strong><\/td><td><strong>Status<\/strong><\/td><td><strong>Patched Versions<\/strong><\/td><\/tr><tr><td>CVE-2026-109618 (PHP2Shell)<\/td><td>Patched Oct 21<\/td><td>8.5.12, 8.4.27, 8.3.36, 8.2.35<\/td><\/tr><tr><td>CVE-2026-109619 (PHP2Shell)<\/td><td>Patched Oct 21<\/td><td>8.5.12, 8.4.27, 8.3.36, 8.2.35<\/td><\/tr><tr><td>CVE-2026-115560<\/td><td>Unpatched; fix queued for next routine release<\/td><td>TBD<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">PHP has not confirmed which branches are affected by <strong>CVE-2026-115560<\/strong> or whether the fix will backport across all supported lines. Assume it will, plan accordingly, and keep the INI mitigation in place until the next routine release lands and you have verified the fix on your version.<\/p>\n\n\n<div class=\"gb-container gb-container-86e8fbac\">\n\n<p class=\"wp-block-paragraph\"><strong>Automate the check with our open-source triage skill<\/strong>: Because php -v can report a different binary from the one serving traffic, we built <a href=\"https:\/\/github.com\/getastra\/php2shell-triage\" target=\"_blank\" rel=\"noreferrer noopener\">php2shell-triage<\/a>, a free Claude skill and plugin for defenders. Its read-only assessor walks \/proc to find the real binary behind every running PHP-FPM, Apache, and CLI worker.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It also flags workers still running an old binary after an upgrade, and tells distro-backported fixes apart from vulnerable builds. It then guides you through hunting for signs of exploitation and the remediation steps. It runs only on hosts you own and contains no exploit code<\/p>\n\n<\/div>\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"What_To_Do_Before_The_Weekend\"><\/span>What To Do Before The Weekend<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Not patched PHP2Shell yet? That is still the higher priority task. Those CVEs are being exploited in the wild. CVE-2026-115560 is not.<\/li>\n\n\n\n<li>Set session.upload_progress.enabled = 0 everywhere. Leave it set until the next routine PHP release lands, and you verify the fix.<\/li>\n\n\n\n<li>Grep your codebase and config layers for runtime ini_set calls against session.serialize_handler. If you find any, you are the narrow case.<\/li>\n\n\n\n<li>Watch php.net and the php-src security advisories page for the full CVE-2026-115560 write-up.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">PHP calling an RCE \u201cunlikely\u201d is not the same as it being safe to ignore. It is a release decision, not a risk assessment for your specific stack. The one-line mitigation costs nothing. Apply it and move on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><span class=\"ez-toc-section\" id=\"How_Astra_Helps\"><\/span>How Astra Helps<span class=\"ez-toc-section-end\"><\/span><\/h2>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"2560\" height=\"1610\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2026\/10\/90363981-autonomous-pentesting-for-php2shell-scaled.png\" alt=\"Autonomous pentesting for PHP2Shell\" class=\"wp-image-49716\" srcset=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/90363981-autonomous-pentesting-for-php2shell-scaled.png 2560w, \/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/90363981-autonomous-pentesting-for-php2shell-scaled.png 365w, \/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/90363981-autonomous-pentesting-for-php2shell-scaled.png 1536w, \/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/90363981-autonomous-pentesting-for-php2shell-scaled.png 2048w\" sizes=\"auto, (max-width: 2560px) 100vw, 2560px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Astra\u2019s DAST and AP detect both PHP2Shell vulnerabilities (CVE-2026-109618 and CVE-2026-109619) for our existing customers. Run a scan on an unpatched PHP app and both CVEs are flagged with context on the exposure and what to patch to.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1401\" height=\"982\" src=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/cdn-blog.getastra.com\/2026\/10\/52fbfbd3-image.png\" alt=\"\" class=\"wp-image-49700\" srcset=\"\/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/52fbfbd3-image.png 1401w, \/cdn-cgi\/image\/quality=80,format=auto,onerror=redirect,metadata=none\/https:\/\/storage.googleapis.com\/cdn-blog.getastra.com\/2026\/10\/52fbfbd3-image.png 328w\" sizes=\"auto, (max-width: 1401px) 100vw, 1401px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">We have also released a <strong>free PHP2Shell scanner<\/strong> that anyone can run without an Astra account. Point it at your endpoints, get a quick read on whether CVE-2026-109618 and CVE-2026-109619 are exposed, and move on with the patch plan. [Link to the scanner]<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Once more information arrives on CVE-2026-115560, we will update here with coverage details.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Disclaimer:<\/strong> This is an evolving situation. As of October 23, 2026, PHP has not published affected version ranges, a CVSS score, a target release for the fix, or confirmation of whether CVE-2026-115560 shares a root cause with CVE-2026-109619.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>TLDR: Two days after PHP shipped emergency patches for PHP2Shell (CVE-2026-109618 and CVE-2026-109619), the project is back with another RCE advisory: CVE-2026-115560. Looks like PHPoclypse is going to stick around till the weekend. In this blog, we break down what CVE-2026-115560 actually is, the narrow configuration that makes it exploitable, and the one-line mitigation you &#8230; <a title=\"CVE-2026-115560: Another PHP Session-Handler RCE\" class=\"read-more\" href=\"https:\/\/www.getastra.com\/blog\/security-advisory\/cve-2026-115560\/\" aria-label=\"Read more about CVE-2026-115560: Another PHP Session-Handler RCE\">Read more<\/a><\/p>\n","protected":false},"author":138,"featured_media":49825,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[819],"tags":[],"class_list":["post-49824","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-security-advisory"],"_links":{"self":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49824","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/users\/138"}],"replies":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/comments?post=49824"}],"version-history":[{"count":3,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49824\/revisions"}],"predecessor-version":[{"id":49830,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/posts\/49824\/revisions\/49830"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media\/49825"}],"wp:attachment":[{"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/media?parent=49824"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/categories?post=49824"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.getastra.com\/blog\/wp-json\/wp\/v2\/tags?post=49824"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}