PolyShell: lo que está establecido y lo que difiere
CVE-2026-48356, apodada PolyShell, afecta a Adobe Commerce y a Magento Open Source. La ficha de la NVD, publicada el 14 de julio de 2026 a partir de la declaración de Adobe, la clasifica como CWE-434 (subida de un archivo de tipo peligroso), con una puntuación CVSS 3.1 de 9,3 y el vector AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N. El parche es el boletín de Adobe APSB26-73. El 27 de octubre de 2026, la CISA la añadió a su catálogo de vulnerabilidades explotadas (KEV), con un plazo hasta el 10 de noviembre de 2026 para las agencias federales estadounidenses: la explotación ya no es una hipótesis.
Las fuentes no describen el fallo de la misma manera. La NVD habla de una ejecución de código arbitrario «en el contexto del usuario actual», que requiere interacción: una víctima tiene que visitar una URL manipulada o una página comprometida, y el impacto va más allá del componente vulnerable. Sansec y la prensa especializada describen subidas de archivos que terminan en webshells en el servidor. No zanjamos entre estas dos lecturas. La conducta prudente, para una agencia, consiste en tratar toda tienda que siga sin parche como una tienda que ya puede llevar un webshell.
Lo que dicen las fuentes y lo que usted retiene
Desplace la tabla
| Fuente | Lo que afirma | Lo que usted retiene |
|---|---|---|
| NVD | CWE-434, CVSS 3.1 de 9,3, interacción requerida, ejecución en el contexto del usuario actual | Los identificadores que debe anotar en el expediente del cliente |
| CISA, catálogo KEV | Explotación constatada, añadida el 27 de octubre de 2026, plazo federal hasta el 10 de noviembre de 2026 | Un horizonte de trabajo, no una fecha cómoda |
| Adobe, boletín APSB26-73 | Las versiones con el sufijo 2026-jul no están afectadas | La versión objetivo de cada rama |
| Sansec, 30 de marzo de 2026 | Oleada masiva: 471 tiendas comprometidas en una hora, un webshell PHP y después puertas traseras `accesson.php` | Los archivos que hay que buscar en el disco |
| Sansec, 24 de octubre de 2026 | Cargador JavaScript en `cms_block`, campaña seguida desde julio de 2025 en 953 tiendas; 102 de 169 instalaciones sin parche tenían archivos subidos | Las consultas que hay que lanzar en la base |
| Prensa especializada | Subida de archivos que lleva a webshells | Una lectura que contrastar, no una fuente primaria |
Por qué el parche no cierra el expediente
Aplicar APSB26-73 elimina la falla. No retira nada de lo que ya ha entrado. Un webshell depositado antes de la actualización sigue en el disco, una puerta trasera accesson.php sigue respondiendo, un script inyectado en cms_block sigue sirviéndose a cada visitante y una cuenta de administrador creada por el atacante sigue siendo válida. Sansec lo resume así: retirar los scripts no retira el acceso del atacante.
El segundo estudio de Sansec muestra por qué la pregunta afecta a todo un parque. De 169 instalaciones de Magento 2 sin parche examinadas, 102 tenían archivos subidos mediante PolyShell o SessionReaper (CVE-2025-54236, corregida por el boletín APSB25-88), es decir, un 60 %. El orden de trabajo es, por tanto, fijo: inventario, estado congelado, actualización, búsqueda de rastros, rotación de accesos y, al final, un informe fechado para el cliente. Saltarse la rotación para ganar una hora es dejar al atacante las llaves que quizá ya ha copiado.
Lo que este procedimiento deja en sus manos
- Un inventario por tienda — edición (Commerce u Open Source), versión exacta, presencia o ausencia del parche 2026-jul.
- Una versión objetivo por rama — leída en el boletín APSB26-73, sin adivinar la numeración.
- Un estado congelado antes de intervenir — snapshot y exportación de la base conservados como prueba, antes de cualquier limpieza.
- Cuatro controles reproducibles — archivos bajo
pub/media, puertas traserasaccesson.php, JavaScript encms_blocky encms_page. - Una rotación completa de accesos — cuentas de administración, claves de API y de integración, base de datos, clave de cifrado, SSH y SFTP.
- Un informe fechado para cada cliente — lo que se ha verificado, encontrado y corregido, y lo que no.
Versiones afectadas y versiones corregidas según APSB26-73
Desplace la tabla
| Producto y rama | Afectada hasta | Versión corregida |
|---|---|---|
| Adobe Commerce 2.4.9 | 2.4.9 | 2.4.9-2026-jul |
| Adobe Commerce 2.4.8 | 2.4.8-p5 | 2.4.8-2026-jul |
| Adobe Commerce 2.4.7 | 2.4.7-p10 | 2.4.7-2026-jul |
| Adobe Commerce 2.4.6 | 2.4.6-p15 | 2.4.6-2026-jul |
| Adobe Commerce 2.4.5 | 2.4.5-p17 | 2.4.5-2026-jul |
| Adobe Commerce 2.4.4 | 2.4.4-p18 | 2.4.4-2026-jul |
| Magento Open Source 2.4.9 | 2.4.9 | 2.4.9-2026-jul |
| Magento Open Source 2.4.8 | 2.4.8-p5 | 2.4.8-2026-jul |
| Magento Open Source 2.4.7 | 2.4.7-p10 | 2.4.7-2026-jul |
| Magento Open Source 2.4.6 | 2.4.6-p15 | 2.4.6-2026-jul |
| Adobe Commerce B2B | 1.5.3, 1.5.2-p5, 1.4.2-p10, 1.3.4-p17, 1.3.3-p18 | 1.5.3-2026-jul, 1.5.2-2026-jul, 1.4.2-2026-jul, 1.3.4-2026-jul, 1.3.3-2026-jul |
| Adobe Commerce Events | 1.20.0 y anteriores | 1.21.0 |
| Magento Open Source 2.4.5 y 2.4.4 | Ausentes de la lista de la NVD | Ninguna conclusión: lea el aviso de Adobe |
Inventariar la versión de cada tienda
Leer la versión declarada
cd /var/www/tienda-clientebin/magento --version
El comando muestra la edición y el número. La ruta es un ejemplo: adáptela a cada alojamiento. Ejecútelo con el usuario del sistema propietario de los archivos, no como root, para no modificar los permisos de la caché.Contrastar con Composer
composer show magento/product-community-edition
para Magento Open Source, ocomposer show magento/product-enterprise-edition
para Adobe Commerce. Composer lee lo que está realmente instalado. Si las dos lecturas difieren, manda Composer, y la diferencia se anota.Recorrer un servidor entero
find /var/www /home -name composer.lock -not -path '*/vendor/*' -exec grep -H -A1 '"name": "magento/product-' {} +
Cada archivo citado pertenece a una instalación de Magento, y la líneaversionsigue al nombre del paquete. Una preproducción pública o una copia antigua descomprimida cuenta como una tienda: está expuesta de la misma manera si se sirve.Clasificar con la tabla de versiones
Compare el número obtenido con la tabla anterior. Regla de lectura: toda versión que no lleve el sufijo 2026-jul de su rama debe tratarse. Para Magento Open Source 2.4.5 y 2.4.4, ausentes de la lista de la NVD, no escriba «no afectada»: remita al boletín de Adobe y trate la tienda como expuesta mientras no haya leído lo contrario.
Anotar una línea por tienda
Cliente, servidor, ruta, edición, versión obtenida, fecha y hora de la lectura. Añada desde ahora las columnas que servirán más adelante: parche aplicado, resultado de los cuatro controles, accesos rotados. Esta tabla se convierte en la pieza central del expediente entregado al cliente.
Congelar el estado antes de tocar: también es una prueba
Antes de cualquier cambio, congele la tienda tal como la encontró. En un VPS, un snapshot del VPS, si su proveedor lo ofrece, captura el disco entero; añada una exportación de la base y un archivo del código en un soporte que la actualización no toque. La diferencia entre ambas herramientas se detalla en nuestra comparativa entre snapshot y copia de seguridad.
Este estado sirve dos veces. Permite volver atrás si la actualización rompe el proceso de compra. Sobre todo, conserva la prueba: si el atacante entró, los archivos depositados, sus fechas y los bloques CMS modificados están en esta copia, y en ningún otro lugar una vez hecha la limpieza. La CISA remite además a sus requisitos de triaje forense para los sistemas afectados. No borre ni sobrescriba este estado mientras el expediente no esté cerrado.
Un cambio de rama, de 2.4.6 a 2.4.9 por ejemplo, es otro proyecto: su procedimiento con Composer y su calendario de soporte están en nuestra guía de actualización. Aquí, cada tienda se queda en su rama y solo recibe el parche.
Aplicar el parche sin un corte largo
Ensayar en una preproducción
Restaure el estado congelado en una preproducción, o clone la tienda, y ejecute primero allí la actualización. Cronometre cada comando: esa duración fija la ventana de mantenimiento que anunciará al cliente.
Fijar la versión corregida
composer require magento/product-community-edition=<version-corregida> --no-update
Sustituya el paquete pormagento/product-enterprise-editionpara Adobe Commerce, y<version-corregida>por la versión con el sufijo 2026-jul de su rama, tal como la escribe el boletín.Resolver y validar el archivo de bloqueo
composer update magento/product-community-edition --with-all-dependencies
Revise la lista de paquetes modificados. Elcomposer.lockobtenido y probado es el que desplegará: la producción ya no resuelve nada, instala.Abrir la ventana de mantenimiento en producción
bin/magento maintenance:enablebin/magento maintenance:allow-ips <su-ip>
Todo lo anterior se hizo sin cortar la venta. El segundo comando le permite probar la tienda antes de reabrirla.Instalar y aplicar
composer install --no-devbin/magento setup:upgradebin/magento setup:di:compilebin/magento setup:static-content:deploy
Con un archivo de bloqueo ya validado, el corte se limita a estos cuatro comandos.Reabrir y comprobar
bin/magento maintenance:disablecomposer show magento/product-community-edition
La versión instalada debe ser la versión corregida de su rama. Haga un pedido con la pasarela de pago en modo de prueba y anote después la versión y la hora en la tabla.
Buscar rastros de compromiso
Listar los archivos depositados bajo pub/media
find pub/media/custom_options/ pub/media/customer_address/ -type f ! -name '.htaccess'
Comando publicado por Sansec, que se lanza desde la raíz de la tienda. Todo archivo listado debe examinarse, en particular un script PHP. Cópielo fuera del árbol público con su fecha de modificación antes de borrarlo.Buscar las puertas traseras accesson.php
find . -name 'accesson.php' -type f
Sansec señala este archivo «en varios directorios»: lance la búsqueda desde la raíz, no solo bajopub/. Un resultado vacío demuestra la ausencia de ese archivo, no la ausencia de cualquier puerta trasera.Consultar la tabla cms_block
SELECT block_id, identifier, update_time FROM cms_block WHERE content LIKE '%fpCode%' OR content LIKE '%se_referrer%' OR content LIKE '%localStorage.getItem%';
Consulta publicada por Sansec. Añada el prefijo de tabla de la instalación si existe. La columnaupdate_timeayuda a fechar la inyección.Consultar la tabla cms_page
SELECT page_id, identifier, update_time FROM cms_page WHERE content LIKE '%fpCode%' OR content LIKE '%se_referrer%' OR content LIKE '%localStorage.getItem%';
El mismo control sobre las páginas CMS. Un resultado no es necesariamente malicioso:localStorage.getItempuede aparecer en un script legítimo. Lea el contenido antes de concluir.Cotejar con los indicadores publicados
Para la oleada de marzo de 2026, Sansec publicó un dominio de cargador,
lanhd6549tdhse.top, una clave de localStorage,136c1e07507f4a97, y una marca de puerta trasera,8194460. Búsquelos en los resultados anteriores y en los archivos encontrados, por ejemplo congrep -rl 'lanhd6549tdhse' pub/ app/. Esta lista no es exhaustiva: su ausencia no exculpa a una tienda.Revisar las cuentas de administrador
SELECT user_id, username, email, created, logdate, is_active FROM admin_user ORDER BY created DESC;
Una cuenta que nadie reconoce, o creada en una fecha cercana a la de un archivo sospechoso, se desactiva y luego se documenta. El control mensual de estos puntos en cada VPS de cliente se describe en nuestra checklist de auditoría.
Refuerzo: PHP no tiene nada que hacer bajo pub/media
Con independencia de PolyShell, un directorio que recibe archivos enviados por los visitantes nunca debería ejecutar PHP. Compruebe que su configuración de nginx o Apache rechaza la ejecución de scripts bajo pub/media, y pruébelo en preproducción con un archivo inofensivo. No es una mitigación publicada por Adobe para esta CVE y no sustituye al parche: es un refuerzo general, que reduce el efecto de una futura subida exitosa.
Solución de problemas: los bloqueos frecuentes del procedimiento
«Your requirements could not be resolved to an installable set of packages.» Composer rechaza la versión pedida: un módulo de terceros fija una dependencia, o la restricción de estabilidad de composer.json excluye la versión buscada. El comando composer why-not magento/product-community-edition <version-corregida> nombra el paquete que bloquea. Resuélvalo en preproducción, nunca en producción.
«Please upgrade your database: Run "bin/magento setup:upgrade" from the Magento root directory.» La tienda muestra este mensaje tras actualizar el código: el paso setup:upgrade no se ejecutó, o falló. Vuelva a lanzarlo y después la compilación.
«Table '…cms_block' doesn't exist» al ejecutar la consulta de Sansec: la instalación usa un prefijo de tabla. Lea el prefijo en la configuración de la tienda y añádalo al nombre de la tabla.
«No such file or directory» con el comando find de pub/media: la carpeta custom_options o customer_address no existe en esta tienda. Anótelo en la tabla; no es ni un fallo ni una prueba de limpieza.
Una tienda que sigue en mantenimiento: compruebe que no quede ningún indicador de mantenimiento y vuelva a lanzar bin/magento maintenance:disable con el usuario propietario de los archivos.
Después de la limpieza: lo que debe rotarse
- Contraseñas de administrador — todas las cuentas de
admin_user, incluidas las que considere sanas. - Claves de API e integraciones — tokens de las integraciones declaradas en la administración, claves de los servicios de terceros (pago, transporte, ERP) guardadas en la configuración.
- Credenciales de base de datos — una nueva contraseña, actualizada en la configuración de la tienda.
- Clave de cifrado — se cambia siguiendo la documentación de Adobe, tras evaluar el efecto sobre los datos ya cifrados.
- Accesos SSH y SFTP — contraseñas, claves SSH autorizadas, cuentas del sistema desconocidas.
- Accesos de alojamiento — panel de control y copias de seguridad, que también dan acceso a los archivos.
El informe fechado que debe entregar a cada cliente
Desplace la tabla
| Columna | Lo que escribe en ella | Por qué |
|---|---|---|
| Versión antes y después | Números leídos por Composer, con fecha y hora | Muestra que el parche APSB26-73 está aplicado |
| Estado congelado | Referencia del snapshot y de la exportación de la base | Permite volver atrás y el examen forense |
| Archivos bajo pub/media | Rutas y fechas de los archivos encontrados, o «ninguno» | Control publicado por Sansec |
| accesson.php | Rutas encontradas, o «ninguna» | Puerta trasera señalada por Sansec |
| cms_block y cms_page | Identificadores listados y veredicto tras la lectura | JavaScript inyectado servido a los visitantes |
| Cuentas de administración | Cuentas desconocidas desactivadas, o «ninguna» | Acceso dejado por el atacante |
| Accesos rotados | Secretos cambiados y fecha del cambio | Cierra lo que el atacante haya podido copiar |
| No verificado | Lo que no pudo revisar, y por qué | Un estado honesto vale más que un «todo va bien» |
Lo que usted conserva y las fuentes que citar
Cuando se descubre que una tienda está comprometida, es a la agencia a quien llama el cliente. Conserve ese papel: usted lleva la relación, el diagnóstico y el informe fechado; la plataforma lleva la infraestructura, el acceso root al VPS que permite lanzar estos controles y el snapshot antes de intervenir. No modificamos el código de una tienda en su lugar: la actualización de Magento sigue siendo tarea de la agencia. Conserve también la plantilla de la tabla: el próximo fallo que afecte a una tienda seguirá la misma secuencia, con una línea más en el inventario.
Fuentes primarias:
Ficha de la NVD de CVE-2026-48356
Boletín de Adobe APSB26-73
Alerta de la CISA del 27 de octubre de 2026
Sansec, oleada masiva de PolyShell
Sansec, cargador JavaScript en cms_block