La candidata número u de la llista prioritzada del Mòdul 3 és una probable injecció SQL a tienda.technova.lab/producto.php?id=, l'aplicació PHP/MySQL de comerç electrònic de TechNova. És també el nostre objectiu principal: la botiga és a Internet i concentra les dades de clients. En aquesta lliçó validem aquesta candidata i recorrem les classes de vulnerabilitat web més rellevants de l'OWASP Top 10 / WSTG, aplicant el cicle controlat de 04-01: mecanisme, PoC de baix impacte i remediació amb codi segur.

Recordatori de l'enquadrament, que aquí és especialment important perquè la botiga gestiona dades personals fictícies: tot passa al laboratori autoritzat de TechNova, dins de l'abast i amb control de l'impacte. No bolquem la base de clients, no esborrem res, no deixem scripts persistents. Cada vulnerabilitat s'ensenya amb el seu mecanisme (per què existeix), una PoC que només demostra (llegir una versió, un id, un valor sentinella) i el seu arranjament. L'objectiu del pentester és reportar i ajudar a corregir, no causar dany.

Contingut

  1. Per què el web és la superfície més exposada
  2. Injecció SQL i la seva automatització responsable (sqlmap)
  3. Cross-Site Scripting (XSS): reflectit i emmagatzemat
  4. Cross-Site Request Forgery (CSRF)
  5. Inclusió de fitxers: LFI i RFI
  6. Pujada de fitxers insegura
  7. IDOR i control d'accés trencat
  8. SSRF (Server-Side Request Forgery)
  9. Deserialització insegura (visió general)
  10. Detecció i eines
  11. Errors comuns i consells
  12. Exercicis
  13. Conclusió

  1. Per què el web és la superfície més exposada

Les aplicacions web estan, per definició, exposades a Internet i processen entrada no confiable de l'usuari en cada petició. Gairebé totes les vulnerabilitats web neixen del mateix pecat original: barrejar dades controlades per l'atacant amb codi o comandes (SQL, HTML, rutes de fitxer, peticions HTTP) sense separar-les correctament. Entendre aquest patró fa que totes les classes següents encaixin.

  1. Injecció SQL i la seva automatització responsable

Mecanisme. La injecció SQL passa quan l'entrada de l'usuari es concatena directament en una consulta SQL. L'atacant escapa del context de "dada" i passa a injectar "codi" SQL.

Codi vulnerable (el producto.php de TechNova):

<?php
// VULNERABLE: el parametre id es concatena sense separar dada de codi
$id = $_GET['id'];
$sql = "SELECT nombre, precio, descripcion FROM productos WHERE id = $id";
$res = mysqli_query($conn, $sql);
?>

Si arriba producto.php?id=1, la consulta és normal. Però si arriba producto.php?id=1 OR 1=1, es converteix en ... WHERE id = 1 OR 1=1, que retorna tots els productes: l'entrada ha canviat la lògica.

PoC de validació de baix impacte. Seguint el marc de 04-01, no bolquem dades: només demostrem que l'entrada s'interpreta com a SQL.

# 1) Prova d'error: una cometa trenca la sintaxi -> confirma injeccio
curl "http://tienda.technova.lab/producto.php?id=1'"
#   -> "You have an error in your SQL syntax..."  (l'entrada arriba al motor)

# 2) Prova booleana: mateixa pagina amb TRUE, diferent/buida amb FALSE
curl "http://tienda.technova.lab/producto.php?id=1 AND 1=1"   # producte visible
curl "http://tienda.technova.lab/producto.php?id=1 AND 1=2"   # producte absent

# 3) Extreure UNA dada inofensiva del motor (la versio), no dades de clients
curl "http://tienda.technova.lab/producto.php?id=-1 UNION SELECT @@version,2,3"
#   -> mostra "5.5.62" al forat del nom: acces confirmat, sense tocar clients

Llegir @@version (que a més confirma el MySQL 5.5.62 de l'inventari) demostra el control sobre la consulta sense extreure ni un sol registre de clients. Això n'hi ha prou per a l'informe.

Automatització responsable amb sqlmap. Per mapar l'abast real (quines bases de dades i taules serien accessibles) es fa servir sqlmap, però de manera controlada:

# Enumerar nomes estructura (bases de dades), sense bolcar contingut sensible
sqlmap -u "http://tienda.technova.lab/producto.php?id=1" --batch --dbs

Ús responsable: enumerar estructura per dimensionar el risc, no --dump-all. Res de --os-shell ni escriptura tret que les RoE ho autoritzin expressament. sqlmap és potent i sorollós; es fa servir dins de la finestra acordada.

Remediació (codi segur):

<?php
// SEGUR: consulta preparada, la dada MAI es barreja amb el codi SQL
$stmt = $conn->prepare("SELECT nombre, precio, descripcion FROM productos WHERE id = ?");
$stmt->bind_param("i", $id);   // "i" forca enter: separa dada de codi
$stmt->execute();
$res = $stmt->get_result();
?>

Les consultes parametritzades (prepared statements) envien la consulta i les dades per separat; el motor mai interpreta la dada com a SQL. És la defensa definitiva, més el principi de mínim privilegi al compte de BD.

  1. Cross-Site Scripting (XSS): reflectit i emmagatzemat

Mecanisme. El XSS injecta JavaScript en una pàgina que altres usuaris veuran, perquè l'aplicació retorna entrada de l'usuari sense escapar-la a l'HTML. El codi s'executa al navegador de la víctima.

Tipus On viu el payload Exemple a TechNova
Reflectit A la URL, es reflecteix a la resposta Cercador: buscar.php?q=...
Emmagatzemat Desat a BD, se serveix a tothom Comentari/ressenya d'un producte
DOM Al JS del client, sense passar pel servidor Fragment # processat per JS

Codi vulnerable (cercador reflectit):

<?php // VULNERABLE: eco directe del parametre a l'HTML
echo "<p>Resultados para: " . $_GET['q'] . "</p>";
?>

PoC de baix impacte. No robem sessions reals: provem amb un payload inofensiu i visible.

http://tienda.technova.lab/buscar.php?q=<script>alert(document.domain)</script>

Si salta l'alert amb tienda.technova.lab, el XSS està confirmat. Un alert() demostra l'execució sense exfiltrar cookies; per a l'informe n'hi ha prou amb la captura.

Remediació (codi segur):

<?php // SEGUR: escapar segons el context de sortida (HTML)
echo "<p>Resultados para: " . htmlspecialchars($_GET['q'], ENT_QUOTES, 'UTF-8') . "</p>";
?>

Defenses: escapar segons context (htmlspecialchars a l'HTML), Content-Security-Policy (capçalera que restringeix quins scripts s'executen), cookies HttpOnly (el JS no les pot llegir) i validació d'entrada. En marcs moderns, l'autoescapament de plantilles cobreix la majoria de casos.

  1. Cross-Site Request Forgery (CSRF)

Mecanisme. El CSRF abusa que el navegador envia les cookies de sessió automàticament. Un lloc maliciós fa que el navegador d'una víctima autenticada enviï una petició legítima a TechNova sense la seva intenció (canviar email, adreça d'enviament...).

Codi vulnerable (formulari sense token):

<!-- VULNERABLE: l'accio nomes depen de la cookie de sessio -->
<form action="/cuenta/cambiar_email.php" method="POST">
  <input type="email" name="email">
  <input type="submit" value="Guardar">
</form>

PoC de baix impacte. Una pàgina externa amb un formulari autoenviat cap a TechNova; al laboratori es prova canviant l'email a un valor sentinella fictici ([email protected]) per demostrar l'efecte sense malmetre comptes reals.

Remediació (codi segur):

<?php // SEGUR: token CSRF per sessio, validat al servidor
$token = bin2hex(random_bytes(32));
$_SESSION['csrf'] = $token; ?>
<form action="/cuenta/cambiar_email.php" method="POST">
  <input type="hidden" name="csrf" value="<?php echo $token; ?>">
  <input type="email" name="email">
</form>
<?php // En processar: comparacio en temps constant
if (!hash_equals($_SESSION['csrf'] ?? '', $_POST['csrf'] ?? '')) {
    http_response_code(403); exit('CSRF');
}

Defenses: token anti-CSRF per sessió, cookies SameSite=Lax/Strict, i reautenticació per a accions sensibles.

  1. Inclusió de fitxers: LFI i RFI

Mecanisme. Passa quan una ruta de fitxer es construeix amb entrada de l'usuari. LFI (Local File Inclusion) inclou fitxers del mateix servidor; RFI (Remote File Inclusion) inclou fitxers remots (més greu: execució de codi).

Codi vulnerable:

<?php $page = $_GET['page']; include($page . ".php"); ?>

PoC de baix impacte. Llegir un fitxer no sensible però provatori amb recorregut de directoris:

http://tienda.technova.lab/index.php?page=../../../../etc/passwd%00

Si apareixen línies de /etc/passwd (noms d'usuari del sistema, no secrets), l'LFI està confirmat. No llegim claus ni fitxers privats: /etc/passwd n'hi ha prou com a prova.

Remediació (codi segur):

<?php // SEGUR: llista blanca; l'entrada mai forma la ruta directament
$permitidas = ['home' => 'home.php', 'ayuda' => 'ayuda.php'];
$page = $permitidas[$_GET['page']] ?? 'home.php';
include(__DIR__ . '/paginas/' . $page);
?>

Defenses: llista blanca de valors, basename(), desactivar allow_url_include (mata el RFI) i mai construir rutes amb entrada crua.

  1. Pujada de fitxers insegura

Mecanisme. Si l'aplicació accepta fitxers sense validar tipus ni destinació, l'atacant puja un script executable (per exemple un .php) a una carpeta servible i després l'invoca: execució remota de codi.

Codi vulnerable:

<?php // VULNERABLE: desa qualsevol cosa en un directori public i executable
move_uploaded_file($_FILES['f']['tmp_name'], "uploads/" . $_FILES['f']['name']);
?>

PoC de baix impacte. Pujar un .php inofensiu que només demostri execució, no una webshell operativa:

<?php echo "poc-technova: " . php_uname(); ?>

En visitar uploads/poc.php i veure el poc-technova amb el kernel, queda demostrada l'execució. No es puja una webshell completa ni s'opera amb ella: la prova sentinella n'hi ha prou.

Remediació: validar tipus real (MIME/magic bytes) contra llista blanca, reanomenar amb nom aleatori i extensió controlada, desar fora del webroot o en emmagatzematge sense execució, i desactivar l'execució de PHP a uploads/.

  1. IDOR i control d'accés trencat

Mecanisme. IDOR (Insecure Direct Object Reference) és accedir a objectes d'altres usuaris canviant un identificador, perquè el servidor no comprova la propietat. És l'essència del "control d'accés trencat".

Codi vulnerable:

<?php // VULNERABLE: serveix la factura per id sense comprovar de qui es
$id = $_GET['factura'];
$f = $db->query("SELECT * FROM facturas WHERE id = $id"); // a mes SQLi...
echo render($f);
?>

PoC de baix impacte. Autenticat com un usuari de prova (cliente01), canviar factura=1001 per factura=1002 i comprovar si es veu la factura d'un altre usuari fictici. N'hi ha prou de veure una factura aliena de prova per confirmar; no es recol·lecten dades massives.

Remediació:

<?php // SEGUR: filtrar SEMPRE pel propietari de la sessio
$stmt = $db->prepare("SELECT * FROM facturas WHERE id = ? AND usuario_id = ?");
$stmt->bind_param("ii", $_GET['factura'], $_SESSION['user_id']);
?>

Defenses: comprovar autorització per objecte en cada accés, referències indirectes o no predictibles, i denegar per defecte.

  1. SSRF (Server-Side Request Forgery)

Mecanisme. L'aplicació fa una petició HTTP a una URL que controla l'usuari. L'atacant apunta aquesta petició a la xarxa interna (a la qual ell no arriba) o a serveis de metadades, fent servir el servidor com a proxy.

Codi vulnerable:

<?php // VULNERABLE: descarrega la URL que demani l'usuari
$img = file_get_contents($_GET['url']);
?>

PoC de baix impacte. Demanar una URL interna del laboratori i comprovar que el servidor l'abasta:

http://tienda.technova.lab/proxy.php?url=http://10.10.10.20:8080/

Si torna contingut d'un servei intern de 10.10.10.0/24 inaccessible des de fora, el SSRF està confirmat. La prova es limita a llegir una resposta, no a atacar el servei intern.

Remediació: llista blanca de dominis/hosts permesos, resoldre i validar la IP de destinació (bloquejar rangs privats i 169.254.169.254), i desactivar redireccions i esquemes perillosos (file://, gopher://).

  1. Deserialització insegura (visió general)

Mecanisme (alt nivell). Quan una aplicació deserialitza dades controlades per l'usuari (objectes PHP/Java/Python serialitzats), un atacant pot construir un objecte que, en reconstruir-se, dispara codi (gadget chains). És una classe avançada; a aquest nivell n'hi ha prou de reconèixer el patró de risc: entrada no confiable → unserialize()/pickle.loads() → possible RCE.

Regla defensiva: no deserialitzis dades no confiables. Si necessites intercanviar dades, fes servir formats que només transporten dades (JSON) amb validació d'esquema, signa la càrrega (HMAC) per detectar manipulació i evita unserialize() sobre entrada d'usuari.

  1. Detecció i eines

Aquestes vulnerabilitats es descobreixen i validen amb proxies d'intercepció i escàners, que es veuen a fons al Mòdul 7:

  • Burp Suite (07-03): interceptar, repetir (Repeater) i automatitzar peticions (Intruder); mapar la botiga.
  • OWASP ZAP (07-04): alternativa lliure amb escaneig passiu/actiu.
  • sqlmap: automatització responsable de SQLi (apartat 2).

Des del costat defensiu, es detecten amb WAF, revisió de logs (pics d'errors SQL, ../ als paràmetres), proves SAST/DAST al cicle de desenvolupament i capçaleres de seguretat (CSP, X-Content-Type-Options).

  1. Errors Comuns i Consells

  • Bolcar la base de dades sencera "perquè es pot". Trenca el control d'impacte i exposa dades personals. Extreu només la dada mínima que prova la fallada.
  • Fer servir un XSS per robar cookies reals de sessió. A la PoC n'hi ha prou amb un alert(); robar sessions alienes és innecessari i perillós.
  • Confondre LFI amb RFI. El RFI (fitxer remot) sol donar RCE directa i és més greu; distingeix-los a l'informe.
  • Pujar una webshell operativa. Un fitxer sentinella que imprimeix php_uname() ja demostra l'execució; una webshell completa és excés d'impacte.
  • Reportar sense remediació. Cada troballa web ha d'anar amb el seu codi segur. El valor de l'informe està en l'arranjament, no en l'ensurt.
  • Llançar sqlmap amb --dump-all o --os-shell sense autorització. És intrusiu i pot excedir l'abast. Enumera estructura; el bolcat i l'execució requereixen permís explícit.
  • Consell: gairebé totes aquestes classes comparteixen arrel —barrejar dada amb codi—. Interioritza el patró "separar/escapar/validar segons context" i les reconeixeràs totes.

  1. Exercicis

Exercici 1. Sobre tienda.technova.lab/producto.php?id=, descriu la seqüència de PoC de baix impacte per confirmar la SQLi de la candidata #1 sense extreure dades de clients, i escriu la versió remediada de la consulta. Explica per què la consulta preparada tanca la fallada.

Exercici 2. El camp de ressenyes d'un producte desa el text i el mostra a tots els visitants. Classifica el tipus de XSS que suposa, proposa un payload de prova inofensiu per validar-lo i dona dues mesures de remediació amb el seu codi.

Exercici 3. Com a cliente01 veus la teva factura a /factura.php?id=1001. Explica com comprovaries un IDOR de manera controlada, quina evidència mínima capturaries i com ho arreglaries al servidor.

Solucions

Solució 1. Seqüència: (1) id=1' → error SQL a la resposta confirma que l'entrada arriba al motor; (2) prova booleana id=1 AND 1=1 (producte visible) enfront de id=1 AND 1=2 (absent) confirma el control de la lògica; (3) id=-1 UNION SELECT @@version,2,3 mostra 5.5.62, una dada del motor, sense tocar clients. Remediació: $stmt = $conn->prepare("SELECT nombre,precio,descripcion FROM productos WHERE id = ?"); $stmt->bind_param("i",$id);. Tanca la fallada perquè la consulta i les dades viatgen per canals separats: el ? és un marcador de posició i l'id es tracta sempre com a dada entera, mai com a SQL executable, així que 1 OR 1=1 deixa de ser interpretat com a codi.

Solució 2. És un XSS emmagatzemat (el payload es desa a BD i se serveix a tots els visitants), el més perillós perquè no requereix enganyar cada víctima. Payload de prova inofensiu: <script>alert(document.domain)</script> a la ressenya; si salta en obrir la pàgina del producte, està confirmat (captura com a evidència, sense robar res). Remediació: (1) escapar a la sortida, echo htmlspecialchars($resenya, ENT_QUOTES, 'UTF-8');; (2) capçalera CSP restrictiva, p. ex. Content-Security-Policy: default-src 'self', que impedeix executar scripts injectats encara que s'hi coli text. Complement: cookies HttpOnly.

Solució 3. Autenticat com a cliente01, canviar id=1001 per id=1002 (o un altre proper) i observar si es mostra la factura d'un altre usuari fictici; amb veure una factura aliena de prova n'hi ha prou per confirmar l'IDOR (evidència mínima: la petició amb l'id alterat i la resposta que mostra dades d'un altre titular, sense recol·lectar-ne més). Arranjament al servidor: consultar sempre filtrant pel propietari de la sessió, ... WHERE id = ? AND usuario_id = ? amb usuario_id = $_SESSION['user_id'], de manera que un id aliè no retorni res. Denegar per defecte i comprovar la propietat en cada accés.

Conclusió

Hem convertit la candidata número u del Mòdul 3 en un fet: la SQLi de producto.php?id= és real i explotable, validada amb una PoC de baix impacte que només va llegir la versió del motor. I no ens hem quedat aquí: hem recorregut el mapa de la superfície web de TechNova —XSS reflectit i emmagatzemat, CSRF, LFI/RFI, pujada insegura, IDOR/control d'accés trencat, SSRF i deserialització— veient en cadascuna el mecanisme, una prova que demostra sense destruir i, sobretot, el codi segur que la tanca. El fil conductor de totes: no barrejar dades de l'usuari amb codi, i separar/escapar/validar segons el context.

Amb la botiga auditada, girem cap a la infraestructura. La lliçó següent, 04-03 Explotació de Vulnerabilitats de Xarxa, baixa del navegador als cables i els serveis: els serveis amb CVE explotable de l'inventari, la intercepció de trànsit (MITM/ARP), els atacs a SMB de la xarxa interna 10.10.10.0/24 i les configuracions febles, sempre amb la seva detecció (IDS) i el seu hardening com a contrapartida.

© Copyright 2026. Tots els drets reservats