Web开发安全注意条例
以下是一些在Web开发中可以注意的安全相关的点
输入输出
- 从外部获取的数据都要做有效性检查,数据范围、数据类型、边界值
- 格式化字符串时,依然要检验用户输入的合法性,避免造成系统信息泄露或者拒绝服务
- 用户输入的数据首先应该过滤特殊字符,原文存储。信息输出到浏览器之前对HTMl标记进行转义
- 防止命令注入攻击:把输入参数作为命令的一部分来执行时,应对参数做过滤或者合法性检查或者转义
- 对于不可信的数据,输出到客户端前必须先进行HTML编码
- 不将用户输入串直接加入html文件、js脚本、xml文件、配置文件、模板文件
- 对于有规则可循的输入,例如email地址、日期、小数等,应使用正则表达式进行白名单校验
身份验证
- 对所有的网页和资源都要求进行身份验证,避免非授权访问,所有的身份验证过程必须在服务器后端上执行
- 普通用户不允许修改其他用户的账号、密码,不允许修改系统设置
- 禁止在系统中预留任何的后门账号或特殊的访问机制
- 登录入口应具有防止暴力猜解及撞库猜解的措施,超过设定失败次数需要启用锁定或者图片随机码进行访问限制
- 采用HTTPS POST请求方式传输身份验证的凭据信息和其他敏感信息
- 身份验证的失败提示信息采用模糊处理,不要使用“用户名错误”或者“密码错误”等明确提示
- 在执行关键操作(如个人密码修改操作)时,应对用户身份进行再次验证
- 当用户输错三次密码后启用图形验证码,图形验证码应一次一用、10分钟内有效、有一定复杂度和混淆、服务端认证
- 用户名、密码和验证码必须在同一个请求中提交给服务器,必须先判断验证码是否正确,否则直接提示验证码错误
密码安全
- 采用基于哈希算法和加入盐值方式安全存储口令信息
- 密码重设和更改操作,需要进行二次合法身份验证,应对手机号或邮箱进行有效验证
- 当密码重新设置时,应短信通知用户操作
- 密码复杂度设置:建议8字符以上,包含字母、数字及特殊字符,并做弱密码检测
- 密码不能输出到日志和控制台,数据库连接配置中的用户密码要以加密的形式存储
- 密码应设计定期修改提醒机制
会话安全
- 用户登出后应立即清理会话及其相关登录信息
- 对敏感数据必须使用POST,当仅为查询操作时允许用GET
- 防止会话固定攻击,每一次登录成功后必须生成新的会话ID,丢弃掉认证前带过来的会话ID
- 如需要建立自己的会话标识符,应设计成密码学上安全随机数作为会话标识,长度至少128位
- 增加Cookie安全性,添加“HttpOnly”和“secure”属性
- 会话ID的生存时间应该设置为浏览器会话,如果有N天免登录的需求,会话有效期应尽可能短
- 设置合理的会话超时时间,当浏览器闲置超过该超时时间,自动销毁服务端的会话标识,推荐10分钟
- 不要再URL、错误信息或者日志中暴露会话标识符,不要将会话标识符以GET参数方式进行传递
- 服务端为每个会话执行合法的身份验证和权限控制,防止存在CSRF跨站点请求伪造漏洞
访问控制
- 将具有特权的逻辑从其他应用程序代码中隔离开
- 限制只有授权的用户才能访问文件资源、受保护的URL、受保护的功能、服务、配置或数据
- 限制只有授权的外部应用程序或接口才能访问受保护的本地程序或资源
- 服务器中创建文件时需指定合理的访问权限
- 当权限发生变更时,应记录好日志并短信通知用户
日志安全
- 不要在日志中输出敏感信息,包括系统指纹信息、会话标识符、账号密码、证件、ID等
- 确保日志记录包含了重要的日志事件数据
- 记录所有失败和成功的输入验证、身份验证记录
- 记录链接无效或者已过期的会话令牌尝试的日志
- 记录所有的管理功能操作行为,包含但不限于安全配置设置的变更
敏感信息安全
- 临时产生的敏感数据(写入内存或文件),应具有及时清除和释放机制
- 不要在HTTP GET请求参数中包含敏感信息,如用户名、密码等
- 敏感信息需要展示在Web页面上时,应在后台进行敏感字段脱敏处理
- 禁止将敏感信息(包含加密秘钥等)硬编码在程序中
- 禁止明文存储用户的密码、身份证、卡号等敏感信息
- 禁止在Cookie或隐藏域中以明文形式存储敏感数据
- 带有敏感数据的Web页面都应该禁止缓存,防止敏感信息泄露或通过代理服务器上网的用户数据互窜
- 禁止将敏感文件(如日志文件、配置文件、数据库文件等)存放在Web内容目录下
- 禁止在日志中输出敏感信息,包含但不限于系统详细信息、会话标识符、密码等
- 禁止在注释信息中包含敏感信息,比如物理路径、数据库连接信息、SQL语句,注释不输出到页面上
- 禁止在异常中泄露应用服务器的指纹信息,如版本、路径等
- 个人隐私等敏感信息禁止在云端存储,如存储需经过法务部同意和备案,并做数据脱敏和加密处理并明确告知用户
SQL注入
- 永远不要信任用户的输入,要对用户的所有输入进行校验,包含SQL语句的过滤和转义
- 不使用动态拼装SQL,可以使用参数化的SQL或者使用存储过程进行数据查询存取
- 不要使用管理员权限进行数据库连接,为每个应用使用单独的非特权权限,且配置有限的数据库连接数
XSS攻击
- 对输入的数据进行过滤和转义,包含但不限于<>"'%()&+\'"等特殊字符
- 数据添加到HTML、Script脚本、style中时,对数据进行相关转义
CSRF攻击
- 在每个关键表单中引入CSRF Token验证(会话中生成的随机串,提交后校验)
- 在关键表单提交时要求用户进行二次身份验证(密码、图片验证码、短信验证码)
- 队请求的refer做验证(如跨域、系统内部的应用)
文件上传下载
- 上传操作应设计身份验证机制,并进行合法身份校验
- 禁止把设备的文件系统的完整路径信息返回
- 只允许上传满足业务需要的相关文档类型,禁止把上传的文件直接放到DocumentRoot目录
- 限制上传任意可能被Web服务器解析的文件,比如jsp、php等,防止上传木马
- 上传文件以二进制形式下载,不建议提供直接访问(防止木马文件直接执行)
- 图片上传,要通过处理(缩略图、水印等),无异常后才能保存到服务器
- 禁止把整个Web根目录开放下载的方式来提供下载,建议通过CGI来间接请求文件见下载,CGI中做权限检查
- 禁止授予上传文件存储目录和上传文件可执行权限,文件默认应该在/tmp/目录下面,再根据需要移到相应目录
API接口安全
- 对调用方需进行身份验证,如Key、Secret、证书等措施进行验证,同时防止数据被篡改
- 调用参数认证,需设计参数容错机制,避免出现参数可遍历敏感数据安全问题
- 调用方权限控制设置,对调用频率、有效期进行控制,建议对调用行为实时检测,对异常阻拦
- 建议采用应用接入安全网关,实现APIID/KEY身份认证,加密传输,摘要签名安全保障
PHP安全
- require、require_once、include、include_once四个函数的参数来源必须非用户可控,防止远程文件包含攻击
- 禁止使用eval()等敏感函数来直接处理用户提交的字符串
- 关闭全局变量注册,隐藏PHP版本信息,发布版本应关闭PHP错误提示信息:display_errors=Off
- 设置open_basedir限制PHP应用程序可以访问的顶层目录
- 避免使用preg_replace()函数,当使用/e修饰符,replacement参数会当作PHP代码执行,建议使用preg_match()替代
- 仅允许使用Cookie来传递session id : use_only_cookies=1
- 开启HttpOnly,session.cookie_httponly=1,如果页面全是HTTPS则开启Secure
MYSQL安全
- 禁用数据库的远程访问,防止远程数据库攻击
- 修改默认的管理员用户名和密码,并删除不使用的数据库用户
- 不直接使用root账号,每个应用使用不同的账号,并设置合理的权限,禁止直接使用root账号
Apache配置安全
- 不显示版本信息,不在404页面上显示版本信息、所运行模块以及关于操作系统的任何信息
- 最少报头信息:ServerTokens=prod(http报头中只包含最少信息)
- HTTP服务器要关闭TRACE方法、禁用目录浏览、关闭WebDAV功能
其他
- 发布、归档的程序文件中禁止保留临时调试或测试用的代码
- 如果输出的HTTP头部信息(如Location)中含有来自输入的数据,需要保证不包含\n,\r\n等字符
- 在设备的Web根目录添加robots.txt文件,防止被搜索引擎索引