写点什么

第 11 周学习总结

用户头像
Bruce Xiong
关注
发布于: 2020 年 08 月 26 日

安全架构

安全问题永远是架构设计中考虑的第一要素,一个系统架构中的安全主要考虑那些方面的问题呢,各个问题又如何去解决呢?



代码层

一、XSS攻击

XSS攻击的原理,是因为恶意用户输入含有一些恶意的脚本代码的信息,导致普通用户在浏览该信息时被恶意执行了。

解决办法就是利用正则表达式,对恶意的脚本进行过滤,或者转换。可以参考以下代码的实现方式。

https://github.com/finn-no/xss-html-filter/blob/master/src/main/java/net/sf/xsshtmlfilter/HTMLFilter.java

二、SQL注入

SQL注入的原理,是因为恶意用户输入查询条件信息中包含了一些 sql脚本或者脚本片断,导致恶意脚本被数据库执行导致数据库数据泄露。

解决办法:

1、对用户输入项进行正则过滤

2、MyBatis 使用 #{} 和 ${} 来进行参数值替换。

3、MyBatis中 order by 的问题。由于只能用${}用#{} 含义不一样,因此:我们就只能禁止用户可以传入order by 的字段,用户提交的参数只能是代码中定义的key,例如:order by name desc; "name desc" 这个不允许用户输入,用户只能输入 “name_desc”,我们代码中根据 name_desc 做为key在map中找到key返回的 name desc 传给查询语句,千万不可split("_") 省事。

4、MyBatis中like语句。可以用concat来解决,但是使用时也要注意对用户输入的参数进行转义,例如:‘%’、‘_’、‘\’

SELECT * FROM user WHERE name LIKE concat ('%', #{name}, '%')

5、MyBatis中 IN 条件,要用 foreach ,不要用 in ${}

SELECT * FROM user WHERE name in
<foreach item = "name" collection = "nameList" open ="("
separator="," close=")">
#{name}
</foreach>



三、端口扫描

由于我们常用的一些第三方中间件比如:Mysql、Redis、Elasticsearch等,因为是开源几乎每个公司都在用,基本上是黑客照顾的对象,但是由于某些人员的安全意识不足或者部署错误,导致Mysql、Redis、Elasticsearch的端口直接暴露在互联网上,黑客就会通过端口扫描工具去扫相关的端口进行恶意的入侵。

解决的办法:

1、所有机器对外开放(含内网)的端口实行登记、申请、开通、审核机制,像Redis、Mysql、Elasticsearch这类拒绝对外网开放端口。

2、像22这类端口也是黑客扫描的重点对象。原则上也不对外开放。建议通过堡垒机对服务器进行操作。没有条件的建议更换端口比如:将22修改成121212之类的。

3、对外提供的端口,最好只开放80或443。其余端口一律禁止面向公网开放。

四、CSRF、重放攻击

CSRF、重放攻击 的原理本质上都是一样的,恶意用户通过伪造表单请求、或者重复提交表单请求。

解决的办法:

每一次表单请求都增加一个token,token由md5(随机数、时间戳、加密串或者验证码)组成,服务器端对token进行校验。如果服务器端根据用户输入的参数生成的token=请求的token就表示是合法的。

五、文件上传漏洞

一般我们的系统都会要求用户上传图片、视频、文档之类的文件。恶意用户可能会上传一下可执行的脚本程序导致服务器资源泄露。

1、因此我们需要在服务器端限制用户上传的文件类型(不能用文件名后缀校验,应该用mine type校验)。

2、上传后的文件需要改名。

3、上传的文件只能保存在文件服务器中,不可以放在可执行的服务器中。

六、0day漏洞、序列化漏洞

这个主要是我们的操作系统、或者第三方中间件 (tomcat、fastjson)暴露的漏洞

解决办法:

随时升级系统或者第三方中间件。像:fastjson之类的反序列化漏洞,是因为:fastjson接受的JSON可以通过@type字段来指定该JSON应当还原成何种类型的对象,在反序列化的时候方便操作,如果找不到@type中的类,由于 fastjson的实现机制,利用反射机制会给我们创建一个按恶意攻击者提交的参数的类实例,这样就达到了恶意入侵我们系统的目的。最好不开启@type的功能,完全没有必要。

再一个呢,我们需要在我们的代码中禁止java执行exec指令。

@Autowired
protected void init(){
System.out.println("初始化安全问题...");
SecurityManager originalSecurityManager = System.getSecurityManager();
if (originalSecurityManager == null) {
// 创建自己的SecurityManager
SecurityManager sm = new SecurityManager() {
private void check(Permission perm) {
// 禁止exec
if (perm instanceof java.io.FilePermission) {
String actions = perm.getActions();
if (actions != null && actions.contains("execute")) {
throw new SecurityException("execute denied!");
}
}
// 禁止设置新的SecurityManager,保护自己
if (perm instanceof java.lang.RuntimePermission) {
String name = perm.getName();
if (name != null && name.contains("setSecurityManager")) {
throw new SecurityException("System.setSecurityManager denied!");
}
}
}

@Override
public void checkPermission(Permission perm) {
check(perm);
}

@Override
public void checkPermission(Permission perm, Object context) {
check(perm);
}
};

System.setSecurityManager(sm);
}
}

七、配置文件安全问题

如果服务器被入侵,可能会遭遇数据库被拖库的风险。为了防范这类风险,最后我们在配置文件中不能明文配置,数据库地址、用户名、密码或者其他敏感参数,最好通过加密的方式配置。

八、内防员工泄露客户资料

由于我们的数据库中可能记录了客户的一些重要信息,有的可能会记录客户的信用卡信息。如果一旦泄露将造成非常巨大的损失。因为我们需要对 客户的一些重要信息进行加密处理,加密所用的密钥,不可以在代码或者配置文件中,最好是采用如下图所示的,专用的密钥服务器来动态获取密钥。

下图所示:

首先:密钥是由三个角色生成,每个角色提供一个片段,密钥再分成多个片段存储在不同的设备中(每种设备管理员权限不一样)。

其次:加密、解密不能由应用服务器来做,应该是由密钥服务器提供的接口来做。保证密钥不会被应用程序获得。



利用防范安全问题

一、可以利用 IBM Rational AppScan 软件(不安利,这个软件确实好用)对我们的上线前的系统进行一次安全扫描,可以解决一大部份问题。

二、利用开源的软防火墙如:Modsecurity 进行相应的安全过滤。

三、如果特有钱可以用阿里、腾讯、网易提供的云安全服务。



用户头像

Bruce Xiong

关注

熊大 2017.10.18 加入

还未添加个人简介

评论 (1 条评论)

发布
用户头像
请添加“极客大学架构师训练营”标签,便于分类
2020 年 08 月 27 日 09:54
回复
没有更多了
第11周学习总结