You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker AuthZ插件开发疑问:如何获取本地Linux用户实现授权绕过

Docker授权插件获取本地Linux用户的解决方案

问题原因

Docker本地unix socket连接时,授权请求的RequestBody中的User字段为空——因为Docker daemon不会主动传递本地用户信息。此时需要通过Socket的Peer Credentials获取发起请求的客户端进程的UID,再映射为用户名来实现特定用户的授权绕过。

实现步骤

1. 获取Socket的Peer Credentials

通过操作系统的SO_PEERCRED socket选项,可获取连接到Docker daemon的客户端进程的PID、UID和GID。在Flask中,需从WSGI环境中获取当前请求的Socket文件描述符,再调用系统调用解析凭证。

2. 将UID转换为用户名

利用Python内置的pwd模块,将获取到的UID转换为对应的Linux用户名。

3. 修改授权逻辑

在exec请求的判断逻辑中,添加特定用户白名单,允许其绕过授权限制。

修改后的完整代码示例

import json
import re
from re import search
import base64
from flask import Flask, request
import struct
import fcntl
import pwd

plug = Flask(__name__)

@plug.route("/AuthZPlugin.AuthZReq", methods=["POST"])
def req():
    res = json.loads(request.data)
    response = {"Allow": True}
    
    # 获取发起请求的本地用户信息
    client_user = None
    try:
        # 从uWSGI环境获取socket文件描述符(不同WSGI服务器可能有差异)
        sock_fd = request.environ.get('uwsgi.socket')
        if sock_fd:
            SO_PEERCRED = 17  # Linux系统的SO_PEERCRED常量值
            # 定义存储凭证的结构体格式:pid_t, uid_t, gid_t(各4字节)
            cred_buf = struct.pack('III', 0, 0, 0)
            cred_len = struct.calcsize('III')
            # 调用ioctl获取peer凭证
            cred_data = fcntl.ioctl(sock_fd, SO_PEERCRED, cred_buf)
            _, uid, _ = struct.unpack('III', cred_data)
            # 将UID转换为用户名
            client_user = pwd.getpwuid(uid).pw_name
    except Exception as e:
        print(f"获取用户信息失败: {str(e)}")
    
    # 处理exec请求的授权逻辑
    if search(r'/(exec)$', res["RequestUri"]) is not None:
        # 允许指定用户(例如"admin")绕过授权
        if client_user == "admin":
            response = {"Allow": True}
        else:
            response = {"Allow": False}
    
    return json.dumps(response)

if __name__ == "__main__":
    plug.run(host='0.0.0.0', port=5000)

注意事项

  • WSGI服务器兼容性:不同WSGI服务器传递Socket的方式不同,示例中使用的是uWSGI的uwsgi.socket变量。如果使用Gunicorn等其他服务器,需要调整获取Socket的方式。
  • 用户映射权限:如果授权插件运行在Docker容器内,需要将主机的/etc/passwd挂载到容器中(例如-v /etc/passwd:/etc/passwd:ro),否则无法将UID转换为用户名。
  • TCP连接场景:此方法仅适用于本地unix socket连接Docker daemon的情况。如果用户通过TCP连接,需要依赖TLS证书的CN字段等其他认证方式来识别用户。

内容的提问来源于stack exchange,提问作者pythonhmmm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 19:19:54