Lenguaje PHP

Seguridad en PHP y las últimas mejores practicas

La idea es tener una buena seguridad en PHP y proteger las aplicaciones que desarrollamos de todo tipo de intentos de hackers. Por lo tanto, es el deber prioritario de un buen Desarrollador Web. Si usted, crea programas usando el lenguaje PHP debería de conocer estas estrategias que le ayudara a construir sus aplicaciones web lo suficientemente fuertes para no tener problemas de seguridad.

Ahora, todo desarrollador debe erradicar en lo más mínimo cualquier ataque malicioso en nuestros proyectos.

Seguridad en PHP y las últimas mejores practicas
Seguridad en PHP y las últimas mejores practicas

Seguridad en PHP y las últimas mejores practicas

PHP es un lenguaje muy usado en el mundo del desarrollo web. Sin embargo, que se olvidan de darle seguridad a sus sistemas.

En el tema de seguridad PHP es el lenguaje de código abierto más criticado cuando se trata de seguridad. Un gran porcentaje de desarrolladores piensan que PHP no posee estrategias sólidas para proteger y dar seguridad a las aplicaciones.

Problemas de seguridad en PHP CMS

En el mundo de los CMS, los más populares son WordPress, Joomla, Magento, y Drupal se desarrolló en base del lenguaje PHP y según Sucuri, la mayoría de las vulnerabilidades en PHP CMS salieron a la luz durante el año 2017:

  • a) Los problemas de seguridad de WordPress aumentaron del 74% en 2016 a 83% en 2017.
  • b) Los problemas de Joomla han bajado del 17% en 2016 a 13,1% en 2017.
  • c) Los problemas de seguridad de Magento aumentaron del 6% en el 2016 al 6,5% en 2017.
  • d) Los problemas de seguridad de Drupal cayeron ligeramente de 2% en 2016 a 1,6% en 2017.
CMS infectados del 2017
CMS infectados del 2017

Como observamos en el cuadro la situación actual no es buena. Sin embargo, gracias a estos problemas PHP está tratando de superarlos y hemos visto algunos cambios drásticos últimamente en la versión PHP 7.x que se lanzó el año pasado con varias actualizaciones y correcciones.

La ventaja de la versión PHP 7. x se relaciona básicamente con la seguridad de su núcleo.

¿Que contiene este tutorial de seguridad PHP?

El objetivo principal de este tutorial de seguridad de PHP es hacer que el programador web use las mejores prácticas para la seguridad en aplicaciones web PHP.

La seguridad en el lenguaje PHP

A continuación, defino los siguientes problemas y mencionaré las posibles soluciones.

A) Actualizar PHP regularmente desde su panel de control

  • En el Cpanel podemos cambiar la versión del PHP y en este momento, la versión más estable es PHP 7.3.
  • Le recomiendo que actualice su aplicación PHP a esta nueva versión.
  • Si todavía está utilizando PHP 5,6 entonces usted estará teniendo varios segmentos de códigos en desuso.
Actualizar la versión del PHP
Actualizar la versión del PHP

También tendrá que actualizar el código fuente, conexiones y algunas  funcionales como hash de contraseña, etc. También hay algunas herramientas disponibles para comprobar la degradación de su código y ayudarle a migrar esos.

B) Scripting entre sitios (XSS)

Es un método muy común en el mundo del hackeo. El scripting entre sitios es un ataque Web malintencionado en el que se inyecta un script externo en el código o salida del sitio Web. Por lo tanto, el atacante puede enviar código infectado al usuario final, mientras que el explorador no puede identificarlo como un script de confianza.

Este ataque se produce principalmente en los lugares donde el usuario tiene la capacidad de introducir y enviar datos. El ataque puede acceder a cierta información confidencial, entre ellos tenemos:

  • Las cookies
  • Sesiones de usuarios
  • Otra información sensible sobre el navegador.

Lo más común es mediante una solicitud del método GET que está enviando algunos datos a través de URL. Veamos un ejemplo:

URL: http://ejemplo.com/search.php?search=<script>alert('test')</script>

<?php
//Recibe la informacion enviada desde un formulario
$search = $_GET['search'] ?? null;
echo 'Resultados de la busqueda por: '.$search;
?>
Vulnerabilidad de XSS (Cross Browser Scripting) en aplicaciones web
Vulnerabilidad de XSS (Cross Browser Scripting) en aplicaciones web

Puede evitar este ataque utilizando «htmlspecialchars». También, mediante el uso de «ENT_QUOTES», pueden escapar comillas simples y dobles.

$search = htmlspecialchars($search, ENT_QUOTES, 'UTF-8');
echo 'Search results for '.$search;

Otro método para no ser víctima de este ataque es usar el método POST para enviar la información.

Sin embargo, los ataques XSS también pueden ejecutarse a través de atributos, esquemas de URI codificados y codificación de código.

C) Ataques de inyección SQL

La inyección SQL es el ataque más común en PHP. Una simple consulta de búsqueda puede comprometer todo el sistema web. Por lo tanto, en el ataque de inyección SQL, el atacante intenta alterar los datos que está pasando a través de consultas SQL. Veamos un ejemplo.

Vamos a suponer que estamos procesando una consulta de búsqueda en nuestro sistema. Supongamos que está procesando directamente datos de usuario en consultas SQL y, de repente, un atacante anónimo utiliza en secreto diferentes caracteres para omisión.

Consulte la consulta SQL mencionada a continuación:

$sql="SELECT * FROM usuarios WHERE usuario_nombre='".$usuario_nombre."';

La variable $usuario_nombre puede contener datos alterados por algún hacker y estos datos pueden dañar la base de datos, incluyendo la eliminación de tablas y/o toda la base de datos en el tiempo que dura la consulta SQL.

¿Cuál es la solución para este problema?

La respuesta es simple y estamos hablando del PDO PHP (La extensión Objetos de Datos de PHP).Sin embargo, siempre se recomienda que se use instrucciones preparadas como el PDO.

Ahora, hay que saber que PDO nos ayuda a proteger las consultas SQL usando PHP.

Ataques de inyeccion sql
Ataques de inyeccion sql

D) Ejemplo completo de inyección SQL

Uno de los tipos de inyecciones SQL es el método GET. Veamos un ejemplo del método GET que se envían a través de la dirección URL: http://ejemplo.com/get-user.php?id=1 o id=2;

$id = $_GET['id'] ?? null;

La conexión entre la base de datos y la aplicación se realiza con la siguiente instrucción:

$dbh = new PDO('mysql:dbname=testdb;host=127.0.0.1', 'dbusername', 'dbpassword');

Se puede seleccionar el nombre de usuario basado en el «id» anterior. Por lo tanto, aquí el código SQL ‘ GET Data ‘ se inyecta en la consulta.

Tengamos mucho cuidado de evitar este tipo de codificación y usar instrucciones preparadas tipo PDO en su lugar:

$sql = "SELECT username, email FROM users WHERE id = ".$id." ;
foreach ($dbh->query($sql) as $row) {
   printf ("%s (%s)\n", $row['username'], $row['email']);
}

La solución para evitar inyecciones SQL

Para evitar la posibilidad de inyección de SQL solo tenemos que implementar instrucciones preparadas, veamos el ejemplo a continuación.

$sql = "SELECT username, email FROM users WHERE id = :id";
$sth = $dbh->prepare($sql, [PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY]);
$sth->execute([':id' => $id]);
$users = $sth->fetchAll();

E) Falsificación de solicitud entre sitios XSRF/CSRF

El ataque CSRF es muy diferente a los ataques XSS. En el ataque CSRF, el usuario final puede realizar acciones no deseadas en los sitios web autenticados y puede transferir comandos maliciosos al sitio para ejecutar cualquier acción no deseada.

CSRF no puede leer los datos de solicitud y en su mayoría se dirige a la solicitud de cambio de estado enviando cualquier enlace o datos modificados en etiquetas HTML.

Puede obligar al usuario a realizar solicitudes de cambio de estado, como transferir fondos, cambiar sus direcciones de correo electrónico, etc. Veamos esta URL en la que las solicitudes GET envían dinero a otra cuenta:

GET http://bank.com/transfer.do?acct=TIM&amount=100 HTTP/1.1

Ahora bien, si alguien quiere explotar la aplicación web cambiará la URL con nombre y cantidad como esta

http://bank.com/transfer.do?acct=Sandy&amount=100000

Los métodos que usan los hacker son los siguientes:

  • Por correo electrónico.
  • Descargar un archivo.
  • Visualizar una imagen, etc.

El atacante podría pedirle que descargue el archivo o haga clic en la imagen. Y tan pronto como lo haces, al instante terminas con la transferencia de una gran cantidad de dinero que usted nunca realizo previo consentimiento.

F) Secuestro de sesión

El secuestro de sesión es un tipo particular de ataque web malicioso en el que el atacante roba secretamente el identificador de sesión del usuario.

Ese identificador de sesión se envía al servidor donde la matriz $_Session asociada valida su almacenamiento en la pila y concede acceso a la aplicación. El secuestro de sesión es posible a través de un ataque XSS o cuando alguien obtiene acceso a la carpeta en un servidor donde se almacenan los datos de la sesión.

¿Cómo solucionar este problema de secuestro de sesión?

Para evitar el secuestro de sesión siempre enlazar sesiones a su dirección IP para:

$IP = getenv ( "REMOTE_ADDR" );

Tenga cuidado al trabajar en localhost, ya que no le proporciona los valores de tipo IP, pero :::1 o :::127 exactos. Usted debe invalidar (cookie unset, unset sesión de almacenamiento, eliminar seguimientos) sesión rápidamente cada vez que se produce una infracción y siempre debe tratar de no exponer los identificadores bajo ninguna circunstancia.

Ahora, para las cookies, la mejor práctica es nunca usar serializar datos almacenados en una cookie. Los hackers pueden manipular las cookies fácilmente, lo que resulta en la adición de variables a su alcance.

Elimine de forma segura las cookies como esta:

setcookie ($name, "", 1);
setcookie ($name, false);
unset($_COOKIE[$name]);

La primera línea del código asegura que la cookie expira en el navegador, la segunda línea representa la forma estándar de eliminar una cookie (por lo tanto, no se puede almacenar false en una cookie). La tercera línea elimina la cookie de su script.

G) Cargar archivos de forma segura

La carga de archivos es muy peligroso y también es una parte fundamental de cualquier aplicación de procesamiento de datos de usuario. Pero recuerde que en algunos puntos, los archivos también se utilizan para los ataques XSS como ya he explicado anteriormente en el artículo.

Resolviendo el problema, siempre utilice la solicitud «POST» en los formularios y declare la propiedad (enctype="multipart/form-data") en todas las etiquetas<form> que manejen carga de ficheros. A continuación, valide el tipo de archivo utilizando finfo, veamos el ejemplo:

$finfo = new finfo(FILEINFO_MIME_TYPE);
$fileContents = file_get_contents($_FILES['some_name']['tmp_name']);
$mimeType = $finfo->buffer($fileContents);

Los desarrolladores pueden crear sus propias reglas de validación de archivos personalizada y ultra-seguro, pero algunos frameworks como Laravel, Symfony y CodeIgniter ya tienen métodos predefinidos para validar tipos de archivos.

El HTML del formulario debe ser así:

<form method="post" enctype="multipart/form-data" action="upload.php">
Archivo: <input type="file" name="pictures[]" multiple="true">
<input type="submit">
</form>
Seguridad en formulario upload
Seguridad en formulario upload

Ahora, el fichero upload.php debe de tener el siguiente código para ser seguro:

foreach ($_FILES['pictures']['error'] as $key => $error) {
  if ($error == UPLOAD_ERR_OK) {
     $tmpName = $_FILES['pictures']['tmp_name'][$key];
     $name = basename($_FILES['pictures']['name'][$key]);
     move_uploaded_file($tmpName, "/var/www/project/uploads/$name");
   }
}

Declarar correctamente el UPLOAD_ERR y basename() puede evitar ataques de recorrido de directorio, pero pocas otras validaciones-como el tamaño del archivo.

H) Usar certificados SSL para todos nuestros proyectos web (HTTPS)

Hoy en día por motivos de seguridad casi la mayoría de navegadores entre ellos Google Chrome, opera, Firefox y otros, recomiendan utilizar el protocolo HTTPS para aplicaciones Web.

Los protocolos de seguridad HTTPs proporciona un canal de acceso seguro y cifrado para sitios que no son de confianza. Por lo tanto, para incluir el HTTPS debe de instalar un certificado SSL en su sitio Web.

Este requisito fortalece sus aplicaciones web contra ataques XSS y evita que los hackers para leer los datos transportados utilizando códigos.

Pagina insegura en formulario login
Pagina insegura en formulario login

I) Registrar todos los errores y oculte en producción

Cuando se haya terminado el desarrollado del sitio web e instalado en el servidor. Lo primero que debe hacer es desactivar la visualización de los errores que emite PHP. Por lo tanto, los hackers podrían obtener información valiosa a través de los errores.

La solución para estos problemas es establecer este parámetro en el archivo php.ini, veamos el ejemplo:

display_errors=Off

Ahora, después registre todos los errores en un archivo específico para futuras necesidades:

log_errors=On
error_log=/var/log/httpd/php_scripts_error.log

El nombre de archivo puede darle el nombre que desee.

Lista blanca de IP pública para MySQL

Cuando se trabaja con aplicaciones PHP que con frecuencia necesita configurar la base de datos MySQL en scripts internos, así como en los clientes de MySQL. La mayoría de los clientes se utilizan para configurar la conexión remota de MySQL que necesita la dirección IP u otro nombre de host proporcionar por el servidor de alojamiento para crear la conexión.

CONCLUSIONES DE SEGURIDAD

Las mejores prácticas de seguridad de PHP es un tema muy amplio para tocarlo en un solo artículo y es más cada día aparecen nuevas estrategias para poder vulnerar nuestros sistemas.

Los desarrolladores de todo el mundo tienden a desarrollar diferentes casos de uso para proteger las aplicaciones Web.

Grandes compañías en internet ejecutan diferentes programas de recompensas para descubrir fallos de seguridad y vulnerabilidades en sus aplicaciones y así premiar a aquellos expertos en seguridad que descubren zonas críticas en las aplicaciones.

En este artículo, he detallado algunos problemas básicos de seguridad en PHP, para ayudarle a entender cómo proteger sus proyectos PHP de diferentes ataques maliciosos. 

Nestor Tapia

Bloggero, amante de la programación PHP, innovador y me fascina compartir información. Desde que conocí el entorno informatico y el internet me llamó la atención la programación, Por tal motivo he creado mi blog BAULPHP.COM para compartir mis experiencias con todos ustedes. ¡Gracias por leerme!.

3 comentarios

  1. gracias nestor, tu capacidad para explicar es impresionante como he aprendido con tus articulos veo que tengo que actualizarme en php ahora comienzo a dar unos pasos con la version 7.3 y tropiezo con muchos problemas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba