HTTP Security: Difference between revisions
Jump to navigation
Jump to search
No edit summary |
No edit summary |
||
| (27 intermediate revisions by the same user not shown) | |||
| Line 1: | Line 1: | ||
<syntaxhighlight lang= | {|class='wikitable' | ||
|valign='top'| | |||
<syntaxhighlight lang='java'> | |||
@Component | @Component | ||
@WebFilter(urlPatterns = {"/*"}) | @WebFilter(urlPatterns = {"/*"}) | ||
| Line 20: | Line 22: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|} | |||
==Default Sources== | ==Default Sources== | ||
<syntaxhighlight lang= | {|class='wikitable' | ||
|valign='top'| | |||
<syntaxhighlight lang='java'> | |||
private String getDefaultSources() { | private String getDefaultSources() { | ||
String tiktok = "https://analytics.tiktok.com/"; | String tiktok = "https://analytics.tiktok.com/"; | ||
| Line 34: | Line 39: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|} | |||
==Content Security Policy== | ==Content Security Policy== | ||
<syntaxhighlight lang= | {|class='wikitable' | ||
|valign='top'| | |||
<syntaxhighlight lang='properties'> | |||
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ajax.googleapis.com https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://assets.zendesk.com; font-src 'self' https://fonts.gstatic.com https://themes.googleusercontent.com; frame-src https://player.vimeo.com https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none' | Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ajax.googleapis.com https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://assets.zendesk.com; font-src 'self' https://fonts.gstatic.com https://themes.googleusercontent.com; frame-src https://player.vimeo.com https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none' | ||
| Line 48: | Line 56: | ||
Content-Security-Policy: default-src 'self' cdn.chorke.org | Content-Security-Policy: default-src 'self' cdn.chorke.org | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|} | |||
==Content Security Policy » Nginx== | |||
{|class='wikitable' | |||
<syntaxhighlight lang= | |valign='top'| | ||
<syntaxhighlight lang='nginx'> | |||
server { | server { | ||
server_name academia.chorke.org; | server_name academia.chorke.org; | ||
…more… | # …more… | ||
add_header Content-Security-Policy "default-src * 'unsafe-inline' 'unsafe-eval' data: blob:"; | add_header X-Frame-Options "SAMEORIGIN"; | ||
add_header Referrer-Policy "same-origin"; | |||
add_header X-Content-Type-Options "nosniff"; | |||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; | |||
add_header Content-Security-Policy "frame-ancestors https://shahed.biz; default-src * 'unsafe-inline' 'unsafe-eval' data: blob:"; | |||
add_header Permissions-Policy "camera=('none'), microphone=('none'), geolocation=('none'), payment=('none')"; | add_header Permissions-Policy "camera=('none'), microphone=('none'), geolocation=('none'), payment=('none')"; | ||
…more… | # …more… | ||
location / { | location / { | ||
return 301 https:// | return 301 https://academia.chorke.org$request_uri; | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|- | |||
|valign='top'| | |||
<syntaxhighlight lang='bash'> | |||
nginx -t | |||
systemctl restart nginx | |||
</syntaxhighlight> | |||
|} | |||
==Content Security Policy » Nginx » Ingress== | |||
{|class='wikitable mw-collapsible' | |||
!scope='col' style='text-align:left'| | |||
Nginx » Ingress | |||
|- | |||
|valign='top'| | |||
{|class='wikitable mw-collapsible mw-collapsed' | |||
!scope='col'| | |||
Service » academia | |||
|- | |||
|valign='top'| | |||
<syntaxhighlight lang='yaml'> | |||
cat <<'YML'| \ | |||
kubectl apply -n academia -f - | |||
--- | |||
apiVersion: v1 | |||
kind: ConfigMap | |||
metadata: | |||
name: academia-csp | |||
namespace: academia | |||
data: | |||
default.conf: | | |||
server { | |||
listen 80; | |||
server_name _; | |||
# php -i|grep upload_max | |||
client_max_body_size 2M; | |||
keepalive_timeout 10; | |||
# header » forward » client | |||
proxy_set_header X-Forwarded-Proto $scheme; | |||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; | |||
proxy_set_header X-Real-IP $remote_addr; | |||
proxy_set_header Host $host; | |||
# header » remove » security | |||
proxy_hide_header X-Powered-By; | |||
proxy_hide_header X-Frame-Options; | |||
proxy_hide_header Referrer-Policy; | |||
proxy_hide_header Permissions-Policy; | |||
proxy_hide_header X-Content-Type-Options; | |||
proxy_hide_header Content-Security-Policy; | |||
proxy_hide_header Strict-Transport-Security; | |||
# header » append » security | |||
add_header X-Frame-Options "SAMEORIGIN" always; | |||
add_header Referrer-Policy "same-origin" always; | |||
add_header X-Content-Type-Options "nosniff" always; | |||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; | |||
add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:" always; | |||
add_header Permissions-Policy "camera=('none'), microphone=('none'), geolocation=('none'), payment=('none')" always; | |||
location / { | |||
proxy_pass http://academia:80/; | |||
proxy_redirect off; | |||
} | |||
} | |||
--- | |||
apiVersion: v1 | |||
kind: Service | |||
metadata: | |||
name: academia-csp | |||
namespace: academia | |||
labels: | |||
app.kubernetes.io/instance: academia-csp | |||
app.kubernetes.io/managed-by: kubectl | |||
app.kubernetes.io/name: academia-csp | |||
app.kubernetes.io/version: 1.0.0 | |||
spec: | |||
type: ClusterIP | |||
ports: | |||
- port: 80 | |||
name: http | |||
protocol: TCP | |||
targetPort: http | |||
selector: | |||
app.kubernetes.io/instance: academia-csp | |||
app.kubernetes.io/name: academia-csp | |||
--- | |||
apiVersion: apps/v1 | |||
kind: Deployment | |||
metadata: | |||
name: academia-csp | |||
namespace: academia | |||
labels: | |||
app.kubernetes.io/instance: academia-csp | |||
app.kubernetes.io/managed-by: kubectl | |||
app.kubernetes.io/name: academia-csp | |||
app.kubernetes.io/version: 1.0.0 | |||
spec: | |||
replicas: 1 | |||
selector: | |||
matchLabels: | |||
app.kubernetes.io/instance: academia-csp | |||
app.kubernetes.io/name: academia-csp | |||
template: | |||
metadata: | |||
labels: | |||
app.kubernetes.io/instance: academia-csp | |||
app.kubernetes.io/name: academia-csp | |||
spec: | |||
containers: | |||
- name: academia-csp | |||
image: nginx:1.27-alpine-slim | |||
ports: | |||
- name: http | |||
protocol: TCP | |||
containerPort: 80 | |||
resources: | |||
requests: | |||
cpu: 50m | |||
memory: 64Mi | |||
limits: | |||
memory: 128Mi | |||
cpu: 100m | |||
volumeMounts: | |||
- mountPath: /etc/nginx/conf.d/default.conf | |||
subPath: default.conf | |||
name: default-conf | |||
volumes: | |||
- name: default-conf | |||
configMap: | |||
name: academia-csp | |||
items: | |||
- key: default.conf | |||
path: default.conf | |||
YML | |||
</syntaxhighlight> | |||
|} | |||
{|class='wikitable mw-collapsible mw-collapsed' | |||
!scope='col'| | |||
Ingress » nginx | |||
|- | |||
|valign='top'| | |||
<syntaxhighlight lang='yaml'> | |||
cat << YML | \ | |||
kubectl apply -n academia -f - | |||
--- | |||
apiVersion: networking.k8s.io/v1 | |||
kind: Ingress | |||
metadata: | |||
name: academia | |||
namespace: academia | |||
labels: | |||
app.kubernetes.io/name: academia | |||
app.kubernetes.io/version: 1.0.0 | |||
app.kubernetes.io/instance: academia | |||
app.kubernetes.io/managed-by: kubectl | |||
annotations: | |||
nginx.ingress.kubernetes.io/proxy-body-size: "0" | |||
spec: | |||
ingressClassName: nginx | |||
rules: | |||
- host: academia.chorke.org | |||
http: | |||
paths: | |||
- path: / | |||
pathType: ImplementationSpecific | |||
backend: | |||
service: | |||
name: academia-csp | |||
port: | |||
number: 80 | |||
YML | |||
</syntaxhighlight> | |||
|} | |||
|} | |||
==Permissions Policy== | ==Permissions Policy== | ||
<syntaxhighlight lang= | {|class='wikitable' | ||
|valign='top'| | |||
<syntaxhighlight lang='properties'> | |||
Permissions-Policy: camera=(), microphone=(), geolocation=() | Permissions-Policy: camera=(), microphone=(), geolocation=() | ||
Permissions-Policy: camera=('none'), microphone=('none'), geolocation=('none'), payment=('none') | Permissions-Policy: camera=('none'), microphone=('none'), geolocation=('none'), payment=('none') | ||
| Line 73: | Line 265: | ||
permissions-policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=() | permissions-policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|} | |||
==References== | ==References== | ||
{| | {|class='wikitable' | ||
| valign= | !scope='col' colspan='3'| | ||
References | |||
|- | |||
|valign='top' style='width:33%'| | |||
* [https://content-security-policy.com/strict-dynamic/ CSP » <code>'strict-dynamic'</code>] | * [https://content-security-policy.com/strict-dynamic/ CSP » <code>'strict-dynamic'</code>] | ||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-attr CSP » <code>script-src-attr</code>] | * [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src-attr CSP » <code>script-src-attr</code>] | ||
| Line 88: | Line 284: | ||
* [https://content-security-policy.com/self/ CSP » <code>'self'</code>] | * [https://content-security-policy.com/self/ CSP » <code>'self'</code>] | ||
| valign= | |valign='top' style='width:34%'| | ||
* [https://stackoverflow.com/questions/59144892/ Cookies » Request to access or storage was blocked] | * [https://stackoverflow.com/questions/59144892/ Cookies » Request to access or storage was blocked] | ||
* [https://www.tinstar.co.uk/studio-blog/some-cookies-are-misusing-the-recommended-samesite-attribute-how-to-fix/ Cookies » Recommended sameSite Attribute] | * [https://www.tinstar.co.uk/studio-blog/some-cookies-are-misusing-the-recommended-samesite-attribute-how-to-fix/ Cookies » Recommended sameSite Attribute] | ||
| Line 100: | Line 296: | ||
* [https://content-security-policy.com/examples/ CSP » Examples] | * [https://content-security-policy.com/examples/ CSP » Examples] | ||
| valign= | |valign='top' style='width:33%'| | ||
* [https://stackoverflow.com/questions/11973047/ CSP » Nginx » Adding & using header] | |||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials CORS » Credential is not supported] | * [https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS/Errors/CORSNotSupportingCredentials CORS » Credential is not supported] | ||
* [https://github.com/goauthentik/authentik/issues/5762 CSP » Allow iframe embedding] | |||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy/frame-ancestors CSP » <code>'frame-ancestors'</code>] | |||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy Content-Security-Policy] | * [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy Content-Security-Policy] | ||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation Content Negotiation] | * [https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation Content Negotiation] | ||
| Line 110: | Line 309: | ||
|- | |- | ||
| colspan= | |colspan='3'| | ||
---- | |||
|- | |||
|valign='top'| | |||
* [https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Frame-Options Header » <code>X-Frame-Options</code>] | |||
* [https://www.srihash.org/ SRI » Hash Generator] | |||
* [https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity SRI » Docs » Mozilla] | |||
* [https://owasp.org/www-community/controls/SubresourceIntegrity SRI » Docs » OWASP] | |||
|valign='top'| | |||
|valign='top'| | |||
|- | |||
|colspan='3'| | |||
---- | ---- | ||
|- | |- | ||
| valign= | |valign='top'| | ||
* [https://securityheaders.com/?q= | * [https://securityheaders.com/?q=http%3A%2F%2Fpfapply.aeoncredit.com.my Scan » CSP » pfapply.aeoncredit.com.my] | ||
* [https://securityheaders.com/?q= | * [https://securityheaders.com/?q=http%3A%2F%2Fcdn.chorke.org%2Fwiki Scan » CSP » cdn.chorke.org/wiki] | ||
* [https://securityheaders.com/?q=https%3A%2F%2Fshahed.biz | * [https://securityheaders.com/?q=http%3A%2F%2Ffinology-group.com Scan » CSP » finology-group.com] | ||
* [https://securityheaders.com/?q=http%3A%2F%2Fwiki.chorke.org Scan » CSP » wiki.chorke.org] | |||
* [https://securityheaders.com/?q=http%3A%2F%2Fwiki.shahed.biz Scan » CSP » wiki.shahed.biz] | |||
* [https://securityheaders.com/?q=http%3A%2F%2Fshahed.biz Scan » CSP » shahed.biz] | |||
| valign= | |valign='top'| | ||
* [https://www.sslshopper.com/ssl-checker.html#hostname=finology-group.com Scan » SSL » finology-group.com] | |||
* [https://www.sslshopper.com/ssl-checker.html#hostname=shahed.biz Scan » SSL » shahed.biz] | |||
| valign= | |valign='top'| | ||
|- | |- | ||
| colspan= | |colspan='3'| | ||
---- | ---- | ||
|- | |- | ||
| valign= | |valign='top'| | ||
* [[Homebrew]] | * [[Homebrew]] | ||
* [[ZA Proxy]] | * [[ZA Proxy]] | ||
| Line 138: | Line 356: | ||
* [[Wrk]] | * [[Wrk]] | ||
| valign= | |valign='top'| | ||
* [[JSON Schema Validation]] | * [[JSON Schema Validation]] | ||
* [[Spring Security]] | * [[Spring Security]] | ||
| Line 150: | Line 368: | ||
* [[Java]] | * [[Java]] | ||
| valign= | |valign='top'| | ||
* [[Spring Exception Handling]] | * [[Spring Exception Handling]] | ||
* [[Security/Certificate/TLS|Security » Certificate » TLS]] | |||
* [[Security/Certificate|Security » Certificate]] | |||
* [[Security/Password|Security » Password]] | |||
* [[Security/Domain|Security » Domain]] | |||
* [[Postman Script]] | * [[Postman Script]] | ||
|} | |} | ||
Latest revision as of 00:56, 19 January 2026
@Component
@WebFilter(urlPatterns = {"/*"})
public class ResponseHeaderWebFilter implements Filter {
@Override
public void doFilter(
ServletRequest request,
ServletResponse response, FilterChain chain
) throws IOException, ServletException {
HttpServletResponse httpServletResponse = (HttpServletResponse) response;
httpServletResponse.setHeader("Content-Security-Policy", "default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:;");
httpServletResponse.setHeader("Strict-Transport-Security", "max-age=31536000 ; includeSubDomains ; preload");
httpServletResponse.setHeader("Permissions-Policy", "geolocation 'self'; payment 'none'");
httpServletResponse.setHeader("X-Content-Type-Options", "nosniff");
httpServletResponse.setHeader("Referrer-Policy", "strict-origin-when-cross-origin");
httpServletResponse.setHeader("X-Frame-Options", "DENY");
chain.doFilter(request, response);
}
}
|
Default Sources
private String getDefaultSources() {
String tiktok = "https://analytics.tiktok.com/";
String facebook = "https://www.facebook.com/ https://connect.facebook.net/";
String doubleClick = "https://stats.g.doubleclick.net/ https://11141660.fls.doubleclick.net/ https://googleads.g.doubleclick.net/";
String google = "https://www.google.com/ https://www.google.com.my/ https://analytics.google.com/ https://www.googletagmanager.com/ https://www.google-analytics.com/";
String[] sources = {DEFAULT_SRC, SELF, UNSAFE_INLINE, UNSAFE_EVAL, google, facebook, doubleClick, tiktok, BLOB_DATA};
String defaultSources = String.join(SOURCE_DELIMITER, sources);
return getFilteredSources(defaultSources, DEFAULT_SRC);
}
|
Content Security Policy
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ajax.googleapis.com https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://assets.zendesk.com; font-src 'self' https://fonts.gstatic.com https://themes.googleusercontent.com; frame-src https://player.vimeo.com https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none'
Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.google.com/ https://www.google.com.my/ https://analytics.google.com/ https://www.googletagmanager.com/ https://www.google-analytics.com/ https://www.facebook.com/ https://connect.facebook.net/ https://stats.g.doubleclick.net/ https://11141660.fls.doubleclick.net/ https://googleads.g.doubleclick.net/ https://analytics.tiktok.com/ data: blob:
Content-Security-Policy: default-src *; style-src 'self' 'unsafe-inline'; font-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' stackexchange.com
Content-Security-Policy: default-src *; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval' http://www.google.com;
content-security-policy: default-src 'self' * 'unsafe-inline' 'unsafe-eval' data: blob:
Content-Security-Policy: default-src 'self' 'unsafe-inline' 'unsafe-eval' data: blob:
content-security-policy: default-src * 'unsafe-inline' 'unsafe-eval' data: blob:
Content-Security-Policy: default-src 'self' cdn.chorke.org
|
Content Security Policy » Nginx
server {
server_name academia.chorke.org;
# …more…
add_header X-Frame-Options "SAMEORIGIN";
add_header Referrer-Policy "same-origin";
add_header X-Content-Type-Options "nosniff";
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
add_header Content-Security-Policy "frame-ancestors https://shahed.biz; default-src * 'unsafe-inline' 'unsafe-eval' data: blob:";
add_header Permissions-Policy "camera=('none'), microphone=('none'), geolocation=('none'), payment=('none')";
# …more…
location / {
return 301 https://academia.chorke.org$request_uri;
}
}
|
nginx -t
systemctl restart nginx
|
Content Security Policy » Nginx » Ingress
|
Nginx » Ingress | ||||
|---|---|---|---|---|
|
Permissions Policy
Permissions-Policy: camera=(), microphone=(), geolocation=()
Permissions-Policy: camera=('none'), microphone=('none'), geolocation=('none'), payment=('none')
Permissions-Policy: geolocation=("https://advertiser.example.com" "https://analytics.example.com")
permissions-policy: accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()
|