内容发布更新时间 : 2024/11/1 7:47:42星期一 下面是文章的全部内容请认真阅读。
安全开发规范
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日志应当尽量输出\\用来定位响应慢请求
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
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来进行日志输出,避免使用System.out.println进行输出信息,日志输出时,应避开敏感信息,日志级别建议: 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中应当至少e.printStackTrace()用于追踪问题堆栈,对于上层调用或远程调用,应当继续throw e对上层进行异常输出,不在错误响应中泄露敏感信息,包括:系
统的详细信息、会话标识符或者帐号信息
32) 尽量避免调用系统脚本进行数据操作以避免触发webshell漏洞,例如在某些条件下使用linux的date -s与lftp命令 33) 对于web应用,非底层通信模块,尽量避免使用synchronized关键字进行同步,以及lock,对于IO以及高速响应的数据通信中,例如nio,netty等,需要单jvm内进行数据锁定以及同步操作的,可以使用多线程同步关键字,对于跨jvm需要网络锁进行同步的,尽量使用db的悲观锁或乐观锁,适不同业务,通常采用乐观锁,或采用redis等带有原子操作的存储 34) 尽量避免使用vector,hashtable,需要同步时采用java.util.concurrent包下的类来处理 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 user.name from user where