Hur implementerar man säkra rubriker med Cloudflare Workers?

Säkerhetsförbättring: HTTP-rubriker med Cloudflare Workers

Denna guide beskriver hur du steg för steg implementerar säkra HTTP-rubriker på webbplatser som använder Cloudflare, genom att utnyttja Cloudflare Workers.

Att implementera HTTP-svarsrubriker är en effektiv metod för att skydda webbplatser mot diverse sårbarheter, såsom XSS, klickkapning, MIME-sniffning och cross-site scripting. Denna metod rekommenderas starkt av OWASP.

Tidigare har jag beskrivit hur man implementerar dessa rubriker på webbservrar som Apache, Nginx och IIS. Men om du använder Cloudflare för att förbättra säkerheten och prestandan på dina webbplatser, kan du använda Cloudflare Workers för att anpassa HTTP-svarsrubriker.

Cloudflare Workers är en serverlös plattform som låter dig köra JavaScript, C, C++ och Rust. Den är globalt distribuerad i Cloudflares nätverk av över 200 datacenter.

Implementeringen är både enkel och flexibel. Du kan styra vilka rubriker som ska gälla för hela webbplatsen, inklusive underdomäner, eller använda matchande mönster med reguljära uttryck (regex) för specifika URI:er.

I detta exempel kommer jag att använda kod som utvecklats av Scott Helme.

Låt oss börja! 👨‍💻

  • Logga in på ditt Cloudflare-konto och klicka på ”Workers” (Direktlänk).
  • Kopiera koden från worker.jsGitHub och klistra in den i skriptredigeraren.
    const securityHeaders = {
        "Content-Security-Policy": "upgrade-insecure-requests",
        "Strict-Transport-Security": "max-age=1000",
        "X-Xss-Protection": "1; mode=block",
        "X-Frame-Options": "DENY",
        "X-Content-Type-Options": "nosniff",
        "Referrer-Policy": "strict-origin-when-cross-origin"
    },
    sanitiseHeaders = {
        Server: ""
    },
    removeHeaders = [
        "Public-Key-Pins",
        "X-Powered-By",
        "X-AspNet-Version"
    ];

async function addHeaders(req) {
    const response = await fetch(req),
        newHeaders = new Headers(response.headers),
        setHeaders = Object.assign({}, securityHeaders, sanitiseHeaders);

    if (newHeaders.has("Content-Type") && !newHeaders.get("Content-Type").includes("text/html")) {
        return new Response(response.body, {
            status: response.status,
            statusText: response.statusText,
            headers: newHeaders
        });
    }

    Object.keys(setHeaders).forEach(name => newHeaders.set(name, setHeaders[name]));

    removeHeaders.forEach(name => newHeaders.delete(name));

    return new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders
    });
}

addEventListener("fetch", event => event.respondWith(addHeaders(event.request)));
  

Spara inte koden direkt, anpassa den istället enligt dina behov.

Content-Security-Policy: Här kan du definiera säkerhetspolicyn för din applikation.

Exempel: Om du behöver tillåta inladdning av innehåll via iframes från vissa domäner, kan du använda `frame-ancestors`.

      "Content-Security-Policy" : "frame-ancestors 'self' gf.dev adminvista.com.com",
    

Detta exempel tillåter inladdning av innehåll från gf.dev, adminvista.com.com och den egna domänen.

X-Frame-Options: Du kan byta till SAMEORIGIN om du vill tillåta att din webbplats visas i en iframe inom samma domän.

     "X-Frame-Options": "SAMEORIGIN",
    

Server: Här kan du rensa eller ändra serverrubriken. Ange önskad text.

      "Server" : "adminvista.com Server",
    

RemoveHeaders: Här anger du rubriker som ska tas bort, för att undvika att visa versionsnummer och annan information som kan användas i informationsläckageattacker.

     let removeHeaders = [
	"Public-Key-Pins",
	"X-Powered-By",
	"X-AspNet-Version",
    ]
   

Lägg till egna rubriker: Om du behöver lägga till egna rubriker för din applikation, gör du det under securityHeaders.

   let securityHeaders = {
	"Content-Security-Policy" : "frame-ancestors 'self' gf.dev adminvista.com.com",
	"Strict-Transport-Security" : "max-age=1000",
	"X-Xss-Protection" : "1; mode=block",
	"X-Frame-Options" : "SAMEORIGIN",
	"X-Content-Type-Options" : "nosniff",
	"Referrer-Policy" : "strict-origin-when-cross-origin",
        "Custom-Header"  : "Success",
    }

När du har justerat rubrikerna efter dina behov, namnge din worker och klicka på ”Spara och distribuera”.

Bra jobbat! Nu måste du koppla din worker till den plats där du vill att rubrikerna ska användas. Jag applicerar detta på min labbmiljö.

  • Gå till Cloudflares kontrollpanel och välj din webbplats.
  • Gå till ”Workers” och klicka på ”Lägg till rutt”.
  • Ange URL:en i ”Rutt”. Du kan använda regex här.
  • Välj den nyskapade worker och spara.

Det är allt. Inom en sekund kommer alla rubriker att implementeras på din webbplats.

Så här ser det ut i Chrome Dev Tools. Du kan även testa rubrikerna med ett HTTP-huvudverktyg.

Jag är inte säker på varför serverhuvudet inte syns. Cloudflare kanske åsidosätter det.

Den totala implementeringen tar ca 15 minuter och kräver ingen driftstopp eller omstart, som kan vara fallet med Apache eller Nginx. Om du tänker använda detta på en produktionswebbplats, rekommenderar jag att du testar först i en lägre miljö eller på testsidor. När du är nöjd, applicera det där det behövs.

Detta är en smidig lösning!

Tack till Scott för den användbara koden.