Skip Content

A05: Inyeccion (Blog)

¿Que es la inyeccion?

La inyeccion ocurre cuando una entrada no confiable se interpreta como codigo, fragmento de query o comando. En Laravel suele aparecer como inyeccion SQL, inyeccion de comandos y XSS cuando se rompe el escape por defecto de Blade.

Laravel advierte explicitamente que nunca debes pasar input controlado por el usuario a Rule::unique()->ignore(...), porque puede crear riesgo de inyeccion SQL.

Fallo tipico en Laravel (blog)

  • SQL crudo con input interpolado.
  • Uso inseguro de ignore() en validacion.
  • Ejecucion insegura de comandos/shell.
  • Inputs dinamicos inseguros para columnas/ordenamiento al listar posts.
  • Stored XSS al renderizar comentarios como HTML con {!! !!}.

Impacto

  • Robo o corrupcion de datos.
  • Toma de cuenta via scripts inyectados (XSS).
  • Ejecucion remota de codigo via inyeccion de comandos.
  • Impacto de cumplimiento e incident response.

Remediacion en Laravel 12

  • Prefiere Eloquent / Query Builder con bindings.
  • Evita DB::raw() salvo que sea inevitable.
  • Nunca uses input del usuario como nombre de columna, order/sort, expresiones raw o comandos shell sin allowlists estrictas.
  • Usa Form Requests y valida antes de construir la consulta.
  • Mantén Blade escapado por defecto; usa {!! !!} solo para HTML confiable y sanitizado.

Arreglo concreto

Bindings seguros (sin interpolacion de strings):

$query->where('email', $request->string('email'));

Ordenamiento seguro para listados de posts con allowlist:

$allowedSorts = ['title', 'created_at'];
 
$sort = in_array($request->sort, $allowedSorts, true)
? $request->sort
: 'created_at';
 
$query->orderBy($sort);

Evita stored XSS en comentarios (mantén Blade escapado por defecto):

<p>{{ $comment->body }}</p>
 
{{-- Malo: output raw de input no confiable --}}
{{-- <p>{!! $comment->body !!}</p> --}}

Enfoque de patron de diseno

Usa Strategy para reglas de filtrado/ordenamiento seguras en lugar de concatenar fragmentos de query en controllers. Mantiene allowlists y mapeos centralizados, explicitos y testeables.

use Illuminate\Database\Eloquent\Builder;
 
interface SortStrategy
{
public function apply(Builder $query, string $direction = 'desc'): Builder;
}
 
final class SortByCreatedAt implements SortStrategy
{
public function apply(Builder $query, string $direction = 'desc'): Builder
{
return $query->orderBy('created_at', $direction);
}
}
 
final class SortByTitle implements SortStrategy
{
public function apply(Builder $query, string $direction = 'asc'): Builder
{
return $query->orderBy('title', $direction);
}
}
 
// Uso: mapea input del usuario a estrategias conocidas
$sorts = [
'created_at' => new SortByCreatedAt(),
'title' => new SortByTitle(),
];
 
$sortKey = $request->string('sort')->toString();
$sort = $sorts[$sortKey] ?? $sorts['created_at'];
 
$query = $sort->apply($query);

Referencias