# EV-003 - Integridad selectiva de PrestaShop

**Ventana:** 2026-09-14, desde las 11:57 CEST  
**Ejecución:** comparación local en PASCAL y lecturas estáticas en `vps-90041654.vps.ovh.net` como `centos`, sin elevación  
**Naturaleza:** hashes y fragmentos mínimos redactados; no contiene secretos ni código completo

## Referencia oficial

Se descargó únicamente en una carpeta temporal local el archivo de la etiqueta oficial `1.6.0.14` del repositorio `PrestaShop/PrestaShop`. La etiqueta apunta al commit abreviado `cc5f69c` y fue publicada el 11 de marzo de 2015. El ZIP obtenido tuvo SHA-256:

```text
a00717fe4116e867093b2a3af45d046cfa2df5355bdc3e38003f20a59ba85205
```

No se ejecutó ningún archivo de la referencia ni de la aplicación remota.

## Comparación selectiva

Coincidieron byte a byte 12 de 14 puntos seleccionados:

```text
index.php                                      coincide
init.php                                       coincide
config/defines.inc.php                         coincide
config/config.inc.php                          coincide
classes/Dispatcher.php                         coincide
classes/Tools.php                              coincide
classes/module/Module.php                      coincide
classes/Hook.php                               coincide
classes/Search.php                             coincide
trastienda/index.php vs. admin-dev/index.php   coincide
webservice/dispatcher.php                      coincide
upload/index.php                               coincide
classes/controller/FrontController.php         difiere, explicado abajo
classes/webservice/WebserviceRequest.php        difiere, explicado abajo
```

`FrontController.php` remoto tiene 1.365 líneas y 50.048 bytes, frente a 1.351 líneas y 49.469 bytes. Los hashes por segmentos demuestran que las líneas remotas 1-163 coinciden con las oficiales 1-163 y las remotas 178-1.365 con las oficiales 164-1.351. La única diferencia es, por tanto, una inserción de 14 líneas dentro de `init()`: calcula el nombre de página y redirige usuarios no autenticados, con una excepción basada en la URI. El comentario está en español y describe la anulación de una redirección tras iniciar sesión. No se observaron cargadores, ejecución de comandos ni descarga remota en ese bloque.

`WebserviceRequest.php` conserva las mismas 1.870 líneas y solo añade dos bytes respecto de la referencia. La comparación por bloques de 100 y luego de 10 líneas aisló la diferencia en la línea 1.512: la instalación encierra entre llaves una expresión de método dinámico (`$object->{...}`), sin cambiar los datos ni el flujo funcional aparente. El resto de bloques coincide con la referencia.

Estas dos divergencias son compatibles con personalizaciones o correcciones locales y no constituyen por sí mismas un indicio de compromiso. La comparación fue selectiva y no certifica todo el árbol.

`classes/Search.php` se añadió después a la muestra porque una excepción reciente apuntaba a una consulta definida allí. Su SHA-256 remoto y oficial es `65331381936f96e2003e829144373f2f2ecb7bf179e01633ff9e4fbb36189809`. La coincidencia descarta una divergencia de ese archivo como explicación del error, pero no permite validar el esquema de base de datos excluido del alcance.

## Módulos de migración

Se identificó `migrationproserver` 4.0.0 bajo la raíz pública. Su `server.php` es un punto de entrada autónomo que:

- comprueba un token literal de 32 caracteres embebido en el archivo; el valor no se mostró ni se conservó;
- ofrece acciones denominadas `Check`, `File` y `Query`;
- puede devolver claves internas de PrestaShop;
- construye una ruta desde entrada codificada por el cliente y lee el archivo si existe;
- decodifica y ejecuta consultas SQL suministradas por la petición.

No se invocó el endpoint, no se probó el token y no se consultó la base de datos. El directorio y los archivos canónicos tienen modo `0777`, no se observó un `.htaccess` propio que deniegue el acceso y la configuración superior de Apache concede acceso general. La accesibilidad externa sigue siendo inferida, no verificada por HTTP.

Además del directorio canónico y de `__migrationproserver`, siete directorios de nombre hexadecimal contienen copias de `migrationproserver/server.php`. Los nueve archivos comparten este SHA-256:

```text
ca9a1264866242980cdbdbc9851dc8c73ee2c7e75a45c39563533238a69fa8cf
```

Otros directorios hexadecimales contienen dos copias de `prestascansecurity` 1.1.5 y una de `popup` 1. Sus nombres y duplicación no prueban una cuarentena ni actividad maliciosa; su procedencia y necesidad operativa no pudieron determinarse sin consultar la base de datos o ejecutar la aplicación.

## ETS Migrate Connector

`ets_migrate_connector` 1.1.0 conserva otro `server.php` direccionable bajo la raíz pública. A diferencia de MigrationPro, su código exige que el módulo esté instalado y activo, que una opción de acceso esté habilitada y que el valor recibido coincida con un token almacenado en configuración. El valor por defecto se genera mediante `Tools::passwdGen(10)` y no está embebido como literal en el punto de entrada. No se leyó el valor configurado.

Una vez superado ese control, el endpoint permite seleccionar tablas existentes con el prefijo de PrestaShop, exportar sus filas, devolver `_COOKIE_KEY_` y metadatos de la instalación, y descargar archivos de entidades predefinidas. Los nombres de archivo pasan por `Validate::isFileName()` y la ruta base procede de estructuras internas; no se observó lectura arbitraria de cualquier ruta como en MigrationPro. El directorio es `apache:apache 0755` y `server.php` es `0644`.

La capacidad de extracción está confirmada por lectura estática. La activación, la opción de acceso, la accesibilidad externa y cualquier uso histórico no se verificaron porque requerirían consultar la base de datos, invocar el endpoint o revisar logs protegidos.

## Cobertura y límites

- Se revisaron metadatos de primer nivel de módulos, temas y `override`; el único override funcional identificado corresponde a pedidos, junto con un controlador histórico renombrado.
- Los módulos de pago identificados por nombre fueron `bankwire` 1.1.2 y `cashondelivery` 1.0.0. No se observaron primitivas de ejecución, descarga remota u ofuscación en la búsqueda dirigida. Los módulos no forman parte del archivo fuente de la etiqueta usado como referencia y sus hashes no pudieron compararse con ese ZIP.
- En el tema personalizado `ap_funiture`, las coincidencias dirigidas correspondieron a compatibilidad HTML5, conversión UTF-8, redirecciones internas e iframes del editor del slider. No se corroboró una inyección en esa muestra. Las plantillas de documentos refuerzan la presencia de enlaces a CSV bajo `ficheros`, sin probar su acceso externo.
- El override de pedidos solo declara `getCustomerOrders()` y el controlador histórico renombrado solo `initContent()`; no se observaron primitivas peligrosas en ambos archivos.
- La búsqueda por extensión en directorios de carga, imágenes, descargas, caché y logs solo mostró índices defensivos y cachés históricas. Una búsqueda adicional de firmas PHP dentro de archivos con otras extensiones agotó 25 segundos sin devolver coincidencias y es no concluyente.
- No se hizo hashing masivo, no se ejecutó PHP y no se probaron rutas por HTTP.
- No se determinó desde la base de datos qué módulos están habilitados. El punto de entrada directo de MigrationPro existe en disco con independencia de ese estado.