← Writeups

UNION-based SQLi en Oracle: fingerprinting de versión vía v$version y banner

Fingerprinting de la versión de Oracle con UNION-based SQLi usando v$version: la vista de la instancia expone el banner del motor en la columna de salida.

1. Target Overview & Vulnerability Summary

El filtro de categoría refleja los resultados de la consulta, permitiendo UNION-based SQLi. En Oracle, la versión de la instancia se lee de la vista fija v$version (columna banner); a diferencia de MySQL/MSSQL no existe una función version() simple en el SELECT de una query normal.

Severidad Endpoint vulnerable Root cause
Medium GET /filter?category=... Concatenación de category en la cláusula WHERE; resultados reflejados en la respuesta

2. Technical Breakdown & Exploitation Flow

  1. Determinar la aridad de la query con UNION SELECT NULL[, NULL...] (2 columnas en este lab).
  2. Leer el banner de la instancia desde v$version:
' UNION ALL SELECT NULL,banner FROM v$version-- -
GET /filter?category=' UNION ALL SELECT NULL,banner FROM v$version-- - HTTP/1.1
Host: 0a...web-security-academy.net

Notas del payload:

  • UNION ALL (en lugar de UNION) evita la deduplicación implícita de filas que aplica Oracle a UNION; es inocuo aquí y evita sorpresas con filas repetidas de v$version.
  • v$version devuelve una fila por componente (Oracle Database, PL/SQL, CORE, TNS). El banner principal identifica edición y versión exacta.

La respuesta refleja el banner y el lab queda resuelto.

3. Root Cause Analysis

La query se interpola sin parámetros:

SELECT column1, column2 FROM products WHERE category = 'Gifts'

Oracle no expone la versión vía una función de un solo valor en la lista SELECT de una query sobre tablas, pero sí a través de las vistas fijas v$*, que son legibles por el rol CONNECT estándar. El atacante encadena UNION ALL SELECT contra v$version y la columna banner se serializa en el HTML. Este fingerprint orienta el dialecto del exploit posterior (diccionario all_tables/all_tab_columns, concatenación ||, FROM dual).

4. Secure Remediation

Parametrización de la query:

String sql = "SELECT column1, column2 FROM products WHERE category = ?";
PreparedStatement stmt = connection.prepareStatement(sql);
stmt.setString(1, category);

Defensa en profundidad: usuario de BD con menor privilegio (sin acceso a vistas fijas si no se requieren) y parametrización como control principal; el rol mínimo elimina la superficie de fingerprint incluso ante una inyección remanente.