2021-09-30 18:44:40 +00:00
|
|
|
\documentclass[12pt, a4paper]{article}
|
|
|
|
\usepackage[spanish]{babel}
|
|
|
|
|
|
|
|
\title{Inyección SQL}
|
|
|
|
\author{Nicolás A. Ortega Froysa}
|
|
|
|
|
|
|
|
\begin{document}
|
|
|
|
\maketitle
|
|
|
|
|
|
|
|
\section{Introducción}
|
|
|
|
Una \textit{inyección SQL} es una especie de ataque cibernético en que se
|
|
|
|
inyecta código SQL malicioso en una entrada de datos de un formulario. De esta
|
|
|
|
forma, el atacante puede correr peticiones arbitrarias en la base de datos, y
|
|
|
|
así conseguir información de ella, insertar información errónea, corromper los
|
|
|
|
datos, o incluso borrar información importante.
|
|
|
|
|
|
|
|
Es un ataque común en sistemas web que hacen uso de una base de datos, y
|
|
|
|
especialmente cuando permiten interacción (indirecta) entre el usuario y la base
|
|
|
|
de datos (e.g.\ formularios de entrada).
|
|
|
|
|
2021-10-04 14:29:36 +00:00
|
|
|
\section{Peticiones SQL Erróneas}
|
2021-09-30 18:44:40 +00:00
|
|
|
Cuando se escribe una petición SQL, se hace combinando en una misma sentencia
|
2021-10-04 14:29:36 +00:00
|
|
|
los datos y los comandos. A menudo, cuando se crean aplicaciones que interactuan
|
|
|
|
con una base de datos, las entradas de los formularios se insertan
|
|
|
|
\textit{verbatim} en la petición SQL. Cuando ocurre esto, un mal actor puede
|
|
|
|
aprovecharse para inyectar un carácter de escape, y luego correr los comandos
|
|
|
|
que quiera (i.e.\ ejecución de código arbitrario).
|
2021-09-30 18:44:40 +00:00
|
|
|
|
2021-10-04 14:29:36 +00:00
|
|
|
Por ejemplo, imaginemos un comando SQL que busque si existe un determinado
|
|
|
|
usuario (asumimos que \texttt{PASSWD()} hace el \textit{hash}):
|
2021-09-30 18:44:40 +00:00
|
|
|
|
2021-10-04 14:29:36 +00:00
|
|
|
\begin{verbatim}
|
|
|
|
SELECT * FROM Users WHERE
|
|
|
|
username="nortega" AND password=PASSWD("MyPasswd");
|
|
|
|
\end{verbatim}
|
2021-09-30 18:44:40 +00:00
|
|
|
|
2021-10-04 14:29:36 +00:00
|
|
|
Esto, normalmente sólo escogería la entrada del usuario \textit{nortega}, y sus
|
|
|
|
datos. Mas, si uno quisiera conseguir todos los datos de todos los usuarios,
|
|
|
|
podría insertar en el formulario de usuario: \texttt{nortega"\ OR 1=1; --}. Al
|
|
|
|
hacer esto, el comando terminaría siendo:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
SELECT * FROM Users WHERE
|
|
|
|
username="nortega" OR 1=1;
|
|
|
|
-- AND password=PASSWD("MyPasswd");
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
Por lo tanto, la contraseña quedaría ignorada (como comentario), y como la
|
|
|
|
condición \texttt{1=1} siempre es verdad, terminaría por devolver todas las
|
|
|
|
entradas de la tabla \texttt{Users}.
|
|
|
|
|
|
|
|
Para evitar esto, se pueden user ciertas funciones en lenguajes como PHP (e.g.
|
|
|
|
\texttt{mysqli\_escape\_string()}) para \textit{escapar} aquellos caracteres que
|
|
|
|
puedan usarse para hacer este tipo de inyecciones (e.g.\ añadiendo un
|
|
|
|
\texttt{\textbackslash} antes del carácter para escapar el \textit{string}).
|
|
|
|
Entonces el comando pasaría a ser lo siguiente:
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
SELECT * FROM Users WHERE
|
|
|
|
username="nortega\" OR 1=1; --"
|
|
|
|
AND password=PASSWD("MyPasswd");
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
\section{Inyección SQL Ciega}
|
|
|
|
Similarmente al caso anterior, la inyección ciega ocurre cuando la página o
|
|
|
|
aplicación no muestra directamente la información de la base de datos, pero sí
|
|
|
|
se mostraría de manera diferente cuando se cumple una condición. Por ejemplo,
|
|
|
|
con el mismo código del caso anterior, si suponemos que el código se ejecuta en
|
|
|
|
un formulario de \textit{login}, si el número de entradas es igual a 1, entonces
|
|
|
|
acepta entrada en la cuenta. En cuyo caso, con añadir la condición
|
|
|
|
\texttt{LIMIT 1}, ya entraría en la primera cuenta que encuentra (que
|
|
|
|
normalmente es la cuenta del administrador).
|
|
|
|
|
|
|
|
\begin{verbatim}
|
|
|
|
SELECT * FROM Users WHERE
|
|
|
|
username="nortega" OR 1=1 LIMIT 1;
|
|
|
|
-- AND password=PASSWD("MyPasswd");
|
|
|
|
\end{verbatim}
|
|
|
|
|
|
|
|
Esto se evita de la misma manera que en la sección anterior.
|
|
|
|
|
|
|
|
\section{Inyección SQL De Segundo Orden}
|
|
|
|
Supongamos que todos los formularios vienen con salvaguardas para evitar las
|
|
|
|
inyecciones SQL. Aún así, es posible implementar un ataque más sutil que no
|
|
|
|
afecte inmediatamente la base de datos, sino que lo afecte luego. En estos
|
|
|
|
casos, la SQL del formulario se ejecuta correctamente, guardando el código SQL
|
|
|
|
inyectado apropiadamente como un dato, para que luego sea usado y ejecutado
|
|
|
|
erróneamente como código SQL. De este modo, podríamos decir que los casos
|
|
|
|
anteriores eran inyecciones de primer nivel, ya que se ejecutaban inmediatamente
|
|
|
|
del formulario, mientras que las inyecciones de segundo nivel son aquellos que
|
|
|
|
se ejecutarán más tarde.
|
2021-09-30 18:44:40 +00:00
|
|
|
|
|
|
|
\end{document}
|