Web常见安全问题分析
1. 替换默认的404、500错误页面提示;
统一错误页面
默认的错误页面有可能会暴露Tomcat、Nginx、MySQL版本等信息,可能会导致黑客针对你的特定环境版本找特定的漏洞来攻击你,避免方式就是拦截异常页面,信息,重定向到自定义错误页面中;
在网页中尽量不暴露特定的服务端内部软件版本号。
2. 上传文件要加前、后台双重验证;
-
上传文件时,加上类型校验,比如docx、doc或者pdf,
避免将所有的文件一股脑上传
。因为某些文件可能是木马病毒,上传后导致服务器崩溃,信息被窃取。 -
前台校验完文件格式后,后台必须再利用头文件判断用户上传的是否为真正的所需文件格式,网络传输过程中文件可能被拦截,导致非法篡改文件名,导致伪装文件上传到服务器;
使用双重验证的好处,避免后台过于繁重的检验压力,若用户上传的文件格式不对,根本走不到服务端,前台用户端之间拦截,减少了后台的压力;同时最大程度上保证了文件上传的安全性;
JPEG (jpg),文件头:FFD8FF
PNG (png),文件头:89504E47
GIF (gif),文件头:47494638
TIFF (tif),文件头:49492A00
Windows Bitmap (bmp),文件头:424D
CAD (dwg),文件头:41433130
3. 登录注册要加验证码、以及弱密码校验;
- 登录注册必须加验证码,登录中不加验证码可能会导致黑客使用脚本工具暴力破解密码、或者使用字典来装库,同时还会后台接口增加负载,导致服务器内存溢出;
- 弱密码校验,防止被撞库;
加入验证码和弱密码校验规则;正则表达式,网上随意搜;
4. 用户密码要加密后存入数据库;
- 用户注册时使用的密码必须加密,管理员及后台无法看到明文的密码且该密码理论上无法被反解出来;只有用户知道自己的密码,其他任何人均不可见,就算看见也是乱码;防止用户隐私泄露,避免不必要的麻烦;
- 同时,若数据库不幸被黑客盗取,盗取走的用户名和密码也无法导致用户账户被泄露;
将用户密码加密后存入数据库;MD5加密即可
5. 项目配置文件中使用加密后数据库账户和密码;
spring.datasource.url=xxx.xxx
spring.datasource.username=ENC(x1dkUSJcq+ByoSq2Z8yPrg==)
spring.datasource.password=ENC(sTrlJmqG6nBgAdi1SOSW7Q==)
即使登录到你的服务器,也没法窃取你的数据库文件!!!
tip:常用的配置写在配置文件中,好维护和好补充,线上也方便修改!
6. url中可以看出参数的方法要在controller层做验证避免SQL注入;
例如http://localhost:8080/product_detail?productId=127
显然 productId
为参数,且为int
类型,则在后台控制器对应的方法中,要加入是否为int
类型的判断,且若根据id查不到对应的信息后如何返回信息,考虑要周全;否则可能会导致url中参数被恶意注入;
同时引申出来:
- 在更新或删除数据的时候,最后先判断数据是否存在,防止出现错误提示;
- 避免真的delete数据,delete一般是不可恢复的,若误删后,会导致很麻烦,一定要谨慎,做好数据备份后再删除;
- 在MyBatis框架中,尽可能使用#来代替$;<防止SQL注入的利器>
是 P r o p e r t i e s ⽂ 件 中 的 变 量 占 位 符 , 它 可 以 ⽤ 于 标 签 属 性 值 和 s q l 内 部 , 属 于 静 态 ⽂ 本 替 换 , ⽐ 如 {} 是 Properties ⽂件中的变量占位符,它可以⽤于标签属性值和 sql 内部,属于静态⽂本替换,⽐如 是Properties⽂件中的变量占位符,它可以⽤于标签属性值和sql内部,属于静态⽂本替换,⽐如{driver}会被静态替换为 com.mysql.jdbc.Driver 。
#{} 是 sql 的参数占位符,Mybatis 会将 sql 中的 #{} 替换为?号,在 sql 执⾏前会使⽤PreparedStatement 的参数设置⽅法,按序给 sql 的?号占位符设置参数值,⽐如ps.setInt(0, parameterValue), #{item.name} 的取值⽅式为使⽤反射从参数对象中获取item 对象的 name 属性值,相当于 param.getItem().getName() 。
7. 避免在循环语句中使用DAO层的方法;
在循环中频繁调用数据库连接去进行数据的CRUD,会大大拖慢系统的运行速度,严重影响用户体验,甚至导致内存泄漏;试验表明,在for中写CRUD方法可能会导致系统慢上10倍及其以上;
- 使用略微复杂一点的SQL语言来代替频繁的在代码中CRUD;
- 使用MyBatis的一对多查询,多对多查询;
- 尝试使用Java8的Stream和parallelStream流式处理;
8. 项目中用到的流要记得关闭,防止内存泄漏;
private void close(Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
// ignore
}
}
}
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
public static void main(String[] args) {
File file = new File("D:" + File.separator + "test.txt");
InputStream in = null;
try {
in = new FileInputStream(file);
// operation input stream
// ...
} catch (FileNotFoundException e) {
e.printStackTrace();
} finally {
IOUtils.closeQuietly(in);
}
}
不关闭流可能会导致内存泄漏,内存泄漏严重会导致内存溢出,整个程序崩溃,JVM OutOfMemonry异常