Skip to main content
Category

Desarrollo de Software

Inyección de SQL (SQL Injection)

By Desarrollo de Software

SQL Injection: Una vulnerabilidad crítica que amenaza la seguridad de tus aplicaciones web

La inyección de SQL (SQL injection, en inglés) es una técnica de ataque informático que consiste en aprovechar una vulnerabilidad en una aplicación o sistema web que interactúa con una base de datos mediante consultas SQL. La vulnerabilidad permite que un atacante pueda insertar sentencias SQL maliciosas en los campos de entrada de la aplicación (comúnmente formularios), engañando al sistema para que ejecute estos comandos de forma no deseada.

El objetivo principal de un ataque de inyección de SQL es obtener acceso no autorizado a la base de datos o extraer información confidencial almacenada en ella. Los atacantes pueden manipular las consultas SQL existentes o agregar nuevas consultas para llevar a cabo acciones maliciosas, como la modificación o eliminación de datos, la obtención de información confidencial o incluso el control total del sistema.

A modo de ejemplo, supongamos que tienes un formulario de inicio de sesión en una aplicación web que utiliza consultas SQL para verificar las credenciales del usuario en una base de datos. El código subyacente podría ser similar a este:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM usuarios WHERE nombre_usuario='$username' AND contraseña='$password'";                                    

En este caso, el código toma los valores de usuario y contraseña ingresados por el usuario a través del formulario y los concatena directamente en la consulta SQL. Sin embargo, esto es peligroso porque permite la posibilidad de una inyección de SQL.

Un atacante podría aprovechar esta vulnerabilidad ingresando una entrada maliciosa en el campo del nombre de usuario. Por ejemplo, si el atacante ingresa ‘ OR ‘1’=’1′ # como nombre de usuario y no ingresa ninguna contraseña, la consulta SQL resultante sería:

SELECT * FROM usuarios WHERE nombre_usuario='' OR '1'='1' #' AND contraseña=''";

La validación OR ‘1’=’1′ siempre dará como resultado TRUE, por lo que se realizará el inicio de sesión, además, el carácter # comentará el resto de la consulta (en el caso de mysql), para que esto no cause inconvenientes al momento de iniciar sesión.

Para evitar este tipo de vulnerabilidades, es fundamental utilizar técnicas de mitigación, como las consultas parametrizadas. Esta técnica permite separar los datos de la consulta SQL, evitando así la posibilidad de inyección de código.

Por ejemplo, utilizando consultas parametrizadas, el código se vería de la siguiente manera:

$username = $_POST['username'];
$password = $_POST['password'];

$query = "SELECT * FROM usuarios WHERE nombre_usuario=? AND contraseña=?";
$stmt = $mysqli->prepare($query);
$stmt->bind_param("ss", $username, $password);
$stmt->execute();

En este caso, en lugar de concatenar los valores directamente en la consulta SQL, utilizamos marcadores de posición (?) y luego vinculamos los valores reales a través del método bind_param(). Esto asegura que los datos ingresados por el usuario se traten como valores, y no como parte de la consulta en sí.

Al utilizar consultas parametrizadas se reduce drásticamente el riesgo de inyección de SQL, ya que la base de datos trata los valores proporcionados como datos, y no como parte de la consulta. Esto ayuda a mantener la seguridad de la aplicación y proteger los datos sensibles de los usuarios.

Sumado a lo anterior, y aunque es importante estar consciente de este tipo de vulnerabilidades, gracias a la alta presencia de librerías y frameworks en los lenguajes de programación más utilizados actualmente, cada vez es más fácil evitar esta vulnerabilidad.

<solutionops-team> Autor: Jonathan Urrutia </solutionops-team>

Diferencias entre CNAME y registro DNS tipo A

By Desarrollo de Software

Entendiendo las diferencias clave en la configuración de tu infraestructura web

Al trabajar con la gestión DNS de un dominio podemos sin duda encontrarnos con los términos CNAME y registro de DNS tipo A. Ambos son registros utilizados para asociar un nombre de dominio con una dirección IP, pero tienen diferencias importantes. En este artículo, exploraremos de manera resumida las diferencias clave entre un CNAME y un registro DNS tipo A.

¿Qué es un registro DNS tipo A?

Es el registro básico y común en DNS. Vincula un nombre de dominio con una dirección IP específica. Cuando se ingresa el nombre de dominio en el navegador, este tipo de registro resuelve la solicitud y la envía al servidor correspondiente utilizando la dirección IP asociada.

¿Qué es un CNAME?

Es un registro que apunta un nombre de dominio a otro nombre de dominio en lugar de una dirección IP. Se utiliza para crear alias o redirigir un nombre de dominio a otro servidor sin cambiar la dirección IP en múltiples registros DNS tipo A.

Diferencias clave entre CNAME y registro DNS tipo A:

Destino de la resolución: El registro DNS tipo A apunta directamente a una dirección IP, mientras que un CNAME apunta a otro nombre de dominio.

Número de resoluciones: Un registro DNS tipo A requiere una única resolución para llegar a la dirección IP deseada, mientras que un CNAME puede requerir múltiples resoluciones si el nombre de dominio de destino tiene otros CNAME o registros DNS tipo A asociados.

Uso y flexibilidad: Los registros DNS tipo A son ideales para asignar un nombre de dominio a una dirección IP específica, mientras que los CNAME son útiles cuando se desea redirigir un nombre de dominio a otro nombre de dominio sin cambiar la dirección IP asociada.

Conclusión:

Tanto los registros DNS tipo A como los CNAME son importantes en la configuración del DNS. El registro DNS tipo A apunta directamente a una dirección IP, mientras que el CNAME apunta a otro nombre de dominio. La elección entre ellos depende de si se necesita asignar una dirección IP específica o redirigir a otro nombre de dominio.

<solutionops-team> Autor: Elias Schotborgh </solutionops-team>

Principales Ceremonias en Scrum

By Desarrollo de Software

Los rituales clave para una gestión ágil y efectiva del desarrollo de proyectos

Scrum, un marco ágil utilizado en proyectos colaborativos, destaca por sus ceremonias, reuniones periódicas que promueven la comunicación, la colaboración y la mejora continua. En este artículo, destacaremos las principales ceremonias de Scrum: Daily Scrum, Sprint Review, Sprint Planning y Sprint Retrospective. Estas ceremonias son fundamentales para el éxito de un proyecto Scrum.

Daily Scrum:

Reunión diaria para sincronizar al equipo y planificar el trabajo del día. Cada miembro comparte progresos, planes y obstáculos. Objetivo: transparencia, colaboración y resolución temprana de problemas.

Sprint Review:

Revisión al final del sprint para mostrar los resultados al cliente y stakeholders. Se presentan las funcionalidades completadas y se recopila el feedback. Oportunidad de evaluar y ajustar el producto según las necesidades del cliente.

Sprint Planning:

Planificación al inicio del sprint. El equipo y el Product Owner seleccionan historias de usuario y estiman el esfuerzo. Objetivo: definir el objetivo del sprint y las tareas necesarias para alcanzarlo.

Sprint Retrospective:

Reflexión al final del sprint para mejorar continuamente. Se analizan éxitos, desafíos y se identifican acciones de mejora. Fomenta el aprendizaje y la adaptación para sprints futuros.

Las ceremonias en Scrum, como el Daily Scrum, la Sprint Review, la Sprint Planning y la Sprint Retrospective, son fundamentales para el éxito de los proyectos ágiles. Estas reuniones promueven la colaboración, la transparencia y la mejora continua del equipo. Utilizadas de manera efectiva, los equipos Scrum optimizan su productividad, entregan valor y se adaptan rápidamente a los cambios en el proyecto.

<solutionops-team> Autor: Elias Schotborgh </solutionops-team>

Leer Correos de Gmail con PHP (IMAP)

By Desarrollo de Software

Entendiendo las diferencias clave en la configuración de tu infraestructura web

En PHP existe un módulo llamado IMAP (Internet Message Access Protocol) dedicado a las conexiones a correos, este módulo contiene un conjunto de funciones que nos ayudan a realizar esta tarea fácilmente.

Pero antes tenemos que cambiar las siguientes configuraciones en nuestra cuenta de Gmail y google para permitir a una aplicación externa conectarse.

Primero debemos crear una contraseña de aplicaciones en nuestra cuenta de google para esto activaremos la verificación en 2 pasos, una vez activada la verificación en 2 pasos, volvemos a ingresar a y creamos la contraseña de aplicaciones, en el campo app selecciona otro y luego deberás indicar una pequeña descripción y te generará una contraseña de 16 caracteres.

La segunda configuración es para que Gmail nos permita conectarnos por el protocolo IMAP. Basta con que vayamos a la configuración de Gmail en la sección de Reenvío y correo POP/IMAP, buscamos la opción Acceso IMAP, marcamos Habilitar acceso IMAP y guardamos cambios.

El siguiente código realiza la conexión a una cuenta de Gmail por medio del protocolo IMAP y a la vez obtiene los asuntos de todos los correos.

Funciones almacenadas en MySQL

By Desarrollo de Software

Mejorando la eficiencia y modularidad de tus consultas SQL

Una función almacenada, también conocida como simplemente función, es un conjunto de instrucciones o bloques de código SQL que se almacenan en una base de datos y pueden ser invocados o llamados en diferentes momentos para realizar tareas específicas. Puede recibir cero o varios parámetros y siempre retorna un valor como resultado. Normalmente, se utiliza mediante una sentencia SELECT o dentro de una expresión.

Para crear una función almacenada se utiliza la sentencia CREATE FUNCTION. A continuación, se presenta un ejemplo de función creada en MySQL, la cual retornará la cantidad de días hábiles entre dos fechas (total de días sin contar fin de semana).

DELIMITER //

CREATE FUNCTION CalcularDiasHabiles(fechaInicio DATE, fechaFin DATE)
RETURNS INT
NO SQL
BEGIN
    DECLARE diasHabiles INT DEFAULT 0;
    DECLARE fechaActual DATE;

    SET fechaActual = fechaInicio;

    WHILE fechaActual <= fechaFin DO
        IF WEEKDAY(fechaActual) NOT IN (5, 6) THEN
            SET diasHabiles = diasHabiles + 1;
        END IF;

        SET fechaActual = fechaActual + INTERVAL 1 DAY;
    END WHILE;

    RETURN diasHabiles;
END //

DELIMITER ;

Como se puede observar, una función almacenada contiene múltiples elementos que pasaremos a detallar a continuación:

  • ‘DELIMITER //’ se utiliza para cambiar el delimitador de sentencias a // en lugar del punto y coma (;) predeterminado, para permitir que la función almacenada contenga sentencias múltiples.
  • ‘CREATE FUNCTION CalcularDiasHabiles(fechaInicio DATE, fechaFin DATE)’ crea la función almacenada llamada «CalcularDiasHabiles» que toma dos parámetros: «fechaInicio» y «fechaFin» de tipo DATE.
  • ‘RETURNS INT’ indica que la función retornará un valor entero.
  • ‘NO SQL’ indica que la función no accede a la base de datos ni modifica datos.
  • ‘BEGIN’ marca el comienzo del bloque de código de la función.
  • ‘DECLARE diasHabiles INT DEFAULT 0;’ declara una variable llamada «diasHabiles» de tipo entero y la inicializa en 0.
  • ‘DECLARE fechaActual DATE;’ declara una variable llamada «currentDate» de tipo DATE para almacenar la fecha actual durante el bucle.
  • ‘SET fechaActual = fechaInicio;’ asigna el valor de «fechaInicio» a la variable «currentDate».
  • ‘WHILE fechaActual ≤ fechaFin DO’ establece un bucle mientras «currentDate» sea menor o igual que «fechaFin».
  • ‘IF WEEKDAY(fechaActual) NOT IN (5, 6) THEN’ verifica si el día de la semana de «fechaActual » no es sábado (5) ni domingo (6).
  • ‘SET diasHabiles = diasHabiles + 1;’ incrementa en 1 el valor de la variable «diasHabiles» si el día actual no es fin de semana.
  • ‘SET currentDate = currentDate + INTERVAL 1 DAY;’ incrementa la fecha actual en un día.
  • ‘END WHILE;’ marca el fin del bucle.
  • ‘RETURN diasHabiles;’ devuelve el valor de la variable «diasHabiles».
  • ‘END //’ marca el fin del bloque de código de la función.
  • ‘DELIMITER ;’ restaura el delimitador de sentencias predeterminado (;).

Para ejecutar la función almacenada, esta se debe llamar de la siguiente forma:

SELECT CalcularDiasHabiles('2023-06-01', '2023-06-30');

Lo que devolverá un total de 22 días.

<solutionops-team> Autor: Jonathan Urrutia </solutionops-team>

Funcionamiento Básico de Redes Neuronales

By Desarrollo de Software

Un viaje al interior de las Redes Neuronales: Entendiendo su funcionamiento básico

Las redes neuronales son modelos matemáticos inspirados en el cerebro humano, utilizados en el campo de la inteligencia artificial. Se componen de tres partes principales: las capas de entrada, las capas ocultas y la capa de salida.

Capa de entrada:

Es la primera capa de la red y recibe los datos de entrada, como imágenes, texto o sonido. Cada dato se representa mediante nodos llamados neuronas artificiales.

Capas ocultas:

Estas capas están intermedias entre la capa de entrada y la capa de salida. Cada neurona en las capas ocultas procesa la información recibida y la envía a las siguientes capas mediante conexiones ponderadas.

Capa de salida:

Es la última capa de la red y produce la respuesta final o predicción. Puede ser una única neurona o varias, dependiendo del tipo de problema.

El funcionamiento básico de una red neuronal implica el procesamiento de los datos de entrada a través de múltiples etapas de cálculo. Cada neurona realiza una operación que incluye la suma ponderada de las entradas y la aplicación de una función de activación, que determina si la neurona se activa o no. La función de activación puede ser, por ejemplo, la función sigmoide o la función ReLU.

Durante el entrenamiento de la red, se ajustan los pesos y las conexiones entre las neuronas para minimizar la diferencia entre las salidas reales y las deseadas. Esto se logra mediante el uso de algoritmos de optimización, como el descenso del gradiente, que buscan encontrar los valores óptimos de los pesos para obtener predicciones precisas en nuevos datos.

En resumen, una red neuronal consta de capas de entrada, capas ocultas y una capa de salida. Procesa los datos de entrada a través de múltiples etapas de cálculo, utilizando conexiones ponderadas y funciones de activación. Durante el entrenamiento, los pesos se ajustan para mejorar la precisión de las predicciones. Las redes neuronales son una poderosa herramienta en el campo de la inteligencia artificial, con aplicaciones en áreas como el reconocimiento de imágenes, el procesamiento del lenguaje natural y la conducción autónoma.

<solutionops-team> Autor: Fabián Pérez </solutionops-team>

Referencias

Aprendizaje automático iconos creados por Flat Icons – Flaticon

Red neuronal iconos creados por Vectors Tank – Flaticon

Triggers en SQL

By Desarrollo de Software

Automatizando acciones en tu base de datos: Explorando los Triggers en SQL

Los TRIGGERS en SQL son un componente de la base de datos que se activa automáticamente cuando ocurren ciertos eventos o cambios en la base de datos. Estos eventos pueden incluir operaciones de inserción, actualización o eliminación que se realizan en tablas específicas.

Funcionamiento de los Triggers

Un trigger consta de un conjunto de instrucciones SQL y se asocia con una tabla en específico. Cuando ocurre un evento que dispara el trigger, se ejecutan las instrucciones definidas en el mismo.

Por ejemplo, supongamos que tenemos una tabla con el campo fecha y queremos mantener un formato en específico. Podemos crear un trigger que se ejecute antes de que se inserte en la tabla.

CREATE TRIGGER formatear_fecha

-- BEFORE para que se ejecute antes de insertar
BEFORE INSERT

-- Asigna el trigger a una tabla
ON nombre_tabla

-- Se ejecuta por cada fila que se inserte
FOR EACH ROW

-- Instrucciones que ejecutará el trigger
BEGIN
    SET NEW.fecha = DATE_FORMAT(NEW.fecha, '%Y-%m-%d');
END;

La instrucción “SET NEW.fecha” asigna a la columna «fecha» el valor formateado utilizando la función DATE_FORMAT, que convierte la fecha en el formato deseado (en este caso, ‘YYYY-MM-DD’).

Al utilizar este trigger, cada vez que se inserte una fila en la tabla, la fecha se formateará automáticamente antes de ser almacenada en la base de datos, asegurando que siga el formato indicado.

<solutionops-team> Autor: Jojan Cardenas </solutionops-team>

Controlando el Acceso a Recursos Externos: Una Guía Completa sobre CORS en Node.js

By Desarrollo de Software

Asegurando tu Aplicación Web con Cross-Origin Resource Sharing y el Paquete CORS en Node.js

Las CORS (Cross-Origin Resource Sharing) son una política de seguridad implementada en los navegadores web para controlar las solicitudes de recursos entre diferentes dominios. Permiten que un servidor especifique qué dominios externos tienen permiso para acceder a sus recursos a través de JavaScript.

Funcionamiento de los Triggers

Para habilitar CORS en Node.js, puedes usar el paquete cors. Primero, instala el paquete ejecutando npm install cors. Luego, en tu aplicación Node.js, puedes agregar el middleware de CORS de la siguiente manera:

const express = require('express');
const cors = require('cors');

const app = express();
app.use(cors());

// Rutas y lógica de tu aplicación

app.listen(3000, () => {
 	console.log('Servidor iniciado en el puerto 3000');
});

Esto permitirá solicitudes de cualquier origen. Si deseas restringir el acceso solo a dominios específicos, puedes proporcionar opciones adicionales al middleware de CORS:

app.use(cors({
  origin: 'https://example.com' // Cambia esto al dominio permitido
}));

De esta manera, solo se permitirán solicitudes desde el dominio especificado. Puedes proporcionar una matriz de dominios si deseas permitir múltiples orígenes. Recuerda que CORS es una medida de seguridad en el navegador y no debe ser la única capa de seguridad en tu aplicación. También debes implementar otras medidas de seguridad en el lado del servidor.

<solutionops-team> Autor: Ramon Duran </solutionops-team>

Exploración de datos: importancia y técnicas básicas

By Desarrollo de Software

Descubriendo el Valor Oculto: Técnicas Esenciales de Exploración de Datos

La exploración de datos es una etapa fundamental en el proceso de análisis de datos. Antes de sumergirnos en modelos complejos y algoritmos avanzados, es esencial comprender los datos que tenemos a nuestra disposición. La exploración de datos nos brinda una comprensión inicial de la información, nos ayuda a identificar patrones, detectar anomalías y formular preguntas relevantes. En este artículo, exploraremos la importancia de la exploración de datos y presentaremos algunas técnicas básicas para llevarla a cabo de manera efectiva.

La importancia de la exploración de datos

La exploración de datos nos permite familiarizarnos con los conjuntos de datos que estamos utilizando. Nos ayuda a comprender la estructura de los datos, identificar la calidad de la información y evaluar su idoneidad para el análisis que deseamos realizar. Además, la exploración de datos nos permite descubrir patrones interesantes, relaciones y posibles tendencias que pueden ser clave para la toma de decisiones informadas.

Técnicas básicas de exploración de datos

Visualización de datos: La visualización de datos es una herramienta poderosa para comprender la distribución y las características de los datos. Gráficos como histogramas, diagramas de dispersión y gráficos de barras nos ayudan a identificar patrones, valores atípicos y correlaciones entre variables.

  • Estadísticas descriptivas:

    Las estadísticas descriptivas nos proporcionan medidas resumidas de los datos. Esto incluye la media, la mediana, la desviación estándar y los percentiles. Estas medidas nos ayudan a comprender la centralidad, dispersión y forma de los datos.

  • Análisis de correlación:

    El análisis de correlación nos permite identificar la relación entre dos variables. Al calcular el coeficiente de correlación, podemos determinar si existe una relación lineal positiva, negativa o nula entre las variables.

  • Manejo de valores faltantes:

    Los valores faltantes son comunes en los conjuntos de datos. Durante la exploración, es importante identificar y manejar adecuadamente los valores faltantes. Esto puede implicar eliminar las filas o columnas con valores faltantes, imputar los valores faltantes o utilizar técnicas más avanzadas, como el algoritmo de imputación múltiple.

  • Detección de valores atípicos:

    Los valores atípicos son observaciones inusuales que difieren significativamente del resto de los datos. La detección de valores atípicos nos ayuda a identificar posibles errores en los datos, así como patrones inesperados o eventos excepcionales.

  • Segmentación de datos:

    La segmentación de datos implica dividir el conjunto de datos en grupos o segmentos más pequeños. Esto nos permite analizar subconjuntos específicos de datos y encontrar patrones más precisos y significativos en cada segmento.

Conclusión

La exploración de datos es una etapa crucial en el proceso de análisis de datos. A través de técnicas como la visualización, el análisis de correlación y la detección de valores atípicos, podemos obtener información valiosa sobre nuestros datos antes de aplicar técnicas más avanzadas. La exploración de datos nos ayuda a comprender la naturaleza de los datos, descubrir patrones y tendencias, y formular preguntas relevantes para guiar nuestro análisis. Al invertir tiempo en la exploración de datos, estamos sentando las bases para un análisis más riguroso y una toma de decisiones más informada.

<solutionops-team> Autor: Fabián Pérez </solutionops-team>

Dockerizando Node.js: Empaquetando tu Proyecto de Node.js en un Contenedor

By Desarrollo de Software
  1. Crea un archivo llamado Dockerfile en la raíz de tu proyecto. Este archivo contendrá las instrucciones para construir la imagen de Docker.
  2. Abre el archivo Dockerfile en un editor de texto y configura tu dockerfile.
# Establece la imagen base
FROM node:16

# Establece el directorio de trabajo dentro del contenedor
WORKDIR /app

# Copia el archivo package.json y package-lock.json a /app
COPY package*.json ./

# Instala las dependencias del proyecto
RUN npm install

# Copia el resto del código fuente al directorio de trabajo actual
COPY . .

# Expone el puerto que tu aplicación Node.js utiliza
EXPOSE 3000

# Comando para ejecutar tu aplicación cuando se inicie el contenedor

CMD ["node", "app.js"]
  1. Guarda y cierra el archivo Dockerfile.
  2. Abre una terminal en el directorio raíz de tu proyecto y ejecuta el siguiente comando para construir la imagen de Docker:
    docker build -t nombre_imagen .
  3. Reemplaza «nombre_imagen» con el nombre que quieras asignarle a tu imagen de Docker. El punto al final del comando indica que el contexto de construcción es el directorio actual.
  4. Una vez que la imagen se haya construido correctamente, puedes ejecutar un contenedor basado en esa imagen con el siguiente comando:
    docker run -p 3000:3000 nombre_imagen

Esto ejecutará el contenedor y redirigirá el puerto 3000 del contenedor al puerto 3000 de tu máquina host. ¡Listo! Ahora tu proyecto de Node.js está dockerizado y se puede ejecutar en un contenedor de Docker.

<solutionops-team> Autor: Ramon Duran </solutionops-team>

× ¿En qué podemos ayudarte?