Ir al contenido principal

PHP · SAST

SAST PHP que se ejecuta totalmente sin conexión

Audite Laravel, Symfony, WordPress y PHP legacy contra inyección SQL, XSS, file inclusion y deriva de configuración — sin subir código a la nube de un tercero.

Frameworks y librerías escaneados

Probamos la cobertura mediante fixtures en estos frameworks. Se añaden nuevos patrones en cada release de reglas integradas.

Laravel Symfony WordPress Drupal CodeIgniter Yii CakePHP Slim Phalcon Doctrine Eloquent PDO mysqli Composer PHPMailer Twig Blade

Principales clases CWE detectadas

Estas clases CWE aparecen con mayor frecuencia en bases de código modernas de este lenguaje. StaticCodeAudit incluye reglas dedicadas para cada una, mapeadas a OWASP Top 10 / ISO 27001 / ASVS cuando es pertinente.

CWE-89

Inyección SQL

mysql_query("... " . $_GET['id']), $pdo->query() con concat, Laravel DB::raw() con entrada user, WordPress $wpdb->query con vars sin escapar.

Detectado por la regla SCA: sql_injection_concat

CWE-79

Cross-Site Scripting (XSS)

echo $_GET['name'] sin htmlspecialchars, Twig {{ var|raw }}, WordPress esc_attr faltante en datos user.

Detectado por la regla SCA: xss_raw_html

CWE-78

Inyección de comando OS

system($cmd), exec(), shell_exec(), passthru() con entrada user. Las funciones shell PHP interpretan metacaracteres por defecto.

Detectado por la regla SCA: command_injection_php

CWE-98

File Inclusion (RFI/LFI)

include $_GET['page'] o require con rutas controladas por usuario. Permite lectura arbitraria de archivos, a veces ejecución remota.

Detectado por la regla SCA: path_traversal_os_join

CWE-502

Deserialización insegura

unserialize($_GET['data']) sobre entrada user. La serialización nativa PHP es un vector gadget conocido (phpggc).

Detectado por la regla SCA: unsafe_deserialization

CWE-798

Credenciales hardcoded

Credenciales DB en config.php commiteado, WordPress wp-config.php en repo público, API keys como constantes.

Detectado por la regla SCA: hardcoded_secret

Vulnerable vs. seguro — tres ejemplos rápidos

CWE-89 Detectado por la regla SCA: sql_injection_concat
❌ Vulnerable
// Vulnerable — concatenación directa
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
$result = $mysqli->query($sql);
✅ Seguro
// Seguro — consulta preparada
$stmt = $mysqli->prepare("SELECT * FROM users WHERE id = ?");
$stmt->bind_param("i", $_GET['id']);
$stmt->execute();
CWE-79 Detectado por la regla SCA: xss_raw_html
❌ Vulnerable
// Vulnerable — echo crudo
echo "<p>Hello, " . $_GET['name'] . "</p>";
✅ Seguro
// Seguro — htmlspecialchars con ENT_QUOTES + UTF-8
echo "<p>Hello, " . htmlspecialchars($_GET['name'], ENT_QUOTES, 'UTF-8') . "</p>";
CWE-78 Detectado por la regla SCA: command_injection_php
❌ Vulnerable
// Vulnerable — abuso metacaracteres shell
system("convert " . $_FILES['img']['tmp_name'] . " /var/thumb.jpg");
✅ Seguro
// Seguro — escapeshellarg + forma 2-arg
$src = escapeshellarg($_FILES['img']['tmp_name']);
system("convert {$src} /var/thumb.jpg");

Qué detecta StaticCodeAudit (este lenguaje)

  • Inyección SQL en PDO concat, mysqli sin prepared statements, Laravel DB::raw, WordPress $wpdb concat
  • XSS vía echo crudo, Twig |raw, htmlspecialchars / esc_attr faltantes
  • Inyección de comando en system, exec, shell_exec, passthru, popen
  • File inclusion (LFI/RFI) vía include, require sobre rutas user
  • Deserialización insegura vía unserialize sobre datos user
  • Credenciales hardcoded en config.php, wp-config.php, .env commiteado
  • Config sesión insegura (session.cookie_secure, session.cookie_httponly off)
  • Open redirect vía header("Location: " . $_GET['url'])
  • Path traversal en file_get_contents, fopen con rutas user
  • Cripto insegura (MD5/SHA1, mcrypt deprecado, claves/IV hardcoded)
  • Token CSRF faltante en endpoints POST
  • Display de errores PHP activado en producción (display_errors=On)
  • APIs deprecadas (mysql_*, ereg, split, php-fpm pm.user=root)
  • Misconfiguraciones CI/CD (.gitlab-ci, GitHub Actions, scripts Composer)

¿Quiere saber cómo se mide realmente la calidad de detección? Consulte la metodología completa de benchmarks multilingües (OWASP Benchmark, NIST Juliet, precisión/recall/F1 por lenguaje) →

CVE Test Suite — Laravel y la stdlib de PHP

StaticCodeAudit fue medido contra un CVE Test Suite real: 45 casos reconstruidos a partir de CVE publicadas e históricas, en 8 frameworks y 5 lenguajes. Laravel y la biblioteca estándar de PHP están incluidas.

80,0%
Mejor F1 (Laravel)
100%
Mejor recall
45
CVE Test Suite (total, todos los lenguajes)

Por framework, reconstruido desde CVE

80,0%
Laravel (reconstruido desde CVE)
72,7%
stdlib PHP (reconstruido desde CVE)

Laravel obtiene 100% de precisión con 66,7% de recall; la stdlib de PHP obtiene 80,0% de precisión con 66,7% de recall — sólido, no perfecto: algunas CVE reales históricas de ambos aún se escapan. Desglose completo cross-lenguaje (incluyendo dónde ASP.NET y Express puntúan más bajo) en la <a href="/es/language-benchmarks.php" class="text-primary font-semibold hover:underline">página de benchmarks por lenguaje</a>.

Las vulnerabilidades reales rara vez caben en un solo archivo

Las aplicaciones Laravel dividen la lógica en capas: un controlador recibe la solicitud, un modelo o query builder construye la consulta. Un escáner limitado a un solo archivo a la vez nunca conecta ambos — ve el dato del usuario en OrderController.php y la llamada a base de datos en Order.php, pero nunca la conexión entre ambos. StaticCodeAudit sigue el dato a través de los archivos.

OrderController.php
public function show(Request $request)
{
    $id = $request->query('id');
    return Order::find($id);
}
Order.php
public static function find($id)
{
    return DB::select(
        "SELECT * FROM orders WHERE id = $id"
    );
}

id proviene del query string en el controlador, y llega a la consulta SQL en crudo un archivo después, sin modificar — StaticCodeAudit lo reporta en la línea exacta donde se ejecuta la consulta.

¿Cómo se compara esto con Psalm o Semgrep?

El modo de análisis de taint de Psalm y Semgrep son las dos herramientas que aparecen primero cuando un equipo PHP busca un escáner de seguridad gratuito. Ambas son legítimas, y muchos equipos ya usan una de ellas — esta es una comparación honesta, no una crítica.

Psalm (modo taint)

Gratuito, open source

Analizador estático diseñado principalmente para verificación de tipos, con un modo opcional de análisis de taint que sigue la entrada del usuario hasta sinks peligrosos (SQLi, XSS, inyección de comandos). Motor sólido, pero el modo de seguridad requiere configuración explícita y anotaciones de tipo para ser efectivo, y los hallazgos no se mapean a CWE/ISO 27001/ASVS por defecto.

Semgrep (Community)

Gratuito, motor open source

Motor de coincidencia de patrones que cubre muchos lenguajes, incluido PHP, con un amplio registro de reglas abiertas. El tier gratuito cubre la mayoría de reglas del día a día; el seguimiento de taint entre archivos, los informes de cumplimiento y algunas integraciones empresariales están en los planes de pago de Semgrep.

Comparativa completa StaticCodeAudit vs Semgrep →

Ninguna de las dos se reemplaza al instalar StaticCodeAudit — si Psalm ya cubre lo que su equipo necesita, sigan usándolo. Lo que StaticCodeAudit añade: hallazgos ya mapeados a CWE/OWASP/ISO 27001/ASVS/NIST CSF (un hallazgo listo para un expediente de auditoría, no solo un ID de regla), seguimiento de taint que funciona desde el primer uso sin trabajo previo de anotación de tipos, y 7 lenguajes más cubiertos por el mismo binario — sin un escáner distinto que configurar por lenguaje. Muchos equipos usan ambos.

Audite su código

Audite Laravel, Symfony, WordPress y PHP legacy contra inyección SQL, XSS, file inclusion y deriva de configuración — sin subir código a la nube de un tercero.

Descargar el binario demo Reservar una demo guiada