PROGRAMMING × CYBERSECURITY × INACAP

FERR FERNANDA

Estudiante de programación y ciberseguridad. Construyo apps web seguras por defecto, con tests, CI y análisis de seguridad en cada repo. Siempre aprendiendo.

Avatar de Fernanda (Ferr) en GitHub

`> whoami`

A NEW ANGLE OF CODE

nombre   →  Ferr (Fernanda)
estudio  →  Programación + Ciberseguridad @ INACAP
enfoque  →  apps web seguras: tests, CI, CodeQL
interés  →  CTF, hacking ético, AppSec, DevSecOps
estado   →  siempre aprendiendo...

Soy Fernanda, pero todos me dicen Ferr. Estudio programación y ciberseguridad en INACAP y paso el rato entre CTFs, líneas de código y música.

  • APIs con Java + Spring Boot y apps con Flask
  • Frontends con React y JavaScript vanilla
  • Apasionada por el ethical hacking
  • Arte digital & pixel-art lover
PROGRAMMING CYBERSECURITY CTF PLAYER PIXEL ART

`> stack`

HERRAMIENTAS
DEL DÍA A DÍA

El combo que uso para construir, romper y aprender.


`> currently learning`

SIEMPRE
APRENDIENDO

arte digital · gaming · música 🎧


`> proyectos`

A NEW ANGLE
OF CODE

Para cada proyecto: qué problema resuelve, cómo usé cada tecnología y qué decisiones de seguridad tomé.

Swagger UI de la API de Clínica con los endpoints de autenticación, historial y pacientes
JAVA · API REST

Clínica: registro de pacientes

El problema
Llevar pacientes e historial clínico en planillas expone datos sensibles y no controla quién puede ver o modificar cada registro.
La solución
Una API REST con autenticación, tres roles (admin, médico y recepción) y validación del RUT chileno: recepción registra pacientes, los médicos escriben el historial y solo admin gestiona usuarios.

Stack:

  • Java 21
  • Spring Boot
  • PostgreSQL
  • Docker
Cómo lo construí

Cómo usé cada tecnología

Spring Boot 3
Estructura en capas (controller → service → repository), DTOs y un manejador global de errores con respuestas consistentes.
Spring Security + JWT
El login entrega un token y cada endpoint exige un rol con @PreAuthorize; las contraseñas se guardan con BCrypt.
PostgreSQL + Flyway
El esquema vive en migraciones versionadas (tablas, índices y datos de desarrollo), así la base se recrea igual en cualquier entorno.
Spring Data JPA
Búsqueda paginada de pacientes por RUT, nombre o email sin escribir SQL a mano.
Docker Compose
Levanta API y PostgreSQL con un comando; imagen multi-stage con usuario no-root, y Compose se detiene si falta un secreto.
JUnit 5 + Mockito
22 tests: validador de RUT, servicio de pacientes y un test de regresión de seguridad.
SpringDoc OpenAPI
Swagger UI para documentar y probar cada endpoint.

Decisiones y seguridad

  • Detecté que el registro de usuarios era público y permitía crearse una cuenta ADMIN: ahora solo un admin puede registrar usuarios, con un test que lo comprueba.
  • Sin credenciales ni JWT secret por defecto: todo se lee de variables de entorno (.env.example).
  • El admin inicial se crea desde una variable de entorno y su contraseña ya no se imprime en los logs.

CI con mvn verify, build de Docker y CodeQL.

Formulario de nueva consulta clínica de MediForm, sección de datos del paciente
PYTHON · WEB

MediForm

El problema
En una ficha de consulta en papel quedan campos sin llenar, los signos vitales alterados pasan desapercibidos y buscar una consulta anterior toma tiempo.
La solución
Un formulario clínico por secciones con validación en el cliente y en el servidor, alertas cuando un signo vital sale de rango, cálculo automático de edad e IMC y búsqueda por nombre o documento.

Stack:

  • Python
  • Flask
  • SQLite
  • pytest
Cómo lo construí

Cómo usé cada tecnología

Flask + Jinja2
Rutas, plantillas y filtros propios (edad, IMC y estado de cada signo vital) usados directamente en el HTML.
SQLite
Persistencia sin servidor externo; todas las consultas van parametrizadas con ?.
Flask-WTF
Protección CSRF en todos los formularios que envían datos.
JavaScript vanilla
Validación en vivo y confirmación de borrado sin scripts inline, compatible con una CSP estricta.
pytest
19 tests: creación de consultas, campos obligatorios, rechazo sin token CSRF, headers de seguridad y configuración.
gunicorn
Servidor de producción para el despliegue (Procfile).

Decisiones y seguridad

  • Debug apagado por defecto y servidor en 127.0.0.1: debug=True en 0.0.0.0 expone la consola de Werkzeug a la red.
  • La app no arranca en producción sin SECRET_KEY.
  • Headers CSP, X-Frame-Options, X-Content-Type-Options y Referrer-Policy en todas las respuestas.
  • Proyecto educativo: no está pensado para datos clínicos reales.

CI con ruff y pytest en Python 3.10 y 3.12, más CodeQL.

Portada de la infografía del ciberataque al Banco de Chile con las cifras del incidente
REACT · CYBERSEC

Infografía: ataque al Banco de Chile 2018

El problema
Los incidentes reales se estudian con textos largos y, muchas veces, con datos que nadie verificó.
La solución
Una infografía interactiva que explica el ataque con la tríada CIA y marca cada afirmación como documentada, hipótesis o no confirmada, con sus fuentes.

Stack:

  • React
  • Vite
  • CSS
  • GitHub Pages
Cómo lo construí

Cómo usé cada tecnología

React
Componentes reutilizables: cronología desplegable, pestañas de la tríada CIA y filtro vulnerabilidad → medidas que la mitigan.
JSON + node:test
Todo el contenido vive en un JSON y los tests verifican que cada referencia a una fuente y cada vínculo vulnerabilidad → medida existan.
Vite + GitHub Actions
Build de producción y despliegue automático en GitHub Pages en cada push.
WAI-ARIA
Pestañas navegables con flechas, acordeón con aria-expanded y filtros con aria-pressed y aria-live.
CSS propio
Estética terminal, estilos de impresión para exportar a PDF y prefers-reduced-motion.

Decisiones y seguridad

  • Contrastar fuentes corrigió la versión original: el malware fue un wiper (KillDisk), no WannaCry, y se quitaron cifras sin respaldo.
  • Verificada con axe-core: 0 violaciones WCAG 2.1 AA.

CI con ESLint, tests de datos y build, más CodeQL.

Simulador de auditoría con los tres principios CIA y el control de acceso por roles
CYBERSEC · CIA

Auditoría CIA

El problema
¿Cómo evitar que un alumno vea datos sensibles de otros, que altere sus notas o que una caída de los sistemas arruine la semana de exámenes?
La solución
Una simulación de controles para cada principio de la tríada CIA en los sistemas de INACAP, en Python y como simulador interactivo en HTML.

Stack:

  • Python
  • hashlib
  • HTML
  • pytest
Cómo lo construí

Cómo usé cada tecnología

Python (biblioteca estándar)
Una clase por principio: control de acceso por roles con log de auditoría, integridad de notas e impacto de un DDoS con plan de continuidad.
hashlib (SHA-256)
Un hash por registro académico detecta cualquier cambio hecho por fuera del sistema; los cambios no autorizados se revierten.
HTML + JavaScript
Versión interactiva para probar roles y recursos desde el navegador.
pytest + ruff
16 tests y lint con reglas de seguridad (bandit) en CI.

Decisiones y seguridad

  • Los tests revelaron que el control de acceso permitía recursos desconocidos (fail-open); ahora deniega por defecto.
  • Un hash sin clave detecta cambios accidentales, pero contra un atacante haría falta un HMAC: queda documentado como mejora.

CI con ruff, pytest y ejecución completa de la simulación.

Inicio de la wiki de inyección SQL con las secciones de aprendizaje
REACT · CYBERSEC

Wiki de Inyección SQL

El problema
La inyección SQL se suele explicar con código que intimida a quien empieza, y sin dejar claro cómo se previene.
La solución
Una wiki con analogías, una simulación que no ejecuta nada y un checklist de prevención, pensada para estudiantes y exposiciones.

Stack:

  • React
  • Vite
  • CSS
Cómo lo construí

Cómo usé cada tecnología

React + Vite
Siete secciones navegables, búsqueda global con Ctrl/Cmd + K, modo claro/oscuro persistente y exportación a PDF.
Simulador propio
Muestra token a token cómo seis payloads clásicos alteran una consulta, sin conectarse a ninguna base de datos.
CSS responsive
Diseño para móvil, tablet y escritorio sin librerías de UI.

Decisiones y seguridad

  • Enseñar el concepto sin publicar material ofensivo funcional.
  • La prevención se centra en consultas parametrizadas; la validación y el escape son capas extra.

CI con ESLint y build, más CodeQL.

Portada del sitio Turismo Extremo Sur con los Cuernos del Paine
HTML · WEB

Turismo Extremo Sur

El problema
Una agencia de turismo aventura de Punta Arenas no tenía dónde mostrar sus rutas y precios ni cómo recibir consultas de reserva.
La solución
Un sitio estático rápido, sin dependencias, con servicios, mapa de ubicación y formulario de contacto validado.

Stack:

  • HTML
  • CSS
  • JavaScript
  • Vercel
Cómo lo construí

Cómo usé cada tecnología

HTML semántico + CSS
Layout responsive con custom properties y menú hamburguesa en móvil.
JavaScript vanilla
Las tarjetas de servicios se generan desde un arreglo de datos, el formulario se valida en el cliente y las animaciones respetan prefers-reduced-motion.
Vercel
Despliegue con headers de seguridad: CSP, X-Frame-Options, Referrer-Policy y Permissions-Policy.

Decisiones y seguridad

  • Para que la CSP prohíba estilos inline, el encuadre de las imágenes pasó de style="..." a CSSOM.
  • El navbar translúcido sobre la aurora animada no cumplía el contraste AA: se le dio fondo oscuro.

CI con ESLint, html-validate y verificación de recursos; axe-core sin violaciones.

Panel de TechStore Manager con el formulario de productos y las métricas de inventario
FULL STACK · REACT

TechStore Manager

El problema
Una tienda de tecnología administraba su inventario a mano, sin una vista rápida del stock, el valor total ni los productos por reponer.
La solución
Un sistema full stack con API REST para el CRUD de productos y un panel en React con métricas de inventario en tiempo real.

Stack:

  • React
  • Express
  • Axios
  • Vercel
Cómo lo construí

Cómo usé cada tecnología

Express
API REST separada en rutas, controladores y middleware; la validación en el servidor (nombre, categoría, precio > 0, stock ≥ 0) es la fuente de verdad.
Middleware propio
Un logger registra método, ruta y hora de cada petición.
React
Componentes (formulario, tabla, estadísticas, notificaciones) con useState, useMemo para las métricas y useCallback para los manejadores.
Axios
Una capa services/api.js centraliza las llamadas y convierte los errores en mensajes legibles para el usuario.
Vercel
Frontend y API desplegados juntos: los rewrites envían /productos a una función serverless que reutiliza la app Express.
node:test
6 tests de la API sin dependencias extra: CRUD completo, validaciones, JSON malformado y headers.

Decisiones y seguridad

  • CORS restringible con la variable FRONTEND_URL y sin la cabecera X-Powered-By.
  • El manejador de errores ya no devuelve err.message al cliente en producción.
  • listen() solo se ejecuta al correr el servidor directamente, para poder testear la app.

CI con tests del backend, ESLint y build del frontend, más CodeQL.

Catálogo de medicamentos con métricas de inventario y estado de vencimiento
PYTHON · DJANGO

Catálogo Farmacia

El problema
En una farmacia, los productos vencidos o por vencer se detectan tarde cuando el inventario vive en una planilla.
La solución
Un CRUD en Django que muestra el valor del inventario, alerta de los productos por vencer en 30 días o ya vencidos y no permite registrar productos con fecha vencida.

Stack:

  • Python
  • Django
  • SQLite / PostgreSQL
  • Vercel
Cómo lo construí

Cómo usé cada tecnología

Django (vistas genéricas)
ListView, CreateView, UpdateView y DeleteView cubren el CRUD; la vista de listado calcula las métricas del inventario.
Django Forms
clean_fecha_vencimiento rechaza fechas pasadas antes de guardar.
ORM + migraciones
SQLite en local y PostgreSQL vía DATABASE_URL en producción, sin cambiar el código.
WhiteNoise
Sirve los archivos estáticos (incluido el admin) en el entorno serverless.
Vercel
Al arrancar se aplican las migraciones y se crea el superusuario desde variables de entorno.
Tests de Django
Listado, creación, eliminación y rechazo de fechas vencidas.

Decisiones y seguridad

  • SECRET_KEY obligatoria en producción: antes, si faltaba, se usaba una clave insegura.
  • Cookies Secure, HSTS y Referrer-Policy cuando DEBUG está apagado; el CI corre manage.py check --deploy.

CI con ruff, tests de Django y chequeos de despliegue, más CodeQL.

Ver todos mis repositorios en GitHub ↗


`> stats`

EN NÚMEROS

Las estadísticas se actualizan automáticamente desde la API pública de GitHub. Si no cargan, puedes verlas directamente en mi perfil de GitHub ↗.


`> contacto`

HABLEMOS

¿Práctica, CTF colaborativo, feedback o simplemente saludar? Aquí me encuentras.

escuchando lo que sea que me mantenga en modo focus 🎧