写点什么

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

评论

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

手把手教你15分钟搭建人脸戴口罩识别软硬件系统

百度大脑

人工智能 EasyDL

Linux内核源码分析方法—程序员进阶必备

Linux服务器开发

操作系统 Linux内核 内核源码 底层原理 内核开发

BI软件漫谈

格林海文

BI Tableau 帆软

量化策略APP系统开发,马丁策略交易平台

13530558032

阿里专家分享内部绝密RocketMQ核心原理与最佳实践PDF

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

MySQL information_schema 系统库介绍

Simon

MySQL

快手基于 Flink 构建实时数仓场景化实践

阿里云大数据AI技术

Tron波场链智能合约系统开发案例|波场链源码搭建

Geek_23f0c3

TRONex波场智能合约 DAPP智能合约交易系统开发 波场DAPP

InnoDB 表空间

leonsh

MySQL innodb 表空间

干货!DataPipeline2021数据管理与创新大会全篇划重点

DataPipeline数见科技

大数据 数据融合 数据管理

膜拜!终于拿到了美团大佬分享的Netty源码剖析与应用PDF

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

80W美团架构师整理分享出了Spring5企业级开发实战文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

中国法定数字货币(DCEP)全面启航!全国普及势在必行

CECBC

LVS 学习: netfilter 与 ipvs 无秘密

绅鱼片

Linux 负载均衡 LVS Netfilter IPVS

小米和网易两位资深工程师联合编写的HBASE原理与实践PDF

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

搭建太阳系3D可视化平台,科普宇宙的未知奥秘

一只数据鲸鱼

科普 数据可视化 智慧宇宙 太空

模块五:微博评论模块高性能高可用计算架构设计

kk

架构实战营

亚信数据库AIDB通过统信UOS认证,国产自主可控项目新选择

亚信AntDB数据库

国产化 国产数据库 亚信数据库AIDB

做正确的事情,而不是把事情做正确

非著名程序员

个人成长 提升认知 认知提升 8月日更

小布助手在面向中文短文本的实体链指比赛中的实践应用

OPPO小布助手

人工智能 算法 模型训练 智能助手 短文本

spring-boot 2.5.4,nacos 作为配置、服务发现中心,Cloud Native Buildpacks 打包镜像,GitLab CI/CD

Zhang

gitlab nacos CI/CD spring-boot 2.5.4 CNB

ipfs矿机公司哪家好?ipfs矿机公司实力排行?

分布式存储 Filecoin ipfs挖矿 ipfs矿机 ipfs矿商排名

迅雷不及掩耳盗铃

escray

生活记录 8月日更 搜房记

探索技术与应用融合的区块链 实现产业良性发展

CECBC

英特尔CEO帕特·基辛格:面向未来的数字化需求,推进未来计算创新、探索与颠覆

科技新消息

上游思维:凭一己之力能做些什么?

石云升

读书笔记 8月日更 上游思维

阿里专家分享的SpringCloudNginx高并发核心文档

公众号_愿天堂没有BUG

Java 编程 程序员 架构 面试

微信架构图设计&“学生管理系统”毕设架构

Imaginary

ipfs投资者靠什么赚钱?投资ipfs要多少钱?

投资ipfs要多少钱 ipfs投资者靠什么赚钱

python通过Matplotlib绘制常见的几种图形

Python研究者

8月日更

BuildPacks 打包

Zhang

Docker image CNB OCI

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