写点什么

谷歌开源 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:213546

评论

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

YashanDB安装初始环境调整

YashanDB

数据库 yashandb

2025 年 Java 工程师必备的 AI 工具链配置方案

飞算JavaAI开发助手

PM求职必备软件!这10款工具助你变身Offer收割机!

职场工具箱

产品 效率工具 产品经理 求职 办公软件

联想AI服务器首次实现低于1TB本地部署DeepSeek满血大模型

新消费日报

财务领导者应如何转型以提高企业运营的效率

智达方通

企业管理 财务管理 财务规划

YashanDB安装前服务器准备

YashanDB

数据库 yashandb

比 cursor 更懂中国程序员,飞算 JavaAI 助力代码平权

飞算JavaAI开发助手

INFINI Labs 推出 Coco AI,携手 DeepSeek 打造下一代企业知识管理神器!

极限实验室

console Gateway easysearch CocoAI

Deepseek R1 的技术揭秘与低成本复现,中科院计算所工程师『致 Great』的分享实录已整理!

ModelWhale

人工智能 大数据 大语言模型 DeepSeeek

Kubernetes Secrets 加密实践

俞凡

Kubernetes 云原生 安全

YashanDB目录划分

YashanDB

数据库 yashandb

如何在 NocoBase 中实现 CRM 的线索转化

NocoBase

开源 低代码 开发工具 教程 CRM

Markdown 区块的妙用

NocoBase

开源 markdown 低代码 开发工具 教程

2025 Lakehouse 趋势全景展望:从技术演进到商业重构

镜舟科技

开源 架构 iceberg LakeHouse StarRocks

企业级智能办公演进:基于低代码平台的流程自动化与系统集成架构设计

不在线第一只蜗牛

YashanDB安装前依赖项准备

YashanDB

数据库 yashandb

Appple 超级体验官招募!大声说出你的宝藏 App~

声网

荣耀一箭,射穿PC行业的苹果屏障

脑极体

AI

《Operating System Concepts》阅读笔记:p179-p179

codists

操作系统

GPU 云服务器的软件系统设计和实践

Baidu AICLOUD

GPU服务器 百度百舸 百度太行

动手魔改属于自己的 Frida

LLLibra146

Frida Android 逆向

02 HarmonyOS Next仪表盘案例详解(一):基础篇

全栈若城

HarmonyOS NEXT

YashanDB安装前操作系统参数调整

YashanDB

数据库 yashandb

使用 OpenLIT 对 LLM 应用进行可观测

观测云

OpenTelemetry LLM

百万技术博主实测:AI+Java 一键写程序 ,写一句代码算我输

飞算JavaAI开发助手

03 HarmonyOS Next仪表盘案例详解(二):进阶篇

全栈若城

HarmonyOS NEXT

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