Sikkerhed

    Linkscannere og engangshemmeligheder

    Slettes et engangslink ved GET, dør det, når Slack eller en e-mailgateway viser en forhåndsvisning. Send metadata på GET, og slet først ved klik på Vis.

    W. Miller · Opdateret · Om LinkPilot

    Et engangslink, der slettes ved et almindeligt GET, dør i det øjeblik, Slack, Teams eller en e-mailgateway henter det for at vise en forhåndsvisning. Løsningen er kun at returnere metadata på GET og først slette hemmeligheden ved en bevidst visning via POST, med en adgangssætning sendt ad en anden kanal som ekstra sikring. Indlægget gennemgår, hvilke systemer der henter links uden at spørge, og hvordan du designer, så de ikke gør skade.

    LinkPilots generator til hemmelige engangslinks er bygget på den måde: en hentning til forhåndsvisning får kun selve siden uden indhold. Hemmeligheden hentes, og visningen tælles, først når en browser kører siden.

    Den typiske fejl

    De fleste chat- og e-mailprogrammer forsøger at vise en forhåndsvisning, når de ser en URL. Forløbet ser sådan ud:

    1. En bruger indsætter det hemmelige link i Slack.
    2. Slacks forhåndsvisningsbot henter URL'en (sender et GET; Slack beskriver adfærden under link unfurling).
    3. Din kode til visning behandler forespørgslen som en visning fra et menneske, sletter hemmeligheden og returnerer indholdet.
    4. Slack modtager det slettede indhold (eller en generisk side) og viser det.
    5. Mennesket klikker på linket, ser ”allerede vist” og beder afsenderen om et nyt.

    Botten havde ingen ond hensigt. Din kode blandede ”nogen hentede URL'en” sammen med ”modtageren læste hemmeligheden”. Det er to forskellige hændelser, og hele designopgaven går ud på at holde dem adskilt.

    Der gemmer sig en værre variant i trin 3: hvis bottens GET fik det egentlige indhold, ligger hemmeligheden nu i en tredjeparts infrastruktur til forhåndsvisninger. I bedste fald blev den kasseret, efter at forhåndsvisningen var lavet, men det kan du ikke bekræfte, og der er ingen hændelse i revisionsloggen, der fortæller dig, at det skete.

    Forhåndsvisningsbots i chatprogrammer, sikkerhedsgateways til e-mail, endpointbeskyttelse, proxyer i virksomheder og browserudvidelser med forhåndsvisning, og som regel mere end én af dem. ”Slack viser forhåndsvisninger” undervurderer problemet. En URL, der indsættes på en moderne arbejdsplads, bliver typisk hentet af flere systemer, før et menneske klikker på den:

    Hvem henterHvornår det skerKan den genkendes?
    Forhåndsvisningsbots i chat (Slack, Teams, iMessage, WhatsApp, LinkedIn)I det øjeblik beskeden sendesSom regel: tydelige user agents som Slackbot-LinkExpanding
    Sikkerhedsgateways til e-mail (Mimecast, Proofpoint, Microsoft Defender)Ved levering og ofte igen, når der klikkesOfte ikke: mange bruger user agents fra rigtige browsere
    Endpointbeskyttelse og antivirusNår URL'en når modtagerens computerSjældent
    Webproxyer i virksomhederNår der klikkes, før brugerens forespørgsel sendes videreSjældent
    Browserudvidelser med forhåndsvisning af linksNår musen holdes over linket, eller siden indlæsesNej: de bruger brugerens egen browsersession

    Leverandørernes adfærd i tabellen ændrer sig hele tiden. Læs konkrete påstande om gateways som ”som offentliggjort i juli 2026, tjek mod den aktuelle dokumentation”. Fællesnævneren ændrer sig dog ikke: alle systemerne sender et almindeligt GET, fordi det er den eneste sikre og universelle måde at se på en URL, man ikke selv styrer.

    Send metadata på GET, og slet kun ved et bevidst POST. HTTP-semantikken findes allerede: RFC 9110, afsnit 9.2.1 definerer GET som sikker og idempotent, dvs. en forespørgsel, som alle frit må sende, fordi den ikke skal ændre noget. POST er handlingsverbet. Gør derfor visningen til en POST-handling bag en synlig knap:

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

    Nu returnerer Slacks GET en neutral side med metadata. Hemmeligheden slettes først, når mennesket klikker på knappen. En scanner, der respekterer HTTP-semantikken, rører aldrig indholdet. Det gælder næsten dem alle, for sendte de POST-forespørgsler med sideeffekter mod vilkårlige URL'er, ville halvdelen af nettet holde op med at virke.

    Et gennemgået eksempel

    Følg ét link hele vejen. Du opretter en hemmelighed med Slet efter læsning og en adgangssætning og indsætter URL'en i en direkte besked i Slack og i en e-mail.

    1. Slacks forhåndsvisningsbot sender GET /s/abc123. Svar: en lille side med metadata, status aktiv, adgangssætning påkrævet. Ingen visning registreret. Hemmeligheden lever.
    2. Modtagerens e-mailgateway omskriver URL'en i e-mailen og henter den ved levering for at tjekke dens omdømme. Samme GET, samme metadata. Hemmeligheden lever stadig.
    3. Modtageren klikker på linket i e-mailen. Gatewayens scanner henter det én gang til (GET) og sender derefter browseren videre.
    4. Browseren indlæser siden til visning, endnu et GET. Siden viser en knap til visning og et felt til adgangssætningen. Stadig ingen visning registreret.
    5. Modtageren indtaster adgangssætningen og klikker på knappen. Browseren sender POST /s/abc123. Visningen registreres, indholdet returneres, og hemmeligheden slettes.
    6. Alle, der henter URL'en bagefter, får et klart svar om, at indholdet ”allerede er vist og destrueret”, i stedet for indholdet.

    Fem hentninger, én visning. Det forhold er normalt i en virksomhed. Et design, der ikke kan tåle det, fejler første dag, og så indsætter afsenderen bare adgangskoden direkte i chatten.

    Forsvar i flere lag

    Opdelingen mellem GET og POST

    Klarer alle forhåndsvisningsbots og scannere, der opfører sig ordentligt, og det er langt størstedelen af den automatiske trafik. Det er fundamentet. Alt nedenfor er ekstra lag.

    Adgangssætning som spærring

    Dækker det, opdelingen ikke kan: sandboxe, der kører JavaScript og interagerer med siden, samt klik ved et uheld og videresendte e-mails. En sandbox til detonation kan klikke på en knap, men den kan ikke levere en adgangssætning, der er sendt ad en anden kanal. Send linket via e-mail og adgangssætningen i en direkte besked i Slack eller via sms.

    Filtrering af bots efter user agent

    Afvis kendte forhåndsvisningsbots (Slackbot, LinkedInBot, Twitterbot), før de når koden til visning. Det er værd at gøre som livrem og seler, men det er aldrig nok alene: sikkerhedsscannere bruger rutinemæssigt user agents fra rigtige browsere, netop for at ondsindede sider ikke kan skjule sig for analysen.

    Kort udløb

    Begræns det tidsrum, hvor der kan ske skade. Et link, der levede i femten minutter, efterlader scannere, logfiler og chathistorik med en URL, der ikke længere fører til noget.

    Cache-Control: no-store

    Sæt headeren på hvert svar fra visningen, så ingen mellemled (virksomhedens proxy, CDN eller browserens cache) gemmer en kopi af indholdet efter den ene legitime læsning.

    Sikkerhedsgateways til e-mail

    Gateways i virksomheder fortjener deres eget afsnit, fordi de henter to gange. Produkter i den kategori (Microsoft Defender Safe Links er det dokumenterede eksempel) omskriver hver URL i indgående e-mails, så den går via deres eget scanningsdomæne. URL'en hentes typisk én gang ved levering for at tjekke omdømmet og igen, når der klikkes, før mennesket sendes videre til den rigtige destination.

    Hvis en af hentningerne slettede hemmeligheden, ville modtageren altid se et dødt link. For brugerne ser fejlen tilfældig ud, men den er helt forudsigelig. Opdelingen mellem GET og POST klarer begge hentninger uden ekstra arbejde, fordi begge er almindelige GET. Omdirigeringen ved klikket fører derefter mennesket til siden til visning, hvor POST sker.

    Særtilfælde, der stadig giver problemer

    • Sandboxe, der kører JavaScript. Nogle miljøer til detonation gengiver siden og interagerer med den. Et POST bag en knap uden adgangssætning kan i princippet blive klikket af en aggressiv sandbox. Adgangssætningen er den ekstra sikring.
    • Link og adgangssætning i samme kanal. Sendes begge i én e-mail, falder alle forsvarene ovenfor sammen til ”håb på, at ingen læser den e-mail”. Brug altid to kanaler.
    • Videresendelse. Hver gang linket sendes videre til et nyt chat- eller e-mailsystem, udløses en ny runde forhåndsvisninger. Med opdelingen er det ufarligt, men hvert led er endnu et sæt logfiler, der rummer URL'en, og det taler for kort udløb.
    • Samtidige visninger. Klikker to personer på knappen samtidig, skal læsning og sletning ske i ét trin, der ikke kan deles op: præcis én forespørgsel vinder, og den anden får ”allerede vist”. En implementering, hvor de to ting sker hver for sig, kan levere indholdet to gange.

    Test dit eget værktøj

    Før du betror rigtige loginoplysninger til en tjeneste til deling af hemmeligheder, så lav dette tjek, som tager to minutter:

    1. Opret en hemmelighed, du kan smide væk, med Slet efter læsning slået til.
    2. Hent den fra en terminal. Det er præcis, hvad en forhåndsvisningsbot gør: curl -s -o /dev/null -w "%{http_code}" "<url>"
    3. Åbn linket i en browser. Ser du ”allerede vist”, sletter værktøjet ved GET, og det er ikke sikkert at indsætte linket i en chat eller en e-mail.
    4. Overlevede hemmeligheden, så vis den på normal vis i browseren og kør curl igen. Nu bør du få et klart svar om, at den er væk eller slettet, ikke indholdet.

    Sådan gør LinkPilot

    LinkPilots hemmelige links bruger netop dette design: et GET mod endpointet til visning returnerer kun metadata (status, og om der kræves en adgangssætning). En visning registreres kun ved et bevidst POST. Adgangssætninger hashes med SHA-256 i browseren og begrænses til fem forsøg pr. IP-adresse pr. minut pr. hemmelighed. Hvert svar fra visningen har Cache-Control: no-store, slettede eller udløbne hemmeligheder returnerer HTTP 410, og det gemte indhold overskrives. Revisionsloggen registrerer hver hændelse med en hashet IP-adresse under et salt, der skiftes dagligt, og den rå IP-adresse gemmes aldrig. Alle detaljer står på siden om sikkerhedsarkitekturen.

    Prøv det gratis, uden tilmelding

    Selvdestruerende besked

    Send en note, der forsvinder efter én læsning.

    Åbn værktøjet

    Designets begrænsninger

    De ærlige grænser: intet af ovenstående beskytter en hemmelighed efter en legitim visning. Modtageren kan kopiere indholdet, tage et skærmbillede af det eller sende det videre. Det hjælper heller ikke, hvis adgangssætningen sendes sammen med linket. Og det kan ikke forhindre en person, der ved en fejl har fået linket, i at åbne det, før den rigtige modtager gør. Det er derfor, der er en revisionslog: du ser den uventede visning og skifter loginoplysningerne.

    Kilder

    Værktøjer til denne artikel

    Ofte stillede spørgsmål

    LinkPilot sender et hemmeligt link, der er væk, når det er åbnet.

    Krypteres i din browser, vises én gang og destrueres derefter. Kræver ingen konto.

    Opret et hemmeligt link

    Læs videre