Een uitgebreide gids voor Cross-Origin Resource Sharing (CORS), die configuratie, beveiligingsimplicaties en best practices voor ontwikkelaars behandelt.
Cross-Origin Resource Sharing (CORS): Configuratie en Best Practices voor Beveiliging
In de wereld van webontwikkeling is beveiliging van het grootste belang. Een cruciaal aspect van webbeveiliging is het beheren van hoe webpagina's van de ene oorsprong toegang krijgen tot bronnen van een andere oorsprong. Hier komt Cross-Origin Resource Sharing (CORS) om de hoek kijken. CORS is een beveiligingsfunctie in browsers die webpagina's beperkt in het doen van verzoeken naar een ander domein dan het domein dat de webpagina heeft geleverd. Dit mechanisme is ingesteld om te voorkomen dat kwaadwillende websites toegang krijgen tot gevoelige gegevens. Dit artikel biedt een uitgebreide gids voor CORS, waarin de configuratie, beveiligingsimplicaties en best practices worden behandeld.
Het Same-Origin Policy Begrijpen
CORS is gebouwd op de fundering van het Same-Origin Policy (zelfde-oorsprongbeleid), een fundamenteel beveiligingsmechanisme dat door webbrowsers wordt geïmplementeerd. Het same-origin policy beperkt webpagina's in het doen van verzoeken naar een ander domein dan het domein dat de webpagina heeft geleverd. Twee URL's worden beschouwd als van dezelfde oorsprong als ze hetzelfde protocol (bijv. HTTP of HTTPS), dezelfde host (bijv. example.com) en dezelfde poort (bijv. 80 of 443) hebben. Bijvoorbeeld:
http://example.comenhttp://example.com/pathzijn van dezelfde oorsprong.http://example.comenhttps://example.comzijn verschillende oorsprongen (verschillende protocollen).http://example.comenhttp://www.example.comzijn verschillende oorsprongen (verschillende hosts).http://example.com:80enhttp://example.com:8080zijn verschillende oorsprongen (verschillende poorten).
Het same-origin policy is ontworpen om Cross-Site Scripting (XSS)-aanvallen te voorkomen, waarbij een kwaadwillende website scripts injecteert in een vertrouwde website om gebruikersgegevens te stelen of ongeautoriseerde acties uit te voeren. Zonder het same-origin policy zou een kwaadwillende website potentieel toegang kunnen krijgen tot uw bankrekeninginformatie als u in een ander tabblad was ingelogd op uw online bankportaal.
Wat is Cross-Origin Resource Sharing (CORS)?
Hoewel het same-origin policy cruciaal is voor de beveiliging, kan het ook beperkend zijn in legitieme scenario's waarin websites toegang moeten hebben tot bronnen van verschillende oorsprongen. Een webapplicatie die bijvoorbeeld wordt gehost op example.com moet mogelijk gegevens ophalen van een API die wordt gehost op api.example.net. CORS biedt een mechanisme om het same-origin policy op een gecontroleerde manier te omzeilen, waardoor webpagina's cross-origin verzoeken kunnen doen wanneer dit expliciet door de server is geautoriseerd.
CORS werkt door HTTP-headers toe te voegen aan de respons van de server, die aangeven welke oorsprongen toegang hebben tot de bron. De browser controleert vervolgens deze headers en blokkeert het verzoek als de oorsprong van de webpagina die het verzoek doet niet is toegestaan.
Hoe CORS Werkt: De HTTP-Headers
CORS is afhankelijk van specifieke HTTP-headers om cross-origin verzoeken te faciliteren. Hier zijn de belangrijkste headers die erbij betrokken zijn:
1. Origin (Request Header)
De Origin-header wordt door de browser meegestuurd bij cross-origin verzoeken. Het geeft de oorsprong (protocol, host en poort) aan van de webpagina die het verzoek doet. Bijvoorbeeld:
Origin: http://example.com
2. Access-Control-Allow-Origin (Response Header)
De Access-Control-Allow-Origin-header is de belangrijkste header in CORS. Het specificeert welke oorsprongen toegang hebben tot de bron. Het kan een van de volgende waarden hebben:
- Een specifieke oorsprong: Bijvoorbeeld,
Access-Control-Allow-Origin: http://example.comstaat alleen verzoeken vanhttp://example.comtoe. *(wildcard):Access-Control-Allow-Origin: *staat verzoeken van elke oorsprong toe. Dit moet met voorzichtigheid worden gebruikt, omdat het effectief het same-origin policy voor die bron uitschakelt.
Voorbeeld:
Access-Control-Allow-Origin: https://www.example.com
3. Access-Control-Allow-Methods (Response Header)
De Access-Control-Allow-Methods-header specificeert de HTTP-methoden (bijv. GET, POST, PUT, DELETE) die zijn toegestaan in het cross-origin verzoek. Dit is vereist voor preflight-verzoeken (hieronder uitgelegd).
Voorbeeld:
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
4. Access-Control-Allow-Headers (Response Header)
De Access-Control-Allow-Headers-header specificeert de HTTP-headers die zijn toegestaan in het cross-origin verzoek. Dit is ook vereist voor preflight-verzoeken.
Voorbeeld:
Access-Control-Allow-Headers: Content-Type, Authorization, X-Requested-With
5. Access-Control-Allow-Credentials (Response Header)
De Access-Control-Allow-Credentials-header specificeert of de browser referenties (bijv. cookies, autorisatieheaders) moet opnemen in het cross-origin verzoek. Het kan een van de twee waarden hebben: true of false. Als true is ingesteld, kan de Access-Control-Allow-Origin-header niet worden ingesteld op *. Het moet een specifieke oorsprong zijn.
Voorbeeld:
Access-Control-Allow-Credentials: true
6. Access-Control-Max-Age (Response Header)
De Access-Control-Max-Age-header specificeert het aantal seconden dat de browser de resultaten van het preflight-verzoek kan cachen. Dit kan de prestaties verbeteren door het aantal preflight-verzoeken te verminderen.
Voorbeeld:
Access-Control-Max-Age: 3600
Eenvoudige Verzoeken vs. Preflight-Verzoeken
CORS maakt onderscheid tussen twee soorten cross-origin verzoeken: eenvoudige verzoeken en preflight-verzoeken.
Eenvoudige Verzoeken
Een eenvoudig verzoek is een verzoek dat aan de volgende criteria voldoet:
- De methode is
GET,HEAD, ofPOST. - Als de methode
POSTis, is deContent-Type-header een van de volgende:application/x-www-form-urlencoded,multipart/form-data, oftext/plain. - Het verzoek stelt geen aangepaste headers in (anders dan die automatisch door de browser worden ingesteld).
Voor eenvoudige verzoeken stuurt de browser het verzoek rechtstreeks naar de server. De server reageert vervolgens met de juiste CORS-headers. Als de oorsprong is toegestaan, verwerkt de browser de respons. Anders blokkeert de browser de respons en geeft een foutmelding.
Preflight-Verzoeken
Een preflight-verzoek wordt door de browser verzonden voordat het daadwerkelijke cross-origin verzoek wordt gedaan, als het verzoek niet voldoet aan de criteria voor een eenvoudig verzoek. Dit gebeurt meestal wanneer het verzoek een andere methode gebruikt dan GET, HEAD, of POST, of wanneer het verzoek aangepaste headers instelt.
Het preflight-verzoek is een OPTIONS-verzoek dat de volgende headers bevat:
Origin: De oorsprong van de webpagina die het verzoek doet.Access-Control-Request-Method: De HTTP-methode die in het daadwerkelijke verzoek zal worden gebruikt.Access-Control-Request-Headers: Een door komma's gescheiden lijst van de aangepaste headers die in het daadwerkelijke verzoek zullen worden gebruikt.
De server reageert vervolgens met de volgende headers:
Access-Control-Allow-Origin: De oorsprong die toegang heeft tot de bron.Access-Control-Allow-Methods: De HTTP-methoden die zijn toegestaan in het cross-origin verzoek.Access-Control-Allow-Headers: De HTTP-headers die zijn toegestaan in het cross-origin verzoek.Access-Control-Max-Age: Het aantal seconden dat de browser de resultaten van het preflight-verzoek kan cachen.
Als de server reageert met de juiste CORS-headers, gaat de browser verder met het daadwerkelijke cross-origin verzoek. Anders blokkeert de browser het verzoek en geeft een foutmelding.
CORS Configuratievoorbeelden
De implementatie van CORS varieert afhankelijk van de server-side technologie die u gebruikt. Hier zijn enkele voorbeelden voor veelgebruikte server-side talen en frameworks:
Node.js met Express
Het gebruik van de cors middleware is een gebruikelijke aanpak om CORS te configureren in Node.js met Express:
const express = require('express');
const cors = require('cors');
const app = express();
// CORS inschakelen voor alle origins
app.use(cors());
// CORS inschakelen voor een specifieke origin
// app.use(cors({ origin: 'http://example.com' }));
// CORS inschakelen met opties
// app.use(cors({
// origin: ['http://example.com', 'http://localhost:3000'],
// methods: ['GET', 'POST', 'PUT', 'DELETE'],
// allowedHeaders: ['Content-Type', 'Authorization'],
// credentials: true
// }));
app.get('/api/data', (req, res) => {
res.json({ message: 'Hallo van de API!' });
});
app.listen(3001, () => {
console.log('Server luistert op poort 3001');
});
Python met Flask
U kunt de Flask-CORS-extensie gebruiken om CORS in Flask te configureren:
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
# CORS inschakelen voor alle origins
CORS(app)
# CORS inschakelen voor specifieke origins
# CORS(app, origins=['http://example.com', 'http://localhost:3000'])
@app.route('/api/data')
def get_data():
return {'message': 'Hallo van de API!'}
if __name__ == '__main__':
app.run(port=3001)
Java met Spring Boot
Spring Boot biedt verschillende manieren om CORS te configureren. Een aanpak is het gebruik van de @CrossOrigin-annotatie:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@CrossOrigin(origins = "http://example.com") // Specifieke origin
public class ApiController {
@GetMapping("/api/data")
public String getData() {
return "Hallo van de API!";
}
}
// Globale CORS-configuratie (met WebMvcConfigurer):
// @Configuration
// public class CorsConfig implements WebMvcConfigurer {
// @Override
// public void addCorsMappings(CorsRegistry registry) {
// registry.addMapping("/**")
// .allowedOrigins("http://example.com", "http://localhost:3000")
// .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
// .allowedHeaders("Content-Type", "Authorization")
// .allowCredentials(true)
// .maxAge(3600);
// }
// }
PHP
In PHP kunt u de CORS-headers rechtstreeks in uw script instellen:
<?php
header("Access-Control-Allow-Origin: http://example.com");
header("Content-Type: application/json");
$data = array("message" => "Hallo van de API!");
echo json_encode($data);
?>
Beveiligingsoverwegingen bij CORS
Hoewel CORS cross-origin verzoeken mogelijk maakt, is het cruciaal om de beveiligingsimplicaties te begrijpen en het correct te implementeren om kwetsbaarheden te voorkomen.
1. Vermijd het Gebruik van Access-Control-Allow-Origin: * in Productie
Het gebruik van de wildcard * in de Access-Control-Allow-Origin-header staat verzoeken van elke oorsprong toe, wat effectief het same-origin policy voor die bron uitschakelt. Dit kan uw API blootstellen aan kwaadwillende websites die potentieel gebruikersgegevens kunnen stelen of ongeautoriseerde acties kunnen uitvoeren. Specificeer in plaats daarvan de exacte oorsprongen die toegang hebben tot de bron. Als uw webapplicatie bijvoorbeeld wordt gehost op example.com en toegang nodig heeft tot een API die wordt gehost op api.example.com, stel dan de header in op Access-Control-Allow-Origin: http://example.com.
Globaal voorbeeld: Stel u een financiële dienst-API voor die Access-Control-Allow-Origin: * instelt. Een kwaadwillende website zou dan namens een ingelogde gebruiker verzoeken naar deze API kunnen doen, en mogelijk geld kunnen overmaken zonder medeweten van de gebruiker.
2. Valideer de Origin-Header op de Server
Zelfs als u een lijst met toegestane oorsprongen specificeert, is het belangrijk om de Origin-header op de server te valideren om te voorkomen dat aanvallers de oorsprong spoofen. Een aanvaller zou potentieel een verzoek kunnen sturen met een vervalste Origin-header om de CORS-controles te omzeilen. Om dit te beperken, vergelijkt u de Origin-header met een lijst van vertrouwde oorsprongen aan de server-kant. Als de oorsprong niet in de lijst staat, wijst u het verzoek af.
Globaal voorbeeld: Beschouw een e-commerceplatform. Een aanvaller zou kunnen proberen de Origin van een legitieme webwinkel na te bootsen om toegang te krijgen tot gevoelige klantgegevens van de API van het e-commerceplatform.
3. Wees Voorzichtig met Access-Control-Allow-Credentials: true
Als u Access-Control-Allow-Credentials: true instelt, kan de Access-Control-Allow-Origin-header niet worden ingesteld op *. Het moet een specifieke oorsprong zijn. Dit komt omdat het toestaan van referenties van elke oorsprong een beveiligingsrisico kan creëren, omdat het kwaadwillende websites in staat kan stellen toegang te krijgen tot gebruikersgegevens als ze een gebruiker kunnen misleiden om hun site te bezoeken terwijl de gebruiker ook is ingelogd op de doelsite. Deze instelling is belangrijk bij het omgaan met cookies of autorisatieheaders.
Globaal voorbeeld: Een socialemediaplatform dat cross-origin verzoeken met referenties toestaat, vereist zorgvuldig beheer om ongeautoriseerde toegang tot gebruikersaccounts te voorkomen.
4. Configureer Access-Control-Allow-Methods en Access-Control-Allow-Headers Correct
Sta alleen de HTTP-methoden en -headers toe die nodig zijn voor de cross-origin verzoeken. Als u alleen GET- en POST-verzoeken hoeft toe te staan, sta dan geen PUT, DELETE, of andere methoden toe. Sta op dezelfde manier alleen de specifieke headers toe die uw applicatie nodig heeft. Al te permissieve configuraties kunnen het risico op aanvallen vergroten.
Globaal Voorbeeld: Een CRM-systeem moet alleen de noodzakelijke API-eindpunten en headers blootstellen aan geautoriseerde externe integraties, om het aanvalsoppervlak te minimaliseren.
5. Gebruik HTTPS voor Veilige Communicatie
Gebruik altijd HTTPS voor veilige communicatie tussen de browser en de server. HTTPS versleutelt de gegevens die tussen de browser en de server worden verzonden, wat afluisteren en man-in-the-middle-aanvallen voorkomt. Het gebruik van HTTP kan gevoelige gegevens blootstellen aan aanvallers, zelfs als CORS correct is geconfigureerd.
Globaal Voorbeeld: Zorgtoepassingen moeten HTTPS gebruiken om patiëntgegevens te beschermen die over verschillende oorsprongen worden verzonden.
6. Content Security Policy (CSP)
Hoewel niet direct gerelateerd aan CORS, is Content Security Policy (CSP) een ander belangrijk beveiligingsmechanisme dat kan helpen bij het voorkomen van XSS-aanvallen. Met CSP kunt u een whitelist definiëren van bronnen waaruit de browser bronnen mag laden. Dit kan helpen voorkomen dat aanvallers kwaadaardige scripts in uw website injecteren, zelfs als ze erin slagen andere beveiligingsmaatregelen te omzeilen.
Globaal voorbeeld: Financiële instellingen hanteren vaak strikte CSP-beleidsregels om de bronnen van inhoud die op hun online bankportalen worden geladen te beperken, waardoor het risico op XSS-aanvallen wordt verminderd.
Veelvoorkomende CORS-problemen en Probleemoplossing
CORS-fouten kunnen frustrerend zijn om te debuggen. Hier zijn enkele veelvoorkomende problemen en hoe u ze kunt oplossen:
1. "No 'Access-Control-Allow-Origin' header is present on the requested resource."
Dit is de meest voorkomende CORS-fout. Het geeft aan dat de server de Access-Control-Allow-Origin-header niet retourneert in zijn respons. Zorg ervoor dat de server is geconfigureerd om de juiste CORS-headers te sturen voor de oorsprong van de webpagina die het verzoek doet. Controleer uw server-side code en configuratiebestanden dubbel.
2. "Response to preflight request doesn't pass access control check: It does not have HTTP ok status."
Deze fout geeft aan dat het preflight-verzoek is mislukt. Dit kan gebeuren als de server niet reageert op OPTIONS-verzoeken of als de server een foutstatuscode (bijv. 404, 500) retourneert in reactie op het preflight-verzoek. Zorg ervoor dat uw server is geconfigureerd om OPTIONS-verzoeken af te handelen en dat deze een 200 OK-statuscode retourneert.
3. "Response to preflight request doesn't pass access control check: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'."
Deze fout treedt op wanneer u probeert referenties (bijv. cookies) te verzenden in een cross-origin verzoek en de Access-Control-Allow-Origin-header is ingesteld op *. Zoals eerder vermeld, kunt u de wildcard * niet gebruiken bij het verzenden van referenties. U moet de exacte oorsprong specificeren die toegang heeft tot de bron.
4. Browser Caching
Browsers kunnen CORS-responsen cachen, wat kan leiden tot onverwacht gedrag als de CORS-configuratie verandert. Om cacheproblemen te voorkomen, stelt u de Cache-Control-header in de respons in op no-cache, no-store, of max-age=0. U kunt ook de Access-Control-Max-Age-header gebruiken om te bepalen hoe lang de browser de resultaten van het preflight-verzoek in de cache opslaat.
Alternatieven voor CORS
Hoewel CORS de standaardmanier is om cross-origin verzoeken mogelijk te maken, zijn er enkele alternatieven die u in bepaalde scenario's kunt overwegen:
1. JSON with Padding (JSONP)
JSONP is een techniek die de <script>-tag gebruikt om het same-origin policy te omzeilen. JSONP werkt door de JSON-gegevens in een JavaScript-functieaanroep te verpakken. De browser voert vervolgens de JavaScript-functie uit en geeft de JSON-gegevens als argument door. JSONP is eenvoudiger te implementeren dan CORS, maar heeft enkele beperkingen. Het ondersteunt alleen GET-verzoeken en is minder veilig dan CORS.
2. Reverse Proxy
Een reverse proxy is een server die voor uw API-server staat en verzoeken naar deze doorstuurt. De reverse proxy kan worden geconfigureerd om de benodigde CORS-headers aan de respons toe te voegen, waardoor de cross-origin verzoeken effectief voor de browser worden verborgen. Deze aanpak kan handig zijn als u geen controle heeft over de API-server of als u de CORS-configuratie wilt vereenvoudigen.
Conclusie
Cross-Origin Resource Sharing (CORS) is een cruciaal beveiligingsmechanisme dat webpagina's in staat stelt om op een gecontroleerde manier toegang te krijgen tot bronnen van verschillende oorsprongen. Het begrijpen van hoe CORS werkt en het correct implementeren ervan is essentieel voor het bouwen van veilige en betrouwbare webapplicaties. Door de best practices in dit artikel te volgen, kunt u CORS effectief beheren en uw API's beschermen tegen ongeautoriseerde toegang.
Onthoud dat u altijd prioriteit moet geven aan beveiliging bij het configureren van CORS. Vermijd het gebruik van wildcards, valideer de Origin-header en gebruik HTTPS voor veilige communicatie. Door deze voorzorgsmaatregelen te nemen, kunt u ervoor zorgen dat uw webapplicaties beschermd zijn tegen cross-site aanvallen.
Deze uitgebreide gids biedt een solide basis voor het begrijpen van CORS. Raadpleeg altijd de officiële documentatie van uw specifieke server-side technologie voor de meest actuele informatie en best practices. Blijf op de hoogte van opkomende beveiligingsrisico's en pas uw CORS-configuratie dienovereenkomstig aan.