Seguretat

    Escàners d'enllaços i secrets d'un sol ús

    Un enllaç d'un sol ús destruït amb un GET mor quan Slack o una passarel·la de correu el previsualitza. Doneu metadades al GET i destruïu-lo en mostrar-lo.

    W. Miller · Actualitzat el · Sobre LinkPilot

    Un enllaç d'un sol ús que es destrueix amb un GET simple mor en el moment en què Slack, Teams o una passarel·la de correu l'obren per generar-ne una previsualització. La solució és tornar només metadades al GET i destruir el secret amb una petició POST explícita en mostrar-lo, amb una frase de contrasenya enviada per un segon canal com a protecció addicional. Aquest article explica quins sistemes obren enllaços sense demanar permís i com dissenyar el servei perquè cap d'ells no el faci fallar.

    El generador d'enllaços secrets d'un sol ús de LinkPilot funciona així: una petició de previsualització només rep l'estructura de la pàgina; el secret s'obté, i la visualització es compta, quan un navegador executa la pàgina.

    La fallada per defecte

    La majoria de clients de xat i de correu intenten mostrar una previsualització quan veuen un URL. El flux és aquest:

    1. Un usuari enganxa l'enllaç secret a Slack.
    2. El previsualitzador de Slack obre l'URL (fa un GET; Slack documenta aquest comportament a link unfurling).
    3. El vostre gestor de visualització tracta la petició com si fos una persona, destrueix el secret i en retorna el contingut.
    4. Slack rep el contingut ja destruït (o una pàgina genèrica) i el mostra.
    5. La persona fa clic a l'enllaç, veu «ja s'ha vist» i demana a qui l'ha enviat un enllaç nou.

    El previsualitzador no tenia cap mala intenció. El vostre gestor ha confós «algú ha obert l'URL» amb «el destinatari ha llegit el secret». Són esdeveniments diferents, i tot el problema de disseny consisteix a mantenir-los separats.

    Al pas 3 s'amaga una variant pitjor: si el GET del previsualitzador ha rebut el contingut real, el secret ara és dins la infraestructura de previsualitzacions d'un tercer. En el millor dels casos s'ha descartat després de generar la previsualització, però no teniu cap manera de confirmar-ho, ni cap esdeveniment d'auditoria que us digui que ha passat.

    Els previsualitzadors dels xats, les passarel·les de seguretat del correu, la protecció dels dispositius, els servidors intermediaris corporatius i les extensions de previsualització, i normalment més d'un alhora. Dir que «Slack genera previsualitzacions» es queda curt. Un URL enganxat en un entorn de treball actual l'obren normalment diversos sistemes abans que cap persona hi faci clic:

    Qui l'obreQuan ho faEs pot identificar?
    Previsualitzadors de xat (Slack, Teams, iMessage, WhatsApp, LinkedIn)En el moment d'enviar el missatgeNormalment sí: user agents propis com Slackbot-LinkExpanding
    Passarel·les de seguretat del correu (Mimecast, Proofpoint, Microsoft Defender)En el lliurament, i sovint una altra vegada en el moment del clicSovint no: moltes es presenten amb el user agent d'un navegador real
    Protecció de dispositius / antivirusQuan l'URL arriba a l'ordinador del destinatariRarament
    Servidors intermediaris web corporatiusEn el moment del clic, abans de reenviar la petició de l'usuariRarament
    Extensions de navegador que previsualitzen enllaçosEn passar el ratolí per sobre o en carregar la pàginaNo: funcionen dins la sessió del navegador de l'usuari

    El comportament dels proveïdors d'aquesta taula canvia amb el temps: preneu les afirmacions concretes sobre cada passarel·la com «segons el que es publicava el juliol del 2026, comproveu-ho amb la documentació actual». El que tenen en comú, en canvi, no canvia: tots aquests sistemes fan un GET simple, perquè és l'única manera segura i universal de mirar un URL que no controleu.

    Doneu metadades al GET i destruïu el secret només amb un POST explícit. La semàntica d'HTTP ja ho preveu: l'RFC 9110, secció 9.2.1 defineix GET com a mètode segur i idempotent, és a dir, una petició que qualsevol pot fer lliurement perquè no hauria de canviar res. POST és el verb d'acció. Per tant, tracteu la visualització com una acció POST darrere d'un botó visible:

    GET  /s/abc123   →  HTML page: "Click to reveal this secret"
    POST /s/abc123   →  burns the secret, returns the payload
    

    Ara el GET de Slack retorna una pàgina neutra de metadades. El secret només mor quan la persona fa clic al botó. Cap escàner que respecti la semàntica d'HTTP no toca mai el contingut, i gairebé tots la respecten, perquè enviar POSTs amb efectes a URL arbitraris trencaria mig web.

    Un recorregut pas a pas

    Seguiu un enllaç de principi a fi. Creeu un secret que es destrueix després de la lectura, amb frase de contrasenya, i enganxeu l'URL en un missatge directe de Slack i en un correu.

    1. El previsualitzador de Slack fa GET /s/abc123. Resposta: una petita pàgina de metadades (estat actiu, cal frase de contrasenya). No es registra cap visualització. El secret continua viu.
    2. La passarel·la de correu del destinatari reescriu l'URL del correu i l'obre en el moment del lliurament per analitzar-ne la reputació. El mateix GET, les mateixes metadades. Continua viu.
    3. El destinatari fa clic a l'enllaç del correu. L'escàner de la passarel·la l'obre una vegada més en el moment del clic (GET) i després redirigeix el navegador.
    4. El navegador carrega la pàgina per mostrar el secret, amb un altre GET. La pàgina mostra un botó i un camp per a la frase de contrasenya. Encara no s'ha registrat cap visualització.
    5. El destinatari introdueix la frase de contrasenya i fa clic al botó. El navegador envia POST /s/abc123. Es registra la visualització, es retorna el contingut i el secret es destrueix.
    6. Qualsevol que obri l'URL després rep una resposta explícita que diu que ja s'ha vist i s'ha destruït, en lloc del contingut.

    Cinc peticions, una visualització. Aquesta proporció és normal en un entorn corporatiu. Un disseny que no l'aguanti fallarà el primer dia, i qui envia acabarà enganxant la contrasenya directament al xat.

    Defenses en capes

    La separació entre GET i POST

    Resol el cas de tots els previsualitzadors i escàners que es comporten bé, que són la immensa majoria del trànsit automatitzat. Aquesta és la base; tota la resta afegeix profunditat.

    Frase de contrasenya

    Cobreix el que la separació no pot cobrir: els entorns aïllats que executen JavaScript i interactuen amb la pàgina, a més dels clics accidentals de persones i dels correus reenviats. Un entorn aïllat d'anàlisi pot fer clic a un botó; no pot proporcionar una frase de contrasenya que ha viatjat per un altre canal. Envieu l'enllaç per correu i la frase de contrasenya per un missatge directe de Slack o per SMS.

    Filtratge de bots pel user agent

    Descarteu els bots de previsualització coneguts (Slackbot, LinkedInBot, Twitterbot) abans que arribin a la lògica de visualització. Val la pena fer-ho com a precaució extra, però mai no és suficient per si sol: els escàners de seguretat es presenten habitualment amb el user agent d'un navegador real precisament perquè les pàgines malicioses no es puguin amagar de l'anàlisi.

    Caducitat curta

    Limiteu el període de risc. Un enllaç que ha viscut quinze minuts deixa als escàners, als fitxers de registre i a l'historial del xat un URL que ja no porta enlloc.

    Cache-Control: no-store

    Poseu-lo a cada resposta de visualització perquè cap intermediari (servidor intermediari corporatiu, CDN, memòria cau del navegador) no conservi una còpia del contingut després de l'única lectura legítima.

    El cas de les passarel·les de seguretat del correu

    Les passarel·les corporatives mereixen una secció pròpia perquè obren l'enllaç dues vegades. Els productes d'aquesta mena (Microsoft Defender Safe Links n'és l'exemple documentat) reescriuen cada URL del correu entrant perquè passi pel seu propi domini d'anàlisi. Normalment l'URL s'obre una vegada en el lliurament, per analitzar-ne la reputació, i una altra en el moment del clic, abans de redirigir la persona a la destinació real.

    Si qualsevol d'aquestes peticions destruís el secret, el destinatari veuria sempre un enllaç mort: una fallada que als usuaris els sembla aleatòria però que és del tot determinista. La separació entre GET i POST absorbeix les dues peticions sense cap cost, perquè totes dues són GETs simples. Després, la redirecció del moment del clic porta la persona a la pàgina de visualització, on es fa el POST.

    Casos límit que encara fan mal

    • Entorns aïllats que executen JavaScript. Alguns entorns d'anàlisi renderitzen la pàgina i hi interactuen. En principi, un entorn agressiu podria fer clic a un POST darrere d'un botó sense frase de contrasenya. La frase de contrasenya és la protecció addicional.
    • Enllaç i frase de contrasenya pel mateix canal. Si viatgen tots dos en un mateix correu, totes les defenses anteriors queden reduïdes a «esperem que ningú no llegeixi aquest correu». Separeu sempre els canals.
    • Reenviaments. Cada reenviament a un xat o un sistema de correu nou provoca una nova ronda de previsualitzacions. Amb la separació no fa cap mal, però cada salt és un altre conjunt de registres que conserven l'URL, i això és un argument a favor de la caducitat curta.
    • Visualitzacions simultànies. Si dues persones fan clic al botó alhora, la lectura i la destrucció han de passar en un sol pas indivisible: exactament una petició guanya i l'altra rep «ja s'ha vist». Una implementació que les separi pot servir el contingut dues vegades.

    Comproveu la vostra eina

    Abans de confiar credencials reals a qualsevol servei per compartir secrets, feu aquesta comprovació de dos minuts:

    1. Creeu un secret de prova que es destrueixi després de la lectura.
    2. Obriu-lo des d'un terminal, que és exactament el que fa un previsualitzador: curl -s -o /dev/null -w "%{http_code}" "<url>"
    3. Obriu l'enllaç en un navegador. Si veieu «ja s'ha vist», l'eina destrueix el secret amb el GET i no és segur enganxar-ne els enllaços en un xat o un correu.
    4. Si ha sobreviscut, mostreu-lo correctament al navegador i torneu a executar curl: ara hauríeu de rebre una resposta explícita que indiqui que ja no existeix o s'ha destruït, no el contingut.

    Com ho implementa LinkPilot

    Perquè consti, aquest és el disseny que fan servir els enllaços secrets de LinkPilot: un GET al punt de visualització només retorna metadades (l'estat i si cal frase de contrasenya), i només es registra una visualització amb un POST explícit. Les frases de contrasenya es converteixen en un hash SHA-256 al client i tenen un límit de cinc intents per IP, per minut i per secret. Cada resposta de visualització porta Cache-Control: no-store, els secrets destruïts o caducats retornen HTTP 410 amb el contingut desat sobreescrit, i la cronologia d'auditoria registra cada esdeveniment amb la IP convertida en hash amb una sal que canvia cada dia: la IP en brut no es desa mai. Teniu tots els detalls a la pàgina d'arquitectura de seguretat.

    Proveu-la gratis, sense registre

    Missatge que s'autodestrueix

    Envieu una nota que desapareix després de llegir-la una vegada.

    Obre l'eina

    Límits d'aquest disseny

    Els límits, amb franquesa: res de tot això no protegeix un secret després d'una visualització legítima, perquè el destinatari pot copiar el contingut, fer-ne una captura de pantalla o reenviar-lo. No serveix de res si la frase de contrasenya viatja amb l'enllaç. I no pot impedir que una persona que ha rebut l'enllaç per error l'obri abans que el destinatari previst. Per a això hi ha la cronologia d'auditoria: veieu la visualització inesperada i roteu la credencial.

    Referències

    Eines per a aquest article

    Preguntes freqüents

    LinkPilot envia un enllaç secret que desapareix després d'obrir-lo.

    Es xifra al vostre navegador, es mostra una sola vegada i després es destrueix. Sense compte.

    Crea un enllaç secret

    Llegiu també