admin 管理员组

文章数量: 887021


2024年2月28日发(作者:扒站工具整站)

安全开发规范

1) 对服务器资源访问进行校验

推荐方式:对公开的访问url以/pub/开始,在webapp中建立filter,对所有非/pub/的访问url进行过滤,未登陆用户不允许访问,对于服务器的图片以及css,js资源,应当以nginx作为动静分离

2) Nginx中的特殊文件后缀.git|.svn|.cvs进行屏蔽,例如

location ~ ^(.*)/.svn/{

deny all;

}

3) 身份认证应避免客户端向服务器发送明文密码,在非ssl环境下,应当采用md5+salt,盐长度大于5且数字与大小写英文结合方式,服务器在收到加密的密码后,在存储与验证前进行二次加密对比

4) 对于敏感信息(如身份证与银行卡),服务器在写入最终存储前,应当进行可逆加密,如DES加密/解密,将密钥放于内网服务器上,测试环境应当无法获得生产环境密钥,即解决研发人员盗走数据的风险

5) 身份验证提示信息应当为”用户名和密码错误”,尽量避免”用户名错误”和”密码错误”

6) 接口应当尽量使用HTTP POST方式提交数据,避免使用GET方式,非内部接口提供数据应当使用https

7) 在连续多次失败后(通常为5次以上),执行锁定帐户操作,锁定时间应不小于30分钟,避免被尝试暴力破解与密码猜测

应避免弱密码,8-20位以内,数字与大小写字母结合方式,由于前后台非明文传输,弱密码检测应当在客户端与js端完成

8) 发送短信验证码、邮件应当以验证码拦截非法请求,验证码为4-6位数字与字母结合,带干扰线,验证码应当在一次验证后,无论正确与错误都重新生成,单位时间内(通常为2分钟)请求验证码的次数应当在10次以内,避免验证码被猜测攻击

9) 使用邮件找回密码功能,邮件有效时长应当小于2小时

10) 除非业务需要,应当尽量避免同一ID的并发登陆,即同一ID后登录用户应当踢掉前用户

11) 用户会话标识token应当在http的cookie中或head的其他位置,不允许将会话标识拼接入GET请求的参数或url中

12) 登陆日志的记录:将用户,登陆时间,登陆ip记录入系统日志或存储与关系型与非关系型数据库,可异步写入

13) Nginx日志应当尽量输出"$request_time" "$upstream_response_time"用来定位响应慢请求

14) 系统白名单:对于关键性业务,内部通信应当采用ip内部白名单方式,仅受限ip可访问,ip白名单可以采用iptables防火墙拦截与filter进行ip过滤方式

15) 加入XSS过滤filter,原理:采用Decorator模式,用继承HttpServletRequestWrapper的XssHttpServletRequestWrapper在getParameter中检查原参数,检测xss关键字,同理建立防SQL注入filter与防webshell的filter,系统应尽量避免jsonp这种远程跨域调用

16) 加入防CC攻击filter,动静分离后对ip进行计数,每2分钟清除ip计数,计数采用concurrentHashMap方式,对每分钟请求超过100的ip进行限制,同时建立

用户ID的concurrentHashMap计数器,对于每分钟操作超30次的用户进行锁定

17) 检测请求页面的referer,除公开页面(/pub/)外,所有需要登陆的页面,检测来源网页,对于关键页面,检测上级来源页面,对于非法机器模拟请求进行拦截

18) 防SQL注入攻击代码:DB层代码应尽量采用PreparedStatement,避开拼接sql以及直接使用statement,所有参数使用setString/setObject方式来替代问号,对于使用模糊查询,使用类似select * from user where username like %?%,之后传参,对于mybatis中${xxx}为直接参与编译的代码,应当慎重使用,尽量使用#{xxx}来进行参数写入,如实在无法避免,也需确认参数不来自于前端的输入,尽量使用mybatis或activerecord等封装好底层jdbc的方式,避免自己手动获得Connection以导致会话未关闭引起的连接数超限制

19) 对于kvdb,类似memcache与redis,应当尽量避免暴露外网端口,内部访问需要进行iptables的白名单设置,对使用者连接时,设置用户名密码,本身kvdb是允许匿名用户直连,此处应当运维方控制

20) 系统使用activemq以及其他类mq时,mq应当避免暴露任何外网端口,管理密码需要重置为复杂密码

21) 系统使用solr,elasticsearch等应当使用iptables控制访问权限,因为本身全文检索服务不提供用户权限管理模块

22) 系统使用mongodb时,运维应当关闭外网访问端口,采用用户名密码方式内网连接

23) 系统应当尽量少使用类似FCKEditor之类的富文本编辑器,如若使用,应去掉文件上传相应代码,或对文件上传进行控制,后台通过以下手段防止漏洞

① 检查用户是否登陆且有上传权限,记录上传日志

② 检查限制上传文件大小

③ 检查文件后缀(.jpg/.gif/.png/.doc/.docx/.xls/.ppt等非可执行文件)

④ 文件服务器尽量采用linux,将文件存储于/store/目录/store目录的权限为可读写,不可执行

⑤ Web应用服务器采用appuser账户启动,对本地文件夹/store/可读写,对root用户文件不可读写执行

24) Web系统应对所有的用户输入参数进行校验,去除非法与越界参数,这步验证为彻底去除xss注入的关键

25) 系统选型应避免struts2,jboss4以及其他已经发现漏洞较多的web容器和框架

26) 系统应使用log4j或slf4j来进行日志输出,避免使用n进行输出信息,日志输出时,应避开敏感信息,日志级别建议:

TRACE 底层细节执行事件以及触发的执行过程

DEBUG 调试应用程序细粒度事件

INFO 突出强调应用程序的运行过程

WARN 表明会出现潜在错误的情形

ERROR 发生错误事件,但不影响系统的继续运行

FATAL 严重的错误事件将会导致应用程序的退出

27) 403/404页面与500页面需要自定义html页面,避免由于tomcat直接打印堆栈输出敏感信息

28) 禁止表单中的自动填充功能,因为表单中可能包含敏感信息,包括身份验证信息

29) 禁止客户端缓存网页,因为可能包含敏感信息。”Cache-Control: no-store”,可以和H”Pragma: no-cache”一起使用

30) Android,iOS以及H5中不存储用户密码,必要时可存储会话标识

31) try{}catch{}在catch中应当至少tackTrace()用于追踪问题堆栈,对于上层调用或远程调用,应当继续throw e对上层进行异常输出,不在错误响应中泄露敏感信息,包括:系统的详细信息、会话标识符或者帐号信息

32) 尽量避免调用系统脚本进行数据操作以避免触发webshell漏洞,例如在某些条件下使用linux的date -s与lftp命令

33) 对于web应用,非底层通信模块,尽量避免使用synchronized关键字进行同步,以及lock,对于IO以及高速响应的数据通信中,例如nio,netty等,需要单jvm内进行数据锁定以及同步操作的,可以使用多线程同步关键字,对于跨jvm需要网络锁进行同步的,尽量使用db的悲观锁或乐观锁,适不同业务,通常采用乐观锁,或采用redis等带有原子操作的存储

34) 尽量避免使用vector,hashtable,需要同步时采用rent包下的类来处理

35) 建立工程尽量使用maven工程,用以避免jar文件混乱,输出部署jar应当以ant脚本或maven脚本进行编译

36) Mysql 基本规则:

① 单表记录控制在1000w

② 字段尽量在20个以内

③ Id为bigint自增

④ Tinyint类型的deleted字段作为伪删除标记

⑤ 有默认值为CURRENT_TIMESTAMP的Timestamp时间戳

⑥ 字段避免默认为NULL

⑦ 查询应当能落到索引上,索引在3个以内比较合适,合理使用索引,mysql会判断使用索引如仍需扫描超过全量20%的情况下,会走全表扫描

⑧ 执行select前进行explain检查是否走了全表扫描

⑨ 对于需要全文检索的数据,将数据同步入lucene

⑩ 尽可能避免触发器与存储过程

11 清空表时采用truncate table 速度快于delete,但同时会把auto_increment的值恢复为1

12 数据表使用innodb存储引擎

13 对于部分特殊场景,不需要事务,单线程写入数据量较大的表可采用myisam引擎

14 对于类似key-->map型数据,可以使用handlesocket方式直接操作innodb

15 OLTP与OLAP分割处理,对于实时高速业务应用OLTP,对于分析性数据,可以采用数据库从库方式进行读写分离

16 强业务一致场景只能走到主库操作,例如:交易完成后立即查询

17 表超过一定量(通常为单表额度1000w),可以对数据进行分库分表以及分区表操作

18 SQL查询应避免select *,采用select 具体列来替代

19 Where 条件中使用IN 与UNION 来替代OR

20 建立视图时避免使用union 与union ALL ,会导致索引失效

21 分页时采用where id>上一次最大id order by id asc limit 条数,来替代limit 偏移量,条数

22 避免使用临时内存表,临时内存表建立通常会消耗0.2秒左右,造成并发响应缓慢

23 避免使用复杂sql来响应前端用户请求,考虑数据变化不明显时,可以采用系统缓存来定时更新sql结果

24 主库写频率较高时,去掉query_cache,数据库querycache为全局锁,频繁的写入会导致锁定时间过长

25 使用decimal而不是double和float

26 对于需要使用乐观锁的表加入int version类型字段

27 函数尽量不要做为条件变量,例如避免使用select from user where

date_format(_time,”yyyyMMdd”)>20150101,而是使用select from user

where _time>’2015-01-01’,原因为如果reg_time为索引字段,使用函数后将无法落到索引上

28 可以使用外键约束,但不推荐使用级联删除

29 Mysql中建立用户应明确ip范围,权限只针对某库某表

30 Mysql监听地址仅为内网

31 Binlog仅运维人员可以接触

37) Filter中使用ThreadLocal时应当用try{}finally{}在finally中将threadLocal的set的变量清空,以避免线程池中变量被下次其他用户使用

38) 对于非线程安全的类的使用,例如SimpleDateFormat,NumberFormat可以采用ThreadLocal或在作用域内单独初始化,甚至使用时进行clone方式

39) 对于较复杂的对象,初始化时会导致线程阻塞,同步的对象,例如Calendar,不使用new

进行创建,使用clone方式进行分配内存空间,可避免线程同步

40) 不推荐使用ehcache和oscache作为二级缓存,原因在于都是线程同步导致系统变慢,少量的缓存走jvm的concurrentHashmap,大量的走redis或memcache

41) Spring mvc中controller尽量设置@Scope("prototype")以避免由于单例bean导致的数据冲突

42) Java操作数据库通常使用spring的事务配置,事务传播级别为PROPAGATION_REQUIRED,即当前没有事务时创建新事务,对于service层进行方法名称匹配时,find*/get*/select*为只读方法,对数据库的数据源配置以readonly方式,仅支持select操作,事务传播级别为无事务

43) Jdk6之后,系统允许动态编译生成运行时class文件并加载到classloader中,非性能要求极致类应用不允许使用

44) Jdk可以动态调用js脚本,js脚本中可以任意调用java的类涉及系统安全与信息泄露,非极端场景不允许使用

45) 事务隔离级别通常为repeatable,可重复读

46) 尽量避免以select ... for update 方式锁定数据,悲观锁方式当无法落到索引情况下,将会导致全表锁,且容易导致死锁发生,在场景允许的情况下,事务隔离级别为可重复读,使用乐观锁,即update .... Where version=当前版本,利用返回值是否为1来判断是否发生了并发冲突

47) 在高IO操作,例如写硬盘文件,采用ssd硬盘,内存映射,内存盘方式提高速度,使用内存映射应当循环利用文件块以避免内存泄漏

48) 尽量避免使用webservice,原因为非轻量级,解析与序列化速度慢,可使用restful或远程RPC(dubbo)来替代,所有内部通信组件,应当只监听内网地址,并通过内部ip白名单与iptables控制访问地址,例如dubbo应设定host

49) Zookeeper通过

clientPortBindAddress=内网地址

clientPortAddress=内网地址

来控制避免暴露外网

50) Tomcat应当8080,8009,8005端口应绑定内网地址

51) 所有java进程在上生产环境中关闭远程调试端口

52) 尽量避免java中直接调用c++,原因为jni/jna通信速度慢且容易引起系统崩溃,且c++

的dll或so库导致的内存泄漏难以察觉,如必须,可以采用socket,或在同一台linux服务器上进行unixsocket调用

53) 门户网站首页应当用nginx cache或者varnish静态化,

① 页面保持在200k以内,开启nginx压缩

② 将css,图片以及变化不大的js放于CDN,图片需要经过压缩,多个小图片合成为整个大图