如何增强Linux内核中的访问控制安全

背景

前段时间,我们的项目组在帮客户解决一些操作系统安全领域的问题,涉及到windows,Linux,macOS三大操作系统平台。无论什么操作系统,本质上都是一个软件,任何软件在一开始设计的时候,都不能百分之百的满足人们的需求,所以操作系统也是一样,为了尽可能的满足人们需求,不得不提供一些供人们定制操作系统的机制。当然除了官方提供的一些机制,也有一些黑魔法,这些黑魔法不被推荐使用,但是有时候面对具体的业务场景,可以作为一个参考的思路。

Linux中常见的拦截过滤

本文着重介绍Linux平台上常见的拦截:

  1. 用户态动态库拦截。
  2. 内核态系统调用拦截。
  3. 堆栈式文件系统拦截。
  4. inline hook拦截。
  5. LSM(Linux Security Modules)

动态库劫持

Linux上的动态库劫持主要是基于LD_ PRELOAD环境变量,这个环境变量的主要作用是改变动态库的加载顺序,让用户有选择的载入不同动态库中的相同函数。但是使用不当就会引起严重的安全问题,我们可以通过它在主程序和动态连接库中加载别的动态函数,这就给我们提供了一个机会,向别人的程序注入恶意的代码。

假设有以下用户名密码验证的函数:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char passwd[] = "password";
if (argc < 2) {
printf("Invalid argc!\n");
return;
}
if (!strcmp(passwd, argv[1])) {
printf("Correct Password!\n");
return;
}
printf("Invalid Password!\n");
}

我们再写一段hookStrcmp的程序,让这个比较永远正确。

#include <stdio.h>
int strcmp(const char *s1, const char *s2)
{
/* 永远返回0,表示两个字符串相等 */
return 0;
}

依次执行以下命令,就会使我们的hook程序先执行。

gcc -Wall -fPIC -shared -o hookStrcmp.so hookStrcmp.c
export LD_PRELOAD=”./hookStrcmp.so”

结果会发现,我们自己写的strcmp函数优先被调用了。这是一个最简单的劫持 ,但是如果劫持了类似于geteuid/getuid/getgid,让其返回0,就相当于暴露了root权限。所以为了安全起见,一般将LD_ PRELOAD环境变量禁用掉。

Linux系统调用劫持

最近发现在4.4.0的内核中有513多个系统调用(很多都没用过),系统调用劫持的目的是改变系统中原有的系统调用,用我们自己的程序替换原有的系统调用。Linux内核中所有的系统调用都是放在一个叫做sys_ call _table的内核数组中,数组的值就表示这个系统调用服务程序的入口地址。整个系统调用的流程如下:

当用户态发起一个系统调用时,会通过80软中断进入到syscall hander,进而进入全局的系统调用表sys_ call _table去查找具体的系统调用,那么如果我们将这个数组中的地址改成我们自己的程序地址,就可以实现系统调用劫持。但是内核为了安全,对这种操作做了一些限制:

  1. sys_ call _table的符号没有导出,不能直接获取。
  2. sys_ call _table所在的内存页是只读属性的,无法直接进行修改。

对于以上两个问题,解决方案如下(方法不止一种):

  1. 获取sys call table的地址 :grep sys _ call _table /boot/System.map-uname -r
  2. 控制页表只读属性是由CR0寄存器的WP位控制的,只要将这个位清零就可以对只读页表进行修改。
/* make the page writable */
int make_rw(unsigned long address)
{
unsigned int level;
pte_t *pte = lookup_address(address, &level);//查找虚拟地址所在的页表地址
pte->pte |= _PAGE_RW;//设置页表读写属性
return 0;
}
/* make the page write protected */
int make_ro(unsigned long address)
{
unsigned int level;
pte_t *pte = lookup_address(address, &level);
pte->pte &= ~_PAGE_RW;//设置只读属性
return 0;
}

开始替换系统调用

本文实现的是对 ls这个命令对应的系统调用,系统调用号是 _ NR _getdents。

static int syscall_init_module(void)
{
orig_getdents = sys_call_table[__NR_getdents];
make_rw((unsigned long)sys_call_table); //修改页属性
sys_call_table[__NR_getdents] = (unsigned long *)hacked_getdents; //设置新的系统调用地址
make_ro((unsigned long)sys_call_table);
return 0;
}

恢复原状

static void syscall_cleanup_module(void)
{
printk(KERN_ALERT "Module syscall unloaded.\n");
make_rw((unsigned long)sys_call_table);
sys_call_table[__NR_getdents] = (unsigned long *)orig_getdents;
make_ro((unsigned long)sys_call_table);
}

使用Makefile编译,insmod插入内核模块后,再执行ls时,就会进入到我们的系统调用,我们可以在hook代码中删掉某些文件,ls就不会显示这些文件,但是这些文件还是存在的。

堆栈式文件系统

Linux通过vfs虚拟文件系统来统一抽象具体的磁盘文件系统,从上到下的IO栈形成了一个堆栈式。通过对内核源码的分析,以一次读操作为例,从上到下所执行的流程如下:

内核中采用了很多c语言形式的面向对象,也就是函数指针的形式,例如read是vfs提供用户的接口,具体底下调用的是ext2的read操作。我们只要实现VFS提供的各种接口,就可以实现一个堆栈式文件系统。Linux内核中已经集成了一些堆栈式文件系统,例如Ubuntu在安装时会提醒你是否需要加密home目录,其实就是一个堆栈式的加密文件系统(eCryptfs),原理如下:

实现了一个堆栈式文件系统,相当于所有的读写操作都会进入到我们的文件系统,可以拿到所有的数据,就可以进行做一些拦截过滤。

以下是我实现的一个最简单的堆栈式文件系统,实现了最简单的打开、读写文件,麻雀虽小但五脏俱全。

https://github.com/wangzhangjun/wzjfs

inline hook

我们知道内核中的函数不可能把所有功能都在这个函数中全部实现,它必定要调用它的下层函数。如果这个下层函数可以得到我们想要的过滤信息内容,就可以把下层函数在上层函数中的offset替换成新的函数的offset,这样上层函数调用下层函数时,就会跳到新的函数中,在新的函数中做过滤和劫持内容的工作。所以从原理上来说,inline hook可以想hook哪里就hook哪里。

inline hook 有两个重要的问题:

  1. 如何定位hook点。
  2. 如何注入hook函数入口。

对于第一个问题:

需要有一点的内核源码经验,比如说对于read操作,源码如下:

在这里当发起read系统调用后,就会进入到sys read,在sys read中会调用vfs read函数,在vfs read的参数中正好有我们需要过滤的信息,那么就可以把vfs_ read当做一个hook点。

对于第二个问题:

如何Hook?这里介绍两种方式:

第一种方式:直接进行二进制替换,将call指令的操作数替换为hook函数的地址。

第二种方式:Linux内核提供的kprobes机制。

其原理是在hook点注入int 3(x86)的机器码,让cpu运行到这里的时候会触发sig trap信号,然后将用户自定义的hook函数注入到sig trap的回调函数中,达到触发hook函数的目的。这个其实也是调试器的原理。

LSM

LSM是Linux Secrity Module的简称,即linux安全模块。是一种通用的Linux安全框架,具有效率高,简单易用等特点。原理如下:

LSM在内核中做了以下工作:

  1. 在特定的内核数据结构中加入安全域。
  2. 在内核源代码中不同的关键点插入对安全钩子函数的调用。
  3. 加入一个通用的安全系统调用。
  4. 提供了函数允许内核模块注册为安全模块或者注销。
  5. 将capabilities逻辑的大部分移植为一个可选的安全模块,具有可扩展性。

适用场景

对于以上几种Hook方式,有其不同的应用场景。

  1. 动态库劫持不太完全,劫持的信息有可能满足不了我们的需求,还有可能别人在你之前劫持了,一旦禁用LD_ PRELOAD就失效了。
  2. 系统调用劫持,劫持的信息有可能满足不了我们的需求,例如不能获取struct file结构体,不能获取文件的绝对路径等。
  3. 堆栈式文件系统,依赖于Mount,可能需要重启系统。
  4. inline hook,灵活性高,随意Hook,即时生效无需重启,但是在不同内核版本之间通用性差,一旦某些函数发生了变化,Hook失效。
  5. LSM,在早期的内核中,只能允许一个LSM内核模块加载,例如加载了SELinux,就不能加载其他的LSM模块,在最新的内核版本中不存在这个问题。

总结

篇幅有限,本文只是介绍了Linux上的拦截技术,后续有机会可以一起探讨windows和macOS上的拦截技术。事实上类似的审计HOOK放到任何一个系统中都是刚需,不只是kernel,我们可以看到越来越多的vm和runtime甚至包括很多web组件、前端应用都提供了更灵活的hook方式,这是透明化和实时性两个安全大趋势下最常见的解决方案。


更多精彩洞见,请关注微信公众号:思特沃克

Share

数据安全在交付中的思考

2017年7月,Equifax用户数据泄露事件使得1亿4千300万个人信息(包括社会保障号码、出生日期、地址、驾照编号)和20万9千个用户的信用卡数据被盗。该事件直接导致1.43亿美国人的个人信息的破坏和泄露。CEO Richard Smith在数据泄露之后直接提出辞职,公司股价跌幅超过8%,市值蒸发35亿美元。

2016年9月,Yahoo宣布遭遇史上最严重的数据泄露,导致5亿用户的真实姓名、电邮地址、出生日期、电话号码的信息泄露。到了12月,新的数据泄露记录被打破,10亿账户数据被窃取,除了上述那些账户信息被盗外,连安全问题和答案也一起被盗。这两次的数据泄漏使得雅虎的售价降低了3亿5千万美元。

这些问题的原因距离我们并不遥远,Equifax将其数据泄露归咎于应用程序的安全问题,可能在于Java应用程序的开源Apache Struts框架中已知的安全漏洞,在这之前的数据泄露则很多来自SQL注入或者其他的业务逻辑漏洞。

伴随欧盟的通用数据保护条例和新的网络安全法的颁布,数据安全已经成为每个企业和IT从业者都必须要关注的一个话题。而我认为依赖于传统控制论基础上的主动防御和合规理论正在逐渐丧失其领导地位,要解决数据安全的问题,需要有一个场景化的方式,体系化的方案。接下来我们逐一解析。

重中之重的是数据安全的意识,意识是能力的基础,我们只有明确了这件事对于我们业务有价值之后,才能继续后面的方法和过程。上文中的数字已经说明,数据安全对于组织和个人来说都有价值且是必须的事情。Build Security In Our DNA, 我们需要不断增强我们在安全上的意识和理解。

在明确了意识在数据安全中的作用之后,我们需要去定义数据安全到底是什么,国际标准化组织(ISO)对计算机系统安全的定义是:为数据处理系统建立和采用的技术和管理的安全保护,保护计算机硬件、软件和数据不因偶然和恶意的原因遭到破坏、更改和泄露。由此计算机网络的安全可以理解为:通过采用各种技术和管理措施,使网络系统正常运行,从而确保网络数据的可用性、完整性和保密性。

狭义的数据安全是指直接围绕数据的防护技术,主要是指的是数据的访问控制,审计,加密,脱敏等。下面几个举措可以完善数据安全性在系统或者应用构建中的实践。在业务探索和系统设计的环节,我们需要建立以数据安全性为主的分析过程,下面几点需要重点关注一下。

首先,需要明确在当前场景下法律法规的约束和要求

本文以《网络安全法》中的数据安全要求为例。涉及到技术和管理两个方面,概括起来有如下几点:

  1. 对数据访问的日志进行审计,且日志留存时间不低于六个月。
  2. 对数据进行分类,将敏感数据和普通数据区别化处理。
  3. 对重要的数据进行备份,容灾。(第21,34条)
  4. 对重要数据进行加密(第21条,31条)
  5. 对个人信息进行脱敏(第42条)

第二,需要结合数据安全目标和构建整个交付项目的数据安全评估体系

思路如下:

  1. 了解场景,做影响性评估
  2. 数据收集和数据处理的分析
  3. 数据安全实现评估
  4. 数据安全的验证和补救

第三,安全虽然现在已经逐渐和业务紧密结合,出现像态势感知、自适应安全等新的方式,但是从总体上来说,它还是来源于体系化的控制,其核心是识别风险,做出改变。

那整体的业务风险我们需要一个框架来做诠释,这其中包括:

  1. 安全的策略和架构:数据安全在设立之初应该了解到组织对于数据安全的要求,明确哪些是敏感的,哪些是隐私数据,对待不同的数据资产,组织的态度是什么。
  2. 风险,业务连续性和合规:这是控制的方式和目标,在识别差异化之后,我们要了解一些业务上的风险,这部分可以用风险分析的方法了解到业务上的风险所产生的问题,结合与具体应用的场景,需要将风险和技术威胁结合起来。
  3. 数据安全运维:这部分需要在运维或者DevOps阶段考虑到,由于数据本身有生命周期的概念,那作为运维人员,需要考虑更多来自数据完整性上的要求,需要在DevOps和运维环节定期备份数据,需要有如下的措施,第一,在生产环境中要防止机密数据的丢失,第二,需要保护和备份敏感数据。第三,需要能够通过脱敏或者其他措施屏蔽或者加密某些字段。第四,要满足个人数据隐私保护法规的要求,对于个人数据的部分进行删除和屏蔽。
  4. 数据的获取,存储,传输和接入。这是数据生命周期中的主体,也是数据保护的难点,这部分会是我们考虑的重点。
  5. 在数据获取方面我们需要关注所要处理的一些敏感数据,这些数据包括一些敏感的生产数据,知识产权,个人身份识别或受保护的信息。我们在做Discovery和Inception的过程中要处理这些不同的数据,将其分类和定义。过程大概如下,需要对元数据进行分类解析,包括PCI,PII,PHI等等,这些数据的分类和获取,需要经过客户或者用户的同意(注意:GDPR当中已经对这部分有明确的立法)。其次作为敏感的数据以及一些合规数据和日志,这部分的存取和处理,也需格外关注。第三,管理敏感数据的访问方式,谁授予访问,修改和共享敏感数据的权限需要被关注到,这其中包括对于系统用户的验证和授权,还包括对于用户的行为提供监控和审核。这部分在系统设计的时候需要重点考虑。认证方面包括服务器和服务器之间的认证,客户端之间以及用户之间的认证。而在授权方需要对不同的阶段和用户进行响应的认证,在秘钥管理以及用户身份侧进行处理。比如,应用系统采用专用的登录控制模块,对登录用户进行身份标识和鉴别,具有用户身份唯一标识和鉴别信息复杂度检查功能,保证应用系统中不存在重复的用户身份标识,身份鉴别信息不易被冒用。应对同一个用户采用两种或两种以上组合鉴别技术实现用户身份鉴别。
  6. 在云计算环境中,安全问题的形势会变得特别严峻。数据安全和隐私保护是用户关注云技术的两个主要因素。尽管学术界和行业研究了许多关于云计算主题的技术,但数据安全和隐私保护对于政府,工业和商业中的云计算技术的未来发展变得越来越重要。数据安全和隐私保护问题与云架构中的硬件和软件相关。

最后,我想总结一下数据安全策略上的理解和认识,数据安全是通过完整性和机密性的控制来实现总体安全性上的目标,所采用的方案包括身份认证,访问授权和安全审计等措施,在用户,服务以及主机端完成的数据传输的一系列实践。


更多精彩洞见,请关注微信公众号:思特沃克

Share

赋能新零售,企业数据能力建设三部曲

【摘要】

无论是新零售还是Omni-Channel,零售业的本质没有变过,依然是成本、效率和体验,变化的只是着力点的不同。如今,消费者和渠道的协同组合带来了“无界”和“精准”的两大要求。其背后的支撑很大程度上将由企业的数据能力所决定。对于传统零售业,数据能力的建设需要从三个方面进行考量:UNI-ID,数据中台建设,应用场景规划。


新零售的兴起

“未来的十年、二十年,没有电子商务这一说,只有新零售 。”这是马云在2016年的云栖大会上提出的,也是“新零售”这个词第一次出现在人们的视野里,一时间似乎每家品牌商/零售商都在思考自身的新零售转型。

如今,新零售已成为了一个老生常谈的名词。我们也观察到:

  1. 新零售领域正在通过连通全域数据、重构整体交互的方式来实现传统人、货、场三者的关系。
  2. 传统零售模式面临着数据割裂的状态,无法实现品牌商与零售商、零售商与消费者、消费者与产品、产品与服务四个环节的联通,形成闭环。
  3. 电商巨头玩家的进入对新零售的整体架构进行了重组及再融合。

在整个新零售领域,由电商平台,互联网巨头,以及传统零售商扮演的玩家开始通过电商模式创新、线下模式创新和融合创新模式尝试新零售下的不同实践。

在这样的大环境下,新风口、新技术、新物种、新玩法不断涌现,资本、新玩家不断涌入,零售行业呈现出了多年来未见的活跃气氛。越来越多的品牌商开始强调以“消费者”为核心,他们希望了解消费者的心理并投其所好,提高经营效益。甚至连奢侈品牌也不得不放低他们高冷的姿态,开始关心起了流量,线上购买和小程序。

新零售的本质

同西方150年以来爆发的零售革命一样,中国从20世纪90年代中期开始,也爆发了一场综合性的零售革命。但无论是百货商店 、连锁商店、超级市场还是电子商务等不同形式,不同阶段的零售发展始终围绕着“成本、效率和体验”展开。

从新零售的特点上来看,我们将其归纳为:线上线下同品同质同价。其中体现了成本、效率和体验的全方位融合。为了实现这一融合,在新零售的背景下,渠道依然是核心的要素。线上企业与线下商家的全方位合作即是对渠道概念的进一步拓展,更是对渠道作用的再一次升级。

消费主权时代的到来使得需求越来越个性化和多元化。消费者的关注点从性价比、产品功能等共性特征转向美学设计、价值标签等个性特征,这对产品和零售的适配度提出了更高的要求。消费者正在扮演更加积极的角色,从被动接受和选择到主动影响和创造。这也让品牌方不得不从品牌为中心转变为以消费者为中心。如何整合碎片化的媒介渠道,提供一体化的购物体验,逐渐成为他们真正关心的内容,

零售业的本质没有变过,依然是成本、效率和体验,变化的只是着力点的不同。新零售时代,消费者和渠道的协同组合带来了“无界”和“精准”的两大要求。其背后的支撑很大程度上将由企业的数据能力所决定。

传统零售的数据困局

为了更好的理解传统零售的数据困局,让我们先来看两个例子:

家乐福

1995年进入中国的家乐福,以主打线下商超为主。2009年家乐福营业额开始下滑,但直到2016年底,家乐福才开始试水APP和线上购物等尝试。但是APP的体验反馈相当差,缺少用户数据和浏览行为跟踪,无法有效的将线下的流量吸引到线上。商品方面,品类相对固定,无法提供网红产品。物流方面,不具备自有物流的能力,所以面对新零售的体验,家乐福在消费者,商品销售和物流效率的体验上都非常的差。对市民特别是年轻人的吸引力明显不足。运营模式日渐丧失其应有的活力。

盒马鲜生

2015年成立后,利用两年多的时间打造了独有的“新零售”商业模式,在2017年底开设了25家门店。盒马鲜生的商业模式来自于线上线下的整合模式:通过实体门店实现建设品牌与引流、提升消费体验、同时还作为仓储物流中心,而线下APP则成为主要销售渠道以及搜集与分析消费者的界面。另外,盒马鲜生基于“吃”的应用场景,把超市跟餐饮结合,建立新零售业态。

根据普华永道2017年零售业的调查,约52%的中国消费者通过移动设备或智能手机购物,41%的中国消费者通过社交平台获取促销信息。相比之下,这一数字在全球仅达到14%和34%。(数据来源:pwc《中国零售业: 智慧开启未来》)随着时间成本的提升,以及大量信息来源可供选择,国内消费者碎片化购物已成为常态。

传统零售业迫切的希望跟上新零售的主航道,但当他们尝试转型的时候,却发现了渠道分散、客户体验不一、成本上升、利润空间压缩等多个困局。当提及传统零售企业面临的巨大挑战时,30%的决策者认为受限于预算,21%认为太多遗留系统需要变更,20%认为难以和现有系统集成。(数据来源:pwc《中国零售业: 智慧开启未来》)

那么是什么造成了这些困局?又是什么让传统品牌商/零售商无法有效的整合自身的渠道资源,更好的实现以消费者为中心?为什么有着互联网基因的零售企业就能打破这些困局呢?

答案或许正是传统品牌商/零售商过早的拥抱了现代化IT建设。其庞大厚重的IT基础设施无法支撑全渠道时代下,随需应变的数据能力要求。

比起有着互联网基因的零售企业,他们更早的采用了商业套件,更早的使用传统的ERP,CRM等系统,通过数据仓库来管理企业的商品数据,客户数据,企业运营等数据。这些数据之间以相对独立的方式运行了几十年,横向扩展性差,数据拉通性也不够理想,最终造成的是实体门店、电商(自建官方商城或入驻平台)、社交自媒体内容平台、CRM会员系统的数据割裂严重。为了满足新零售时代下对于消费者和渠道利用的要求,传统品牌商/零售商开始被迫的使用独立部署的方式响应业务发展带来的需求。应用烟囱一个接一个的竖起。让本身就无法实现数据拉通的IT架构雪上加霜。

对于IT部门,他们有心无力,既缺乏转型的技术能力,又得不到企业内部的有效重视。对于业务部门,缺少有力的IT能力的支持,创新的业务实践也无法快速展开,更别提拥抱新零售了。

突围困局:建立数据能力

今天,以数据智能推进品牌建设,精准运营用户,已经是全球众多品牌的“战略标配”。数据越精准,企业产品开发的风险便越小,生产成本和损耗也会变得更低。同时,企业对消费者的感知也会更精确,营销费用也比较低。而这些数据,靠传统渠道是无法获知的。

新零售体系下,要求传统品牌商/零售商以消费者运营为核心,以数据为能源,实现全链路、全媒体、全数据、全渠道的智能化运营。从上图的零售业数据应用金字塔模型中我们能看到,用户唯一ID(用户画像),数据拉通能力是企业进行业务运营(成本,效率),用户洞察与体验优化(体验)的基石。因此,对于传统零售业,数据能力的建设需要从三个方面进行考量:UNI-ID,数据中台建设,应用场景规划。

UNI-ID(统一身份识别体系)

目的

品牌商/零售商想要了解他们的顾客,必须先回答以下6个问题:

  • WHO——顾客是谁,他们到底长什么样子,有什么偏好?
  • WHEN——他们一般什么时候来,多长时间来一次,一次来多久?
  • WHERE——他们一般都会去哪些位置,这些位置之间有什么联系
  • WHAT——他们来的时候都做了一些什么事情
  • WHY——为什么要做?可不可以不做?有没有替代方案?
  • HOW ——他们是怎么做这些事情的?如何提高效率?如何实施?方法是什么?

在全渠道时代,这些问题的答案分布在不同的消费,行为,兴趣,社交等数据中。为了勾勒出真实的用户,我们就需要建立基于消费个体/群的身份识别体系。汇聚碎片化的用户信息,对应到个人/群体,才能360度地描绘出基于消费个体/群的画像,帮助企业更好地进行消费者资产管理。进而对这个虚拟的人进行全景分析,分析内容兴趣偏好、购买偏好、态度偏好等,基于这些数据,为品牌的决策提供数据支持。

做法

很多企业的管理者都已经意识到,在新零售的环境下,不仅要采集用户的线上数据,更需要采集线下的数据,这样才能让用户的行为数据从独立的信息孤岛,真正串联起来,实现由点到面的质变。

为了实现UNI-ID,可以从两种方式进行切入:

运营驱动型UNI-ID

不是每一个传统的品牌商/零售商都可以一蹴而就的实现UNI-ID的能力建设。面对割裂严重,甚至是残缺少量的用户数据,企业需要一个较长的改造过程。在这期间,回归本源,通过运营流程的设计引导用户按企业希望的方式提供关联性数据,可能是一个更加理性和有效的方式。

所谓的运营驱动型UNI-ID,是指品牌商/零售商先以可作为唯一ID的手机号码或者身份证号来标识不同的顾客;通过对现有渠道数据采集方式和内容的梳理,分析线上、线下不同用户触点间为了达到统一身份识别所存在的差异;针对这些差异,设计对应的运营流程来补全缺失的数据。如:线下表单注册,到店注册好礼,手机互动等。逐渐积累数据过渡到以数据驱动的UNI-ID的建设上来。

数据驱动型UNI-ID

数据驱动的UNI-ID属于相对高阶的玩法,需要企业已经积累了一定量的消费者数据,且在多个渠道上有不同的触点可以不断跟踪获取消费者行为的增量数据(如:Wi-Fi指纹、MEMS、蓝牙推送、NFC会员卡、3D传感+视频监控、线上埋点等)。

在建立UNI-ID体系的时候,不再需要通过手机号码或身份证号这些信息来形成用户唯一标识(当然,如果存在,效果更好),而是通过采集所有消费者账号、行为数据等重构为一个虚拟的人。通过数据分析、机器学习等技术对用户建模,将增量的用户行为数据归并到虚拟消费者身上,随着行为的越来越多,数据越来愈大,标签越来越多,这个虚拟消费者就会越来越趋近于真实世界的那个他。

数据中台

目的

无论是UNI-ID,还是智能零售应用,它们都需要依靠底层打通的数据进行支撑,这点十分考验品牌商/零售商对数据采集、整理、分析和应用的能力。所以数据中台的建设是企业避不开的环节,也是悬在企业头上的达摩克利斯之剑。

数据中台为品牌商/零售商提供了一个场所和工具,以数据-业务一体化为核心,将跟品牌,消费者相关的多维度数据,沉淀到数据中台中形成数据资产,通过数据的闭环能力进行分析、再利用和再营销,帮助实现营销和用户运营的再优化。

新零售时代,不再区隔线上和线下消费者,消费者与品牌商/零售商互动的过程,跨越了实体渠道和数字化渠道的多个触点。因此,在架构上,要求把零售主数据(包括:商品、顾客、价格)、动态数据(包括:库存、订单)集中处理,沉淀到数据中台中,作为唯一可信数据来源的数据中台在其中可以对接多样的业务前端,支持业务前端的灵活变化,将这些功能从相对死板的ERP,CRM中解放出来,解决了商业套件不适应全渠道时代的问题。

做法

数据中台的架构大同小异,相信很多传统品牌商/零售商已经听出了茧。但同时,他们又对平台,中台等词汇有着一种抵触的情绪,觉得太大了,太重了。其中牵涉到的业务环节太多了,可谓牵一发而动全身。甚至连阿里巴巴如此雄厚的技术能力,也需要花费多年,投入巨大的财力和精力才成功的完成了数据中台的转型。传统品牌商/零售商的IT能力本身就相对薄弱,所以虽然知道了概念,理解了数据中台能带来的好处,但是迟迟未曾有实际的动作。

其次,现成的一些平台套件也无法完全满足传统零售差异化的业务需求,所以势必需要企业采用完全定制化的做法。数据和智能创新所带来的不确定进一步让品牌商/零售商裹足不前。

数据资产的安全性又是另一方面的考量,不得不承认阿里中台能力的对外开放,能够帮助传统品牌商/零售商快速建立数据中台的相应能力,但如果从长远来看,企业的数据无法沉淀下来为己所用,数据安全性上的担忧势必要求企业进行取舍。

面对这样的一种业界需求,ThoughtWorks结合自身多年来在敏捷实践和微服务架构的技术能力,采用精益数据资产中台的方案,帮助企业完全定制化的快速建立数据中台的基础能力,通过后续的迭代演进,为企业实现数据资产的沉淀。

将原本横向叠加的建设方式演变为纵向切分,逐步完善。 MVP阶段就能满足基本的数据应用能力。 轻量、敏捷的部署方式让企业能够快速试错,迅速建立数据中台能力。

应用场景的数据化

目的

无论是盒马鲜生、超级物种、连咖啡,还是小米之家等,这些“新物种”无一不是基于消费者的场景化需求而出现的。电子小票、专属导购客服、客户到店数据采集也是诸多应用场景的成功实践。

定位到正确的场景,就是成功了一半。品牌商/零售商之所以要做UNI-ID,要建设数据中台,要搭建智能应用,其目的都是为了实现应用场景的下沉。所以无论数据中台搭建得多么强大,UNI-ID体系建设得多么完善,没有应用场景的支撑,数据就只是存储着的0和1而已,没有任何商业价值。

同时,有了成功的应用场景,消费者才愿意与品牌商/零售商进行互动,有效的互动过程中,才能帮助企业拿到真实的用户数据,反哺和优化现有的“人-货-场”数据资产,让其发挥更高的价值。

做法

应用场景的规划不是天马行空式的,需要符合企业的战略发展,满足未来落地的实际需求。品牌商/零售商在面对行业中不断涌现的“新玩法”,“新物种”时,总有一颗跃跃欲试的心,此时更要求决策者们冷静的思考,根据实际的需求,现状和数据能力判断投入和产出。

长期的实践让我们对于这样的规划形成了一套独有的探索-定义-验证-规划的方法。能够帮助品牌商/零售商从战略的角度出发,结合自身的业务现状进行理性的调研和分析,通过发散-收敛的循环往复,勾勒出应用场景的雏形。 对数据的探索和关联成为了数据化应用场景的关键,这一过程中涉及诸如:内部数据的勘查,外部数据的调研,数据成熟度分析,数据的场景化匹配等内容。

下图展示了一个应用场景的规划所涉及的内容(参考):

效益指数和紧迫性指数将决定着应用场景列表中有哪些场景是需要优先被测试模拟的。通过POC验证高优先级的应用场景,便于对数据需求进行调整和优化。通过创建-设计-定义-测试的闭环进行迭代后,最终形成了数据化后的应用场景。

结语

零售业是一个数据密集的行业,商品、供应链以及用户挖掘等方面有极多的数据应用。除了上文提到的UNI-ID、数据中台和应用场景,品牌商和大型零售企业还需要关注数据治理,数据安全等多个新零售时代下的难题。

在传统零售时代,从产品的规划设计到送达消费者使用的整个供应链中,我们依靠人力来做出联动和商业决策,自然会流失很多的商机。也无法整体发掘我们为消费者带来的价值。

在新零售时代,品牌商/零售商端到端的转型已迫在眉睫。在通过数字赋能优化决策和转型的过程中,数据令品牌能够快速反应,及时改进销售策略、调整产品。

数据能力决定了谁能把握新零售的机会,谁又将被历史所淘汰。


更多精彩商业洞见,请关注微信公众号:ThoughtWorks商业洞见

Share

第三方组件安全剖析

Apache Struts2再曝高危漏洞

前段时间,Apache Struts2又接连曝出了两个高危远程代码执行(Remoce Code Execution,下文简称RCE)漏洞(CVE-2017-5638)。为什么要说“又”呢?那是因为这早就不是Apache Struts2第一次曝出这类漏洞了。

你应该还有印象,早几年前Apache Struts2披露了一系列RCE漏洞,而且他们家在披露RCE漏洞的同时还附带了证明漏洞存在的POC(Proof Of Concept)脚本。在那次事件中,由于POC包含的信息量太大,其本意可能是想方便开发者了解更多漏洞细节,但未曾想却为黑客攻击提供了重要线索,不得不让人觉得是“神助攻”。再加上,这种做法几乎就没给使用Struts2的开发团队留出进行修复的时间,以至于在短时间里,国内外众多使用Struts2的网站,包括一些知名网站均遭到黑客攻击,大量网站纷纷表示躺枪。

前端JS框架、库的安全性同样令人担忧

如果说现如今Struts2在新开发的应用中的使用量小到几乎可以忽略不计,它的安全漏洞所带来的影响有限,那么当下火爆的各种前端JavaScript开发框架、库当中也存在安全漏洞这一事实却让情况变得不容乐观。

早在2014年,当时的一份调查研究发现,在Alexa排名前10万的网站中,有60%的网站使用了至少含有一个已知安全漏洞的JavaScript库。时间来到2017年,美国波斯顿Northeastern University做了一次跟进调查,发现Alexa排名前13万的网站中,有37%的网站使用了至少含有一个已知安全漏洞的JavaScript库。

挑战

使用含有已知安全漏洞的第三方组件的现象为何会如此普遍呢?原因是多方面的,比如,在采用第三方组件的时候没有对其进行安全检查,或者最初该组件并没有安全漏洞,只是随着时间推移,一段时间后被发现存在安全问题并披露了出来等等。要想扭转这一局面,开发团队却也面临着不小的挑战。

挑战一:第三方组件及其版本号众多,需要快速确认哪些存在已知安全漏洞,是否受到漏洞披露的影响

无论是服务器端应用还是运行在浏览器里的前端应用,使用几十个第三方组件、库是稀疏平常的事情,更何况这还只是直接依赖的第三方组件,要是算上间接依赖(即第三方组件所依赖的第三方组件,以此类推)的话,组成一个应用的第三方组件数量将会相当可观。

在知道应用所使用的所有第三方组件之后,还需要知道各个组件的精确版本号,然后才能将组件、版本号在已知漏洞数据库里进行匹配查询,得出最后的结果。

让问题变得更加棘手的是,一个企业里往往有不止一个应用系统,而每个系统都需要定期或者不定期的做这样的排查,所需要的工作量有多么巨大可想而知。

挑战二:和时间赛跑,需要在第一时间内得到通知,以最短时间完成修复和测试,并发布到生产环境

应用在还未发布时如果遇到这类问题,开发团队有充足的时间来做出应对,但对于已经处于运营中的应用而言,时间就是生命线,这是一场和黑客争分夺秒的战争,如果不能赶在黑客进行攻击前完成修复、发布等一系列任务,那就只能祝你好运了。

挑战三:对企业持续交付能力是个考验

在第三方组件的提供商披露安全漏洞的同时,还会给出修复建议,而通常的情况是,开发团队只需要将受到影响的第三方组件升级到新版本即可。看上去这似乎一点不难,但却细思极恐。

第一,版本升级可能会带来兼容性问题,导致应用无法正常启动、使用等。解决兼容性问题就可能得花去不少时间。

第二,迈过了兼容性这一关,开发团队还得对应用进行回归测试,以确保版本升级没有破坏原有的业务功能。那么问题来了,你的团队需要花多少时间进行这一测试呢?几分钟?几小时?还是几天甚至几周?

第三,开发团队排除重重困难,避开了兼容性问题,完成了回归测试,终于走到了发布修复这一步。此时,你的团队是否能对应用进行蓝绿部署、滚动发布以保证生产环境业务不会因为部署而中断?

解决之道

创建和维护第三方组件信息库

开发团队可以将应用中所使用到的所有第三方组件,包括那些间接依赖的第三方组件,及其版本号集中收集起来,形成一个组件信息库。于是,每当有第三方组件安全漏洞信息披露出来的时候,开发团队都可以立即做出判断,了解自己的应用是否受此次漏洞披露的影响。

定期匹配排查

除了在得到第三方组件安全漏洞的信息披露通知后进行识别判断,开发团队还非常有必要主动的对所用到的组件进行定期安全检查。因为在上一步中已经识别出了所有的第三方组件及其版本号,开发团队接下来需要做的,是将这些信息在已知安全漏洞数据库(例如National Vulnerability Database)中进行匹配。

自动化

刚才已经提到,识别第三方组件及其版本号,并且还要对其进行细致的匹配排查,工作量是非常巨大的,如果没有自动化的帮助,仅仅依靠人工的话,几乎是不可能完成的任务。

幸运的是,目前已经有不少工具能帮我们完成这一工作,例如两次入选ThoughtWorks技术雷达的OWASP Dependency Check,它能自动完成第三方组件识别、漏洞数据库维护,以及漏洞匹配、生成检查报告等一些列活动。除了支持Java和.Net应用外,还支持Ruby、NodeJS以及Python应用,以及部分C/C++应用。

同类型的工具还有支持.NET的OWASP SafeNuGet,专门针对Node应用的Node Security Project等等。对于其他语言,也有各自对应的自动化检查工具,在此就不一一列举了。

贯穿整个生命周期

在应用开发过程中,第三方组件可能会不断的被加入到项目里,或者移除出去,其版本也可能会随着时间的推移而不断更改。在这个过程中,组件的的每一次变化都可能会带来新的安全隐患。

开发团队可以利用上一步提到的自动化检查工具,并将其和CI服务器集成起来,可以很容易做到在每次代码提交的时候进行一次安全检查,从而达到持续监控组件安全性的目标。

总结

应用往往使用了大量第三方组件,它们可能含有安全漏洞,给应用的整体安全性埋下隐患。开发团队和黑客一直都在进行时间竞赛,其必须要在第一时间内得到安全漏洞的披露通知,赶在黑客发动攻击之前,完成漏洞修复工作。

好在开发团队可以利用各种自动化工具,快速且全面的发现那些有问题的第三方组件,通过运行回归测试以确保原有业务行为的正确性,并且结合持续交付的能力,在不影响生产环境业务持续运行的情况下,将代码改动发布到生成环境,及时避免第三方组件安全漏洞给应用带来安全风险。


更多精彩洞见,请关注微信公众号:思特沃克

Share

8大前端安全问题(下)

《8大前端安全问题(上)》这篇文章里我们谈到了什么是前端安全问题,并且介绍了其中的4大典型安全问题,本篇文章将介绍剩下的4大前端安全问题,它们分别是:

  • 防火防盗防猪队友:不安全的第三方依赖包
  • 用了HTTPS也可能掉坑里
  • 本地存储数据泄露
  • 缺乏静态资源完整性校验

防火防盗防猪队友:不安全的第三方依赖包

现如今进行应用开发,就好比站在巨人的肩膀上写代码。据统计,一个应用有将近80%的代码其实是来自于第三方组件、依赖的类库等,而应用自身的代码其实只占了20%左右。无论是后端服务器应用还是前端应用开发,绝大多数时候我们都是在借助开发框架和各种类库进行快速开发。

这样做的好处显而易见,但是与此同时安全风险也在不断累积——应用使用了如此多的第三方代码,不论应用自己的代码的安全性有多高,一旦这些来自第三方的代码有安全漏洞,那么对应用整体的安全性依然会造成严峻的挑战。

(图片来自:http://t.cn/RlAQsZ0

举个例子,jQuery就存在多个已知安全漏洞,例如jQuery issue 2432,使得应用存在被XSS攻击的可能。而Node.js也有一些已知的安全漏洞,比如CVE-2017-11499,可能导致前端应用受到DoS攻击。另外,对于前端应用而言,除使用到的前端开发框架之外,通常还会依赖不少Node组件包,它们可能也有安全漏洞。

手动检查这些第三方代码有没有安全问题是个苦差事,主要是因为应用依赖的这些组件数量众多,手工检查太耗时,好在有自动化的工具可以使用,比如NSP(Node Security Platform),Snyk等等。

用了HTTPS也可能掉坑里

为了保护信息在传输过程中不被泄露,保证传输安全,使用TLS或者通俗的讲,使用HTTPS已经是当今的标准配置了。然而事情并没有这么简单,即使是服务器端开启了HTTPS,也还是存在安全隐患,黑客可以利用SSL Stripping这种攻击手段,强制让HTTPS降级回HTTP,从而继续进行中间人攻击。

问题的本质在于浏览器发出去第一次请求就被攻击者拦截了下来并做了修改,根本不给浏览器和服务器进行HTTPS通信的机会。大致过程如下,用户在浏览器里输入URL的时候往往不是从https://开始的,而是直接从域名开始输入,随后浏览器向服务器发起HTTP通信,然而由于攻击者的存在,它把服务器端返回的跳转到HTTPS页面的响应拦截了,并且代替客户端和服务器端进行后续的通信。由于这一切都是暗中进行的,所以使用前端应用的用户对此毫无察觉。

解决这个安全问题的办法是使用HSTS(HTTP Strict Transport Security),它通过下面这个HTTP Header以及一个预加载的清单,来告知浏览器在和网站进行通信的时候强制性的使用HTTPS,而不是通过明文的HTTP进行通信:

Strict-Transport-Security: max-age=<seconds>; includeSubDomains; preload

这里的“强制性”表现为浏览器无论在何种情况下都直接向服务器端发起HTTPS请求,而不再像以往那样从HTTP跳转到HTTPS。另外,当遇到证书或者链接不安全的时候,则首先警告用户,并且不再让用户选择是否继续进行不安全的通信。

(图片来自:http://t.cn/Rfj3Tku

本地存储数据泄露

以前,对于一个Web应用而言,在前端通过Cookie存储少量用户信息就足够支撑应用的正常运行了。然而随着前后端分离,尤其是后端服务无状态化架构风格的兴起,伴随着SPA应用的大量出现,存储在前端也就是用户浏览器中的数据量也在逐渐增多。

前端应用是完全暴露在用户以及攻击者面前的,在前端存储任何敏感、机密的数据,都会面临泄露的风险,就算是在前端通过JS脚本对数据进行加密基本也无济于事。

举个例子来说明,假设你的前端应用想要支持离线模式,使得用户在离线情况下依然可以使用你的应用,这就意味着你需要在本地存储用户相关的一些数据,比如说电子邮箱地址、手机号、家庭住址等PII(Personal Identifiable Information)信息,或许还有历史账单、消费记录等数据。

尽管有浏览器的同源策略限制,但是如果前端应用有XSS漏洞,那么本地存储的所有数据就都可能被攻击者的JS脚本读取到。如果用户在公用电脑上使用了这个前端应用,那么当用户离开后,这些数据是否也被彻底清除了呢?前端对数据加密后再存储看上去是个防御办法,但其实仅仅提高了一点攻击门槛而已,因为加密所用到的密钥同样存储在前端,有耐心的攻击者依然可以攻破加密这道关卡。

所以,在前端存储敏感、机密信息始终都是一件危险的事情,推荐的做法是尽可能不在前端存这些数据。

缺乏静态资源完整性校验

出于性能考虑,前端应用通常会把一些静态资源存放到CDN(Content Delivery Networks)上面,例如Javascript脚本和Stylesheet文件。这么做可以显著提高前端应用的访问速度,但与此同时却也隐含了一个新的安全风险。

如果攻击者劫持了CDN,或者对CDN中的资源进行了污染,那么我们的前端应用拿到的就是有问题的JS脚本或者Stylesheet文件,使得攻击者可以肆意篡改我们的前端页面,对用户实施攻击。这种攻击方式造成的效果和XSS跨站脚本攻击有些相似,不过不同点在于攻击者是从CDN开始实施的攻击,而传统的XSS攻击则是从有用户输入的地方开始下手的。

防御这种攻击的办法是使用浏览器提供的SRI(Subresource Integrity)功能。顾名思义,这里的Subresource指的就是HTML页面中通过<script><link>元素所指定的资源文件。

每个资源文件都可以有一个SRI值,就像下面这样。它由两部分组成,减号(-)左侧是生成SRI值用到的哈希算法名,右侧是经过Base64编码后的该资源文件的Hash值。

<script src=“https://example.js” integrity=“sha384-eivAQsRgJIi2KsTdSnfoEGIRTo25NCAqjNJNZalV63WKX3Y51adIzLT4So1pk5tX”></script>

浏览器在处理这个script元素的时候,就会检查对应的JS脚本文件的完整性,看其是否和script元素中integrity属性指定的SRI值一致,如果不匹配,浏览器则会中止对这个JS脚本的处理。

小结

在上一篇和本篇文章中,我们为大家介绍了在开发前端应用的时候容易遇到的8大安全问题,它们是:

  • 老生常谈的XSS
  • 警惕iframe带来的风险
  • 别被点击劫持了
  • 错误的内容推断
  • 防火防盗防猪队友:不安全的第三方依赖包
  • 用了HTTPS也可能掉坑里
  • 本地存储数据泄露
  • 缺乏静态资源完整性校验

我们希望能通过对这些问题的介绍,引起前端开发小伙伴的注意,尽可能提前绕过这些安全问题的坑。


更多精彩洞见,请关注微信公众号:思特沃克

Share