写点什么

谷歌开源 Sandboxed API,可对单个软件库进行安全保护

  • 2019-03-25
  • 本文字数:2681 字

    阅读完需:约 9 分钟

谷歌开源Sandboxed API,可对单个软件库进行安全保护

很多软件项目需要处理外部生成的数据,因此不能被完全信任。 例如,将用户提供的图片文件转换为不同的格式,或者是执行由用户生成的软件代码等。



如果软件库对这类数据的解析过程特别复杂的话,它很有可能会成为某些特定安全漏洞的受害者:安全漏洞诸如内存损坏,又或者是跟解析逻辑相关的的问题(路径遍历问题)。这些安全漏洞可能会造成很严重的安全问题。


为了缓解这些问题,开发人员通常使用软件隔离的方法,这种方法又被称作沙箱技术。 通过使用沙盒的方式,开发人员可以限制那些需要解析外部数据的代码,确保它们只能访问特定的文件、网络连接和其他操作系统资源。 这样最坏的情形就是,即使潜在的攻击者获取了这些代码的执行权限,他们也只能访问沙箱范围内的资源,沙箱技术将它们一并隔离了,这有效保护了其余的软件基础设施。


沙箱技术必须对攻击具有高度的防御性,能够充分保护操作系统的其它部分,同时又需要容易使用,从而让软件开发人员快速上手。 对于当前很多流行的软件隔离工具来说,它们要么无法充分隔离操作系统的其余部分,要么需要额外消耗大量时间来为每个项目重新定义安全边界。

实现一次,到处运行

为帮助这个目标的实现,谷歌开源了项目Sandboxed API(沙箱 API),该项目已在谷歌内部广泛使用,久经考验。通过 Sandboxed API,开发者可以为单个软件库创建安全策略,也就是说我们能够在软件类库内部为功能创建可重用的和安全的实现,而它的隔离粒度又刚好能保护其它被使用的软件基础设施。


Sandboxed API 主要用于访问沙箱类库中的某个软件函数,我们还开源了沙箱项目的核心 Sandbox2。 Sandox2 现在已经是 Sandboxed API 的一部分,提供了底层沙箱原语。它又被认为是一种底层 API,可以单独使用来隔离任意的 Linux 进程。

实现机制

目前 Sandboxed API 主要用于 C 语言编写的软件类库(或提供 C 绑定),未来可能会实现对更多编程语言的支持。


从全局的角度看,Sandboxed API 把沙箱里的库以及库的调用者分离到两个不同的系统进程中:宿主机二进制进程和 Sandboxee(沙箱)进程。 宿主机端的 API 对象重新封装了实际的库调用,并通过进程间通信发送到 Sandboxee,然后由 Sandboxee 中的 RPC Stub(存根)对调用重组并把它转发到原始库。


API 对象(SAPI 对象)和 RPC Stub 都由项目本身提供,前者由接口生成器自动生成。 用户只需要提供一个沙箱策略,一组允许底层库使用的系统调用,以及允许访问和使用的资源。 一旦这些条件就绪,基于 Sandboxed API 的库就可以很容易地在其他项目中重用了。



SAPI 对象的 API 同原始库的 API 非常类似。 例如,当使用流行的压缩库 zlib 时,如下代码片段实现了一个数据块的压缩(为简洁起见,我们在这里忽略了错误处理) :


void Compress(const std::string& chunk, std::string* out) {  z_stream zst{};  constexpr char kZlibVersion[] = "1.2.11";  CHECK(deflateInit_(&zst, /*level=*/4, kZlibVersion, sizeof(zst)) == Z_OK);

zst.avail_in = chunk.size(); zst.next_in = reinterpret_cast<uint8_t*>(&chunk[0]); zst.avail_out = out->size(); zst.next_out = reinterpret_cast<uint8_t*>(&(*out)[0]); CHECK(deflate(&zst, Z_FINISH) != Z_STREAM_ERROR); out->resize(zst.avail_out);

deflateEnd(&zst);}
复制代码


而如果使用 Sandboxed API,代码将会变成:


void CompressSapi(const std::string& chunk, std::string* out) {  sapi::Sandbox sandbox(sapi::zlib::zlib_sapi_embed_create());  CHECK(sandbox.Init().ok());  sapi::zlib::ZlibApi api(&sandbox);

sapi::v::Array<uint8_t> s_chunk(&chunk[0], chunk.size()); sapi::v::Array<uint8_t> s_out(&(*out)[0], out->size()); CHECK(sandbox.Allocate(&s_chunk).ok() && sandbox.Allocate(&s_out).ok()); sapi::v::Struct<sapi::zlib::z_stream> s_zst; constexpr char kZlibVersion[] = "1.2.11"; sapi::v::Array<char> s_version(kZlibVersion, ABSL_ARRAYSIZE(kZlibVersion)); CHECK(api.deflateInit_(s_zst.PtrBoth(), /*level=*/4, s_version.PtrBefore(), sizeof(sapi::zlib::z_stream).ValueOrDie() == Z_OK));

CHECK(sandbox.TransferToSandboxee(&s_chunk).ok()); s_zst.mutable_data()->avail_in = chunk.size(); s_zst.mutable_data()->next_in = reinterpet_cast<uint8_t*>(s_chunk.GetRemote()); s_zst.mutable_data()->avail_out = out->size(); s_zst.mutable_data()->next_out = reinterpret_cast<uint8_t*>(s_out.GetRemote()); CHECK(api.deflate(s_zst.PtrBoth(), Z_FINISH).ValueOrDie() != Z_STREAM_ERROR); CHECK(sandbox.TransferFromSandboxee(&s_out).ok()); out->resize(s_zst.data().avail_out);

CHECK(api.deflateEnd(s_zst.PtrBoth()).ok());}
复制代码


通过对比我们可以发现,在使用 Sandboxed API 时,需要额外的代码来设置沙箱本身以及将内存传入或传出到 Sandboxee,但除此之外,代码流保持不变。

安装测试

我们只需要几分钟时间就可以启动并运行 Sandboxed API。假设已经安装了 Bazel:


sudo apt-get install python-typing python-clang-7 libclang-7-dev linux-libc-devgit clone github.com/google/sandboxed-api && cd sandboxed-apibazel test //sandboxed_api/examples/stringop:main_stringop
复制代码


上述操作会自动安装必要的依赖项,并运行测试项目。 更详细内容可查阅入门指南,尤其是关于 Sandboxed API 的使用示例

未来计划

Sandboxed API 以及 Sandbox2 已经被谷歌内部的很多团队所使用。虽然这个项目已经很成熟,但开发团队对其未来发展仍然充满期待,而不仅仅限于维护:


  • 支持更多的操作系统—目前为止,只支持 Linux。 开发团队将研究如何把 Sandboxed API 引入到类 Unix 系统,如 BSD(FreeBSD、OpenBSD),macOS 以及 Windows 系统。移植到 Windows 系统是一项更复杂的任务,需要更多的基础工作。

  • 新的沙盒技术—随着硬件虚拟化技术的普及,通过沙盒将代码限制在虚拟机中变成了可能。

  • 系统构建—我们目前使用 Bazel 构建项目,包括处理依赖项。 但这并不是每个人都想要的方式,对 CMake 编译的支持是我们的首要任务。

  • 推广—用 Sandboxed API 来保护开源项目,该项目属于补丁奖励计划,参与者将有机会获得开发奖励。

参与进来

除了对 Sandboxed API 和 Sandbox2 的优化,该项目开发团队一直致力于增加更多的功能:支持更多的编程运行时、不同的操作系统以及可替代的容器技术。


源码码请查看Sandboxed API GitHub仓库。欢迎大家积极参与,贡献代码或任何关于项目改进和扩展的建议。


2019-03-25 17:213677

评论

发布
暂无评论
发现更多内容

MSE 费芮新金融行业标杆案例

阿里巴巴中间件

阿里云 微服务 云原生

「GitLab篇」如何用Git平台账号登录建木CI

Jianmu

开源 持续集成 CI/CD 持续部署 流水线

零故障支持数百场重大会议成功举办,HW云会议做了这些事

科技怪咖

自动化元数据管理的“七宗最”?

雨果

元数据

一箭双雕!刷完阿里P8架构师spring学习笔记+源码剖析,涨薪8K

退休的汤姆

Java 面试 阿里 Java工程师 spring、

开源一夏 |企业内部应用接入钉钉获取部门及人员信息

六月的雨在InfoQ

开源 钉钉 API 钉钉开放平台 8月月更

2022年中国生鲜电商年度综合分析

易观分析

电商 生鲜

【IT运维】Linux运维需要掌握哪些技能?

行云管家

Linux 运维 linux运维 IT运维

什么样的数据架构可以彻底解决企业数据孤岛的问题?

雨果

数据孤岛

阿里资深架构师熬夜纯手写的238页微服务容器化开发实战笔记

退休的汤姆

面试 微服务 社招 Java工程师 秋招

SAP Fiori Launchpad Tile,UI5 应用,和 PFCG Role 的对应关系

汪子熙

SAP Fiori Launchpad ui5 8月月更

阿里的职级是如何上升的,是工作经验还是能力?(附阿里面试题)

程序知音

Java 阿里巴巴 java面试 后端技术 八股文

技术开发人员:一款远超Hue的SQL工具!

雨果

sql

1对1直播源码:运行多个任务,资源如何切换?

开源直播系统源码

软件开发 一对一直播源码 直播系统源码 语音连麦app

从入门到高手,数据从业者的成长一般都要经过哪些阶段?

雨果

数据工程师必备技能

太强了!字节大佬的《设计模式宝典》越读越有意思!

退休的汤姆

Java、 面经 社招 Java工程师 秋招

如何完美的进行数字化转型?

雨果

数字化转型

SAP AMDP 介绍 - ABAP 托管的 HANA 数据库过程

汪子熙

数据库 SAP abap 8月月更 AMDP

ArkID 企业级开源 IDaaS/IAM 统一身份认证授权管理解决方案

龙归科技

开源项目 iam SSO Idaas

Hadoop与数据湖是什么关系?终于有人说明白了!

雨果

hadoop 数据湖

所有人!把膝盖准备好,这份“保姆级”的RabbitMQ笔记,你不服不行

退休的汤姆

面试 RabbitMQ 社招 Java工程师 秋招

Node js 开发入门 —UDP 编程,小白也能轻松学会

CRMEB

发展靠扩大人力规模,而不是技术研发创新,国内软件行业如何破局?

龙归科技

开源项目 Idaas 龙归科技 统一软件市场 ArkID

教育行业运维审计用什么堡垒机好?有什么作用?

行云管家

网络安全 教育 堡垒机 IT运维 运维审计

MAUI + Masa Blazor 开发带自动更新功能的安卓App

MASA技术团队

.net blazor MASA MAUI Xamarin

IBM Semeru Windows 下的安装

HoneyMoose

IntelliJ IDEA 设置 IBM Semeru JDK

HoneyMoose

【有奖评测局】阿里云容器镜像 ACR 测评团限时招募中!

阿里巴巴中间件

阿里云 云原生 容器镜像

云会议玩法升级

sofiya

LCD液晶屏和LED显示屏有什么区别?

Dylan

LED显示屏 户外LED显示屏 led显示屏厂家

大型软件团队协作中的常见难题和避坑策略|ONES 研发管理大师课

万事ONES

谷歌开源Sandboxed API,可对单个软件库进行安全保护_安全_Google Security_InfoQ精选文章