容器镜像静态扫描原理

前言

有这样一个工具, 可以对镜像进行扫描, 拿出其中包含的软件包、lib库(pip包等)、危险文件等, 并能够识别出哪些包是存在漏洞的. 比如trivy工具. 那么他们是如何做到这件事情的呢?

正好最近在研究这块, 索性就简单谈一谈(其实原理很简单).

获取包含内容

对于镜像的存储, 层之间的关系, 以及如何将多层数据进行聚合, 可以看之前的这篇文章.

扫描单层软件包

扫描单层的数据, 说白了就是文件扫描. 比如:

  1. 获取系统版本
    • etc/os-release文件获取系统版本
    • etc/debian_version文件获取debian的版本
    • etc/lsb-release文件获取ubuntu版本
    • etc/alpine-release文件获取alpine的版本
  2. 获取系统包
    • lib/apk/db/installed文件获取安装的所有apk
    • var/lib/dpkg/status文件获取安装的所有dpkg
  3. 获取依赖库
    • 依据.jar后缀拿到所有jar
    • 依据go.mod文件名获取依赖的库
    • requirements.txt文件拿到依赖的pip
  4. 获取风险文件
    • 通过一些文件识别的扫描库, 可实现对恶意文件的识别. 比如yara

通过对本层所有文件的扫描, 就能够将当前层包含的信息全部拿到了.

多层合并

在拿到每一层的数据之后, 接下来就是将多层的数据进行聚合了. 软件包的聚合规则与文件的聚合规则相同. 可以回这篇文章复习一下文件是如何聚合的.

  1. 覆盖: 对于单文件内容, 上层覆盖下层, 比如:
    • 系统包. apk/dpkg等, 在信息修改后, 其对应的单位件会覆盖
  2. 合并: 将多层内容进行合并. 比如:
    • jar文件, 每层增加一个, 在最后将所有jar包合并到一起
  3. 移除: 之前说过, 当文件删除的时候, 会保留一个without文件. 因此, 当上层将下层内容删除时, 需要在最终聚合的时候去掉.

经过以上步骤, 整个镜像的完整信息就已经拿到了.

识别漏洞

如何识别漏洞呢? 就更简单了, 在本地数据库中维护一份漏洞库, 标识了某个系统的某个软件的某个版本, 存在某个漏洞. 然后拿着匹配到的结果一个一个找就行了.

总结

以上, 就是镜像的静态扫描原理了. 看完之后是不是发现特别的简单?

但其实写起来并没有想象中那么简单, 比如合并的操作就比较繁琐. 不过这里只介绍原理, 知道是怎么回事就行了.

还有一些扫描是动态扫描, 会将镜像启动, 然后通过攻击行为来判断是否存在某种漏洞. 不在本文的说明范围内.

订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请发表评论。x