防止 Google Kubernetes Engine (GKE) Ingress/FrontendConfig 中的主机标头注入/重定向

问题描述 投票:0回答:3

我有一个 k8s 部署,它使用 Cloud DNS托管证书(用于 SSL) 以及 k8s 服务。

我已根据 此 GKE 文档

将 HTTP 配置为 HTTPS

它工作得非常好,并将我的 HTTP 请求重定向到 HTTPS 网站。

现在,当我使用 CMD 中的以下命令测试 HOST HEADER INJECTION 的漏洞时,

curl http://staging.mysite.com --header 'Host: malicious.com'

我收到如下回复

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="https://malicious.com/">here</A>.
</BODY></HTML>

值得一提的是,我的应用程序是基于 angular 11 构建的,构建后我使用 Nginx 为应用程序提供服务。

这是我的入口和前端配置以及托管证书配置

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
    name: ssl-redirect
spec:
    redirectToHttps:
        enabled: true
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
    name: staging-service-ingress
    annotations:
        kubernetes.io/ingress.global-static-ip-name: staging-global-ip
        networking.gke.io/managed-certificate: staging-cert
        networking.gke.io/v1beta1.FrontendConfig: ssl-redirect
spec:
    defaultBackend:
        service:
            name: web-staging-service
            port:
                number: 80
    rules:
        - host: staging.mysite.com
          http:
              paths:
                  -   backend:
                          service:
                              name: web-staging-service
                              port:
                                  number: 80
                      pathType: ImplementationSpecific
                      path: /*
---
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
    name: staging-cert
spec:
    domains:
        - staging.mysite.com

这是我的 Nginx 配置

worker_processes 4;
error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

events { worker_connections 1024; }

http {
    server {
        listen       80;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256';
        ssl_prefer_server_ciphers on;
        server_tokens off;

        server_name *.mysite.com, mysite.com;

        types {
            module js;
        }

        sendfile on;
        include       /etc/nginx/mime.types;

        gzip on;
        gzip_http_version 1.1;
        gzip_disable      "MSIE [1-6]\.";
        gzip_min_length   256;
        gzip_vary         on;
        gzip_proxied      expired no-cache no-store private auth;
        gzip_types        text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript;
        gzip_comp_level   9;

        location / {
            root   /usr/share/nginx/html;
            try_files $uri $uri/ /index.html;
            index  index.html index.htm;
        }

        error_page   404 500 502 503 504  /404.html;
        location = /404.html {
            root   /usr/share/nginx/html;
        }

    }
    add_header Strict-Transport-Security "max-age=31536000;" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Frame-Options sameorigin always;
    add_header X-Content-Type-Options nosniff;
    add_header Referrer-Policy 'origin';
    add_header Content-Security-Policy "some rules";
    add_header Permissions-Policy "some rules";
}

我没有找到任何正确的方法来防止注射。该应用程序在当前配置下可以完美运行。

请帮助我找到适当的解决方案来防止主机标头注入

angular nginx kubernetes google-cloud-platform google-kubernetes-engine
3个回答
2
投票

GCP 通过 Cloud Armor 提供针对此类攻击的保护。 Cloud Armor 具有内置的 WAF 策略,支持防止 HTTP 标头注入等协议攻击。

您首先需要配置 Cloud Armor 策略,然后可以将其与附加到 Ingress 资源使用的后端 Kubernetes 服务(“web-staging-service”)的 BackendConfig 相关联。

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: cloud-armor
spec:
  securityPolicy:
    name: "waf-security-policy"

0
投票

我们通过

Config Connector
创建经典应用程序负载均衡器来处理到所需主机的重定向,解决了因使用 Host Header Injection
 资源中的 
redirectToHttps
 字段而导致的 FrontendConfig 漏洞:

前端配置

apiVersion: networking.gke.io/v1beta1
kind: FrontendConfig
metadata:
  name: http-https-redirect-example
  namespace: example-ns
spec:
  sslPolicy: unizin-ssl-policy

入口

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: http-https-redirect-example
  namespace: example-ns
  labels:
    role: http-https-redirect-example
  annotations:
    ingress.gcp.kubernetes.io/pre-shared-cert: http-https-redirect-example-cert
    ingress.kubernetes.io/ssl-cert: http-https-redirect-example-cert
    kubernetes.io/ingress.global-static-ip-name: http-https-redirect-example
    kubernetes.io/ingress.allow-http: "false"
    networking.gke.io/v1beta1.FrontendConfig: "http-https-redirect-example"
spec:
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: http-https-redirect-example
                port:
                  number: 80

必须将

kubernetes.io/ingress.allow-http
注释设置为
false
,以便仅为 HTTPS 创建 LB。

计算地址

# https://cloud.google.com/config-connector/docs/reference/resource-docs/compute/computeaddress
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeAddress
metadata:
  annotations:
    cnrm.cloud.google.com/project-id: example-project
  name: http-https-redirect-example
  namespace: example-ns
spec:
  address: 8.8.8.8
  addressType: EXTERNAL
  ipVersion: IPV4
  location: global
  resourceID: http-https-redirect-example

我们已经为

http-https-redirect-example
保留了 IP 地址,因此我们需要包含
spec.address
的实际外部 IP 以避免冲突。

ComputeURLMap

# https://cloud.google.com/config-connector/docs/reference/resource-docs/compute/computeurlmap
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeURLMap
metadata:
  annotations:
    cnrm.cloud.google.com/project-id: example-project
  name: http-https-redirect-example
  namespace: example-ns
spec:
  defaultUrlRedirect:
    hostRedirect: example.com
    httpsRedirect: true
    redirectResponseCode: PERMANENT_REDIRECT
    stripQuery: false
  location: global

ComputeTargetHTTPProxy

# https://cloud.google.com/config-connector/docs/reference/resource-docs/compute/computetargethttpproxy
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeTargetHTTPProxy
metadata:
  name: http-https-redirect-example
  annotations:
    cnrm.cloud.google.com/project-id: example-project
spec:
  location: global
  urlMapRef:
    name: http-https-redirect-example

计算转发规则

# https://cloud.google.com/config-connector/docs/reference/resource-docs/compute/computeforwardingrule
apiVersion: compute.cnrm.cloud.google.com/v1beta1
kind: ComputeForwardingRule
metadata:
  name: http-https-redirect-example
  annotations:
    cnrm.cloud.google.com/project-id: example-project
spec:
  ipAddress:
    addressRef:
      name: http-https-redirect-example
  ipProtocol: TCP
  loadBalancingScheme: EXTERNAL
  location: global
  portRange: 80-80
  target:
    targetHTTPProxyRef:
      name: http-https-redirect-example

一旦应用于我们的 GKE 集群,就会创建两个负载均衡器:

我们还可以验证该漏洞不再起作用:

之前(使用

redirectToHttps

$ curl http://example.com -v --header "host: fake.com"
*  Trying 8.8.8.8:80...
* Connected to example.com (8.8.8.8) port 80 (#0)
> GET / HTTP/1.1
> Host: fake.com
> User-Agent: curl/8.1.2
> Accept: */*
> 

< HTTP/1.1 308 Permanent Redirect
< Cache-Control: private
< Location: https://fake.com:443/. <-- vulnerable
< Content-Length: 0
< Date: Tue, 23 Jan 2024 02:39:55 GMT
< Content-Type: text/html; charset=UTF-8

< 
* Connection #0 to host example.com left intact

之后:

$ curl http://example.com/ -v --header "host: fake.com"                       
*   Trying 8.8.8.8:80...
* Connected to example.com (8.8.8.8) port 80 (#0)
> GET / HTTP/1.1
> Host: fake.com
> User-Agent: curl/8.1.2
> Accept: */*
> 
< HTTP/1.1 308 Permanent Redirect
< Cache-Control: private
< Location: https://example.com:443/ <-- good response
< Content-Length: 0
< Date: Tue, 23 Jan 2024 16:21:26 GMT
< Content-Type: text/html; charset=UTF-8
< 
* Connection #0 to host example.com left intact

此外,GCP 支持还向我们指出了此问题跟踪器,其中要求提供以下信息:

请在待办事项中包含将 hostRedirect LB 功能合并到 GKE Ingress 中的可能性。

目前,GKE Ingress 的 FrontendConfig 仅支持 HTTP 到 HTTPS 重定向。我们有些用户也希望通过 GKE Ingress 配置选项利用 hostRedirect 功能。


-1
投票

Web 应用程序应使用 SERVER_NAME 而不是 Host 标头。它还应该创建一个虚拟虚拟主机来捕获所有具有无法识别的主机标头的请求。这也可以在 Nginx 下通过指定非通配符 SERVER_NAME 来完成,在 Apache 下也可以通过使用非通配符 serverName 并打开 UseCanonicalName 指令来完成。 https://www.nginx.com/resources/wiki/start/topics/examples/server_blocks/

© www.soinside.com 2019 - 2024. All rights reserved.