终端安全一站式解决方案(GuGu)

Feei <feei#feei.cn> 2017

1 背景和思路

在整体入侵生命周期中的安全产品布局差不多的情况下,我们意识到人成为最大问题。

1.1 办公网络安全隐患

先看看我们早期的网络架构:

网络拓扑

TODO 网络架构图

入侵手段

这样导致物理攻击渗透非常的容易,之前京东就出现过类似案例。这个风险的核心问题在于进入办公网就拥有了一部分访问权限了,而进入办公网的访问控制还只能是账号密码802.1.x。

然而回过头来看,办公网对于我们实际工作中的意义是否足够大呢?员工日常工作可以分为几部分

而办公网对于我们的意义是通过专线从办公网到机房解决了访问机房资源的速度问题,也解决了局域网内的文件互传的速度问题。

那为什么授权范围从办公网再细化点,细化到每个人的电脑上呢?你的电脑是否有权限接入内网,而不是你连入办公网就有权限接入内网了。

如果不考虑任何历史包袱,我们希望能去掉办公网这个存在,每个人独立的连入内网,在任何地方都可以办公。

1.2 VPN软件的安全隐患

第一个案例我们通过强制全部员工邮箱必须绑定微信,后续每次登陆邮箱需要强制微信扫码才能登陆,以减缓邮箱被盗所带来的风险。但邮件只是一个泄露配置文件的渠道,员工下次可能把配置文件传到GitHub或者网盘上,根源文件是解决VPN配置文件和Google鉴权的配置文件泄露问题。

第二个案例则是由于安全要求需要每次连接时输入Google验证码,鉴权虽然安全但体验非常糟糕。

如果不考虑任何历史包袱,我们希望能做一套自己的鉴权协议并包一层VPN使其更方便和安全。

1.3 账号密码安全隐患

除了我们能在密码策略上增强一些,比如强制定期更改、密码强度验证、不允许使用相同相似密码等等外,还是无法彻底解决密码所带来的各类问题,比如内部系统全部增加二次验证非常影响效率。

如果不考虑任何历史包袱,我们希望的是去掉密码这种古老的验证方式,设计一套更方便、更有效的鉴权方案。

1.4 员工客户端安全

我们全员都是Macbook,所以在终端安全上能少很多Windows上的各种风险。

但之前还是出现过几次风险较高的事件,比如之前macOS端出现的几次影响较大的漏洞。

而对于一些电脑的不安全配置,我们没办法仅仅依靠意识手段去做好,必要的技术检测还是要并行的。

所以理想状况下我们希望能一个终端软件能将软件和版本信息以及安全配置信息收集上来,当出现威胁事件时以便于进行风险影响判断。

2 技术方案

2.1 入网管控

通过GuGu控制密钥,使内置的VPN软件更加安全和方便,随时随地一键即可连入内网。杜绝从办公网入口渗透进入内网的可能性,也不会再出现VPN配置文件泄露导致内网漫游。 同时为了提升开发工作效率,在原有的VPN基础上增加了科学上网功能,方便开发过程中查阅资料和学习。

全平台VPN方案

TODO 各VPN产品功能对比

OpenVPN、IKEv1(IPSec)、IKEv2、

最终选型方案

TODO 中间遇到的坑

VPN认证方案

VPN认证方案

VPN Auth Code

将上面计算的最终的结果当成密码去连接VPN。 VPN验证服务判断密码中有四处gu/ug,且密码长度为89位的话则走GuGu SID验证逻辑。

# 【拼接原始数据】拼接sessionID(会话ID)、serialNumber(序列号)、timestamp(时间戳)、分隔符(gu/ug)
original = gu + sessionID(32) + ug + serialNumber(34) + gu + timestamp(10)

# 【统一平台数据交互】转换为小写
original = tolower(original)

# 【防止请求重放攻击】取original sha1的前五位,并和original拼接
result = original + ug + sha1(original)[:5]

# len = 89
2*4 + 32 + 34 + 10 + 5 = 89 

入网架构

####科学上网


2.2 一键免密

GuGu登陆过程中集成了多重安全策略,确保了账号的安全性。其它软件就可以信任GuGu的账号登陆状态,形成一个信任链。 登陆和使用大部分的日常系统,都会唤起GuGu的授权框,实现一键免密鉴权。 当所有系统的免密鉴权全部覆盖完成后,就不存在需要密码的系统了,届时GuGu就可以接管全部系统的密码替换为随机Token,而员工将不用记住任何密码。

Web端免密技术方案

GuGu启动HTTP Server

GuGu处理获取Token请求

接入方客户端请求GuGu客户端接口

App端免密技术方案

三方系统免密方案


2.3 终端安全

鉴权的GuGu登陆体系和信任设备机制保障GuGu基础安全;通过预先收集电脑已安装的软件和版本号、安全配置信息等,当出现软件安全情报时能快速的确认影响范围;通过开启自动锁屏功能缓解离开电脑时未锁屏的风险。

信息收集

可信设备


2.4 自身加固

登陆限制

预警信息包含规则名、用户名、错误次数、IP、序列号及电脑名称

以下信息可在metabase动态配置

Token签名算法

将所有需要提交的参数的key取出来进行顺序排序,并拿到value 比如要提交k1=v1&k2=v2,则将k1,k2提取出来,拿到v1,v2

将所有value拼接成字符串,计算sha1,并附带在最终需要提交的数据中。 sign = sha1(v1+v2) 最终提交的数据k1=v1&k2=v2&sign=sha1(v1+v2)

import hashlib

def generate_sign(params):
    """
    Generate sign by params
    :param params:
    :return:
    """
    if not isinstance(params, dict):
        raise TypeError
    values = '#%$'.join(str(params[x]) for x in sorted(params))
    sha = hashlib.sha1()
    sha.update(values.encode())
    return sha.hexdigest()

params = {
    'k2': 233,
    'k1': '.cn',
    'a': 'feei',
}
sign = generate_sign(params)
assert sign == '7344da1feae2faa432c2fa8aa70839d6bedde142'
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

public static final String SEPERATE_CHAR = "#%$";
public static String generateSign(Map<String, Object> param) {
    Set<String> keys = param.keySet();
    //过滤掉sign
    List<String> sortedKeys = keys.stream().filter(key -> !Objects.equals(key, "sign")).sorted().collect(Collectors.toList());
    String calcSign = sortedKeys.stream().map(param::get).map(String::valueOf).collect(Collectors.joining(SEPERATE_CHAR));
    calcSign = DigestUtils.sha1Hex(calcSign);
    return calcSign;
}

Token交互流程

3 项目成型

在项目起始,我们也调研了几家大企业对于这些问题的解决方案,大都是常规单项解决方式。 大多数问题都是密码导致的,所以提出了一个大胆的想法,去密码。将所有密码都去掉,交由可信设备处理。 于是GuGu的雏形出来了,用一个客户端,解决上面遇到的所有问题。 整个项目涉及安全、运维、内网、IM四大团队;Mac、Windows、Android、iOS四大平台。

项目场景

项目架构

TODO 整体架构图