惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
Microsoft Azure Blog
Microsoft Azure Blog
V
V2EX
阮一峰的网络日志
阮一峰的网络日志
宝玉的分享
宝玉的分享
Hugging Face - Blog
Hugging Face - Blog
Y
Y Combinator Blog
Recorded Future
Recorded Future
博客园 - Franky
F
Fortinet All Blogs
The Register - Security
The Register - Security
雷峰网
雷峰网
博客园 - 【当耐特】
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
WordPress大学
WordPress大学
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Recent Announcements
Recent Announcements
S
Schneier on Security
Latest news
Latest news
S
Securelist
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Blog — PlanetScale
Blog — PlanetScale
L
Lohrmann on Cybersecurity
V
Visual Studio Blog
NISL@THU
NISL@THU
Cyberwarzone
Cyberwarzone
H
Hackread – Cybersecurity News, Data Breaches, AI and More
腾讯CDC
Spread Privacy
Spread Privacy
酷 壳 – CoolShell
酷 壳 – CoolShell
Security Latest
Security Latest
A
About on SuperTechFans
大猫的无限游戏
大猫的无限游戏
SecWiki News
SecWiki News
N
News and Events Feed by Topic
T
Threatpost
The GitHub Blog
The GitHub Blog
博客园_首页
F
Full Disclosure
爱范儿
爱范儿
The Hacker News
The Hacker News
T
The Blog of Author Tim Ferriss
Stack Overflow Blog
Stack Overflow Blog
Last Week in AI
Last Week in AI
月光博客
月光博客
C
Check Point Blog
G
Google Developers Blog
M
MIT News - Artificial intelligence
博客园 - 司徒正美

顾宇的博客

用 AI 重启生活 初始化 MacOS 关于我 再次见面,期待相遇 演讲和分享 如何通过政策红利获利?——海南发展(SZ.002163)交易复盘 2025年的总结 2024年的总结 2023年的总结 2022年的总结 《敏捷测试价值观、方法与实践》序 【翻译】函数式编程中的领域驱动设计 【翻译】通过跟踪技术债来改进你的开发实践 【翻译】不要把测试用例自动化 【翻译】持续部署 vs 持续交付 【翻译】测试替身 【翻译】做多少测试才足够 【翻译】蓝绿部署的起源 【翻译】持续部署 【翻译】作为演进式架构的微服务架构 【翻译】gRPC 的动机和设计原则 【翻译】分布式计算谬误 【翻译】微服务和分布式对象第一法则 采用 Multipass 管理本机虚拟 K8S 集群 博客主题升级到 Congo 2.0 【翻译】Terraform 最佳实践:模块组合 【翻译】Kubernetes 部署语言(Kubernetes Deployment Language) 通过 Vagrant 一键初始化 K8S 集群 2021年的总结 通过 Github Actions 部署 Mkdocs 文档 博客迁移到了新的 Hugo 主题 2020年的总结 2019年的总结 千人规模组织级 DevOps 演进的 9 个实践技巧 从技术雷达看 DevOps 的十年——容器技术与微服务 DevOps 模式 - 引入 DevOps 顾问 DevOps 模式 - 索引 DevOps 模式 - 定义你的DevOps 从技术雷达看 DevOps 的十年——基础设施即代码与云计算 DevOps 模式 - 采用模式语言讨论 DevOps 从星巴克店面运营学习 DevOps 从技术雷达看 DevOps 的十年——DevOps与持续交付 【翻译】微服务安全:所有应该被问到的问题 云原生下的 DevSecOps 实践 【翻译】软件定义交付宣言 微服务演进中的经验和反思 迟到的 2018 年终总结 成功微服务实施的组织演进 从第19期技术雷达看 DevOps 的发展趋势 成功微服务实施的技术演进 我们如何衡量微服务的成功? 关于四周四 AWS 架构工作坊的设计和实践 讨论微服务之前,你知道微服务的 4 个定义吗? 公有云(AWS)上的生产环境架构优化案例和迁移套路总结 公有云(AWS)上的生产环境性能分析案例 一怒之下,我又写了一个开源流量测试工具 采用 DevOps 故事落地 DevOps 测试驱动开发 Nginx 配置 云原生 DevOps 翻译-混沌工程的原则 Serverless 风格的微服务的持续交付 从最新一期技术雷达看 DevOps 的发展 关于 DevOps ,咱们聊的可能不是一回事 Serverless 风格的微服务的架构案例 提升微服务实施效率的 7 个步骤 微服务实施常被忽视的 5 个难点 你的 CI 在挖矿吗? DevOps前世今生 - 4. DevOps 的文化 DevOps发展的九个趋势 DevOps 前世今生 - 3. DevOps 的目标和核心 DevOps 前世今生 - 2. DevOps 矛盾从何而来 DevOps 前世今生 - 1. DevOps 编年史
不要让你的持续集成服务器成为安全隐患
顾宇 · 2017-03-03 · via 顾宇的博客
  1. 顾宇的博客/
  2. Blogs/
  3. 不要让你的持续集成服务器成为安全隐患/

最近临时接手了一个客户测试环境和产品环境的维护工作。接手的客户资产里包含:代码库,生产环境主机,测试环境主机以及搭建在测试环境主机上的CI(基于Jenkins)。这个CI可以用来部署测试环境和生产环境的应用。

不久,接到了客户的一个维护请求:把最新的生产环境数据同步到测试环境里

这个维护工作需要通过SSH登录到测试环境主机上进行操作。测试主机是通过 authorized_keys 进行 SSH 认证的,因此没有用户名和密码。这样有两个好处:一方面无需生产环境用户名密码。一方面可以按需吊销不再用的客户端。这样可以避免密码泄露。所以我需要把自己的 ssh public key 交给管理员,让他把我的 key 加到可访问列表里。

悲剧的是,管理员告诉我他的 key 因为更换电脑的关系没有及时更新。所以,他也登录不上去了。而且之前所有的管理员的 key 都失效了。我手上只有CI的管理员的用户名和密码,于是一个邪恶的想法就诞生了:

既然 CI 可以执行脚本,那么我是否可以通过CI把我的key注入进去

于是我用Execute Shell的Job变成了我的命令行,通过CI运行日志得知了宿主用户的文件目录信息。然后把自己的ssh public key加到了登录列表里(此处省略敏感信息):

1
2
sudo sh -c “cp \~/.ssh/authorized\_keys \~/.ssh/authorized\_keys.bak”
sudo sh -c "echo ‘{**你的****ssh public key**}’ \>\> \~/.ssh/authorized\_keys"

It works !

我成功的登录了机器,但这却暴露了一个问题:CI有可能会成为一个安全隐患。

首先,CI可以执行代码。这就意味着它有可能执行有害代码。

其次,CI缺乏足够的用户鉴权,这很有可能导致未授权用户访问。

那么,如何构建一个更安全的 CI 服务器 #

rootless原则 #

“神操纵着万物,你感觉得到他,但永远看不见他。” ——《圣经·希伯来书 11:27》

在服务器的世界里,root用户就是神,具有至高的权力和力量。如果有人获得了”神力“,后果可能不堪设想。

无论是Web服务器,还是CI服务器。都是这个世界里的二等公民,权限和力量都应该受到约束。执行的时候应该“

此外,应该极力避免sudo的滥用,尤其是对那些从外部访问的用户。很多情况下,为了操作方便,很多用户都有sudo的权限。但这恰恰造成了低权限用户提升自己的访问权限进行有害操作。

在上述的故事里,因为没有对Jenkins的主机用户做有效的隔离,导致了我可以用sudo注入自己的key获得机器的访问权限。

沙盒隔离原则 #

因为CI会执行脚本或运行程序,而这些程序和脚本极有可能是不安全的。所以,CI任务应该在隔离的安全沙盒中执行,例如:受限的用户,受限的权限,受限的空间。

在上述的故事里,我就通过CI执行了一段不安全的脚本成功获得了登录主机的权限。

如果这些任务执行在隔离并受控的Docker容器里,那么会安全得多。

也可以考虑采用TravisCI这样的第三方CI服务来保证安全性。

备份和备份核查原则 #

在上述的故事里,因为缺乏有效的备份机制,导致了所有人都失去了对主机的访问。此外,我在修改authorized_keys的时候先进行了备份。这样,如果我注入失败,还可以还原。

这里的备份,不光是对配置,数据的备份,还有岗位的备份。

如果有备份的管理员,完全不会出现这种事情。

如果有备份QA服务器,完全可以不需要当前的QA服务器。

在做任何变更前,都应该做好备份以及还原的准备。因为任何变更都会带来“蝴蝶效应”。

但是,光备份是不够的。如果备份不能有效还原,那和没有备份没有什么区别。所以,要定时的进行备份恢复测试。确保备份在各种情况下可用。

多重要素身份验证原则 #

上述的CI是暴露在互联网中的,任何一个人访问到这个站点,通过一定程度的密码破解,就可以获得这个CI的访问控制权限。从而可以做出上述的操作。

所以,有了用户名和密码,并不一定是可信用户。所以需要通过更多的手段,诸如手机短信验证码或者第三方认证集成来验证用户的身份。

关键操作手动验证原则 #

试想一下,如果上述的例子我并没有服务器的访问权限。而是通过提交未经审查的代码自动运行测试脚本。实际上也会造成同样的效果。

有时候我们会为了方便,让CI自动触发测试。但是,恰恰是这种“方便”,却带来了额外的安全隐患。而这样的方便,不光方便了自己,也方便了恶意入侵者。

所以,不能为了方便而留下安全隐患。在关键操作上设置为手动操作,并通过一定的机制保证关键操作的可靠性才是最佳实践。

构建安全 CI 的几个实践 #

  • 采用Sibling的方式在Docker里运行CI任务。
  • 账户密码管理统一采用LDAP认证,如果过期则从外部修改。
  • CI的登录权限和其他的认证方式(比如GItHub,Okta等)集成起来。并用组限制登录。
  • 对于生产环境的CI,通过更加细粒度的权限限制来隔离一些危险操作。

官方的安全指南 #

不少CI软件的官方都提供了最佳实践以及安全指南帮助我们更好的构建CI服务器。请务必在构建CI前阅读并理解这些安全实践和措施,并遵照安全最佳实践构建CI服务器:

Jenkins 最佳实践:https://wiki.jenkins-ci.org/display/JENKINS/Jenkins+Best+Practices

Jenkins 官方安全指南https://wiki.jenkins-ci.org/display/JENKINS/Securing+Jenkins

如果没有这些如果 #

上面提到了太多的如果。如果这些“如果”能发生在事前,这些问题就不会产生。CI本身是开发的最佳实践,但如果缺乏安全的意识,一味的追求方便和高效,则会带来很大的安全隐患。技通过一些简单而基础的措施和手段,我们就能大大的减少安全隐患。

感谢 ThoughtWorks 高级咨询师赵朝朝,蒋帆对本文的建议