La seguridad es un concepto interesante y atrae a mucha gente. Desafortunadamente, es un tema complejo e incluso los profesionales se equivocan. Encontré agujeros de seguridad en Google (CSRF), Facebook (más CSRF), varios minoristas en línea importantes (principalmente inyección SQL/XSS), así como miles de sitios más pequeños, tanto corporativos como personales.
Estas son mis recomendaciones:
1) Usar consultas parametrizadas
Las consultas parametrizadas obligan a que los valores pasados a la consulta se traten como datos separados, de modo que el DBMS no pueda analizar los valores de entrada como código SQL. Mucha gente recomendará que escape sus cadenas usando mysql_real_escape_string()
, pero contrariamente a la creencia popular, no una solución general para la inyección de SQL. Tome esta consulta por ejemplo:
SELECT * FROM users WHERE userID = $_GET['userid']
Si $_GET['userid']
se establece en 1 OR 1=1
, no hay caracteres especiales y no se filtrará. Esto da como resultado que se devuelvan todas las filas. O, peor aún, ¿qué sucede si se establece en 1 OR is_admin = 1
? ?
Las consultas parametrizadas evitan que se produzca este tipo de inyección.
2) Valide sus entradas
Las consultas parametrizadas son excelentes, pero a veces los valores inesperados pueden causar problemas con su código. Asegúrate de validar que están dentro del rango y que no permitirán que el usuario actual altere algo que no debería poder.
Por ejemplo, puede tener un formulario de cambio de contraseña que envíe una solicitud POST a un script que cambie su contraseña. Si coloca su ID de usuario como una variable oculta en el formulario, podrían cambiarlo. Enviando id=123
en lugar de id=321
podría significar que cambian la contraseña de otra persona. Asegúrate de que TODO esté validado correctamente, en cuanto a tipo, rango y acceso.
3) Use htmlspecialchars para escapar de la entrada del usuario mostrada
Digamos que su usuario ingresa su "acerca de mí" de la siguiente manera:</div><script>document.alert('hello!');</script><div>
El problema con esto es que su salida contendrá marcas que el usuario ingresó. Tratar de filtrar esto usted mismo con listas negras es simplemente una mala idea. Usa htmlspecialchars
para filtrar las cadenas para que las etiquetas HTML se conviertan en entidades HTML.
4) No use $_REQUEST
Los ataques de falsificación de solicitud entre sitios (CSRF) funcionan haciendo que el usuario haga clic en un enlace o visite una URL que representa un script que realiza una acción en un sitio para el que está conectado. El $_REQUEST
variable es una combinación de $_GET
, $_POST
y $_COOKIE
, lo que significa que no puede notar la diferencia entre una variable que se envió en una solicitud POST (es decir, a través de una input
etiqueta en su formulario) o una variable que se estableció en su URL como parte de un GET (por ejemplo, page.php?id=1
).
Digamos que el usuario quiere enviar un mensaje privado a alguien. Podrían enviar una solicitud POST a sendmessage.php
, con to
, subject
y message
como parámetros. Ahora imaginemos que alguien envía una solicitud GET en su lugar:
sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!
Si estás usando $_POST
, no verá ninguno de esos parámetros, ya que están configurados en $_GET
en cambio. Su código no verá el $_POST['to']
o cualquiera de las otras variables, por lo que no enviará el mensaje. Sin embargo, si está utilizando $_REQUEST
, el $_GET
y $_POST
quedar atrapados, por lo que un atacante puede establecer esos parámetros como parte de la URL. Cuando el usuario visita esa URL, sin darse cuenta envía el mensaje. Lo realmente preocupante es que el usuario no tiene que hacer nada. Si el atacante crea una página maliciosa, podría contener un iframe
que apunta a la URL. Ejemplo:
<iframe src="http://yoursite.com/sendmessage.php?to=someone&subject=SPAM&message=VIAGRA!">
</iframe>
Esto da como resultado que el usuario envíe mensajes a las personas sin darse cuenta de que hicieron algo. Por este motivo, debe evitar $_REQUEST
y usa $_POST
y $_GET
en su lugar.
5) Trata todo lo que te den como sospechoso (o incluso malicioso)
No tienes idea de lo que te está enviando el usuario. Podría ser legítimo. Podría ser un ataque. Nunca confíes en nada que te haya enviado un usuario. Convierta a los tipos correctos, valide las entradas, use listas blancas para filtrar cuando sea necesario (evite las listas negras). Esto incluye cualquier cosa enviada a través de $_GET
, $_POST
, $_COOKIE
y $_FILES
.
Si sigue estas pautas, se encuentra en una posición razonable en términos de seguridad.