规范修炼与代码安全

在编写符合规范的代码以提高可阅读性时,注意代码的安全问题也不能忽视。

互联网企业的核心就是产品,如果对软件产品安全不够重视,受到的经济损失将是无法估计的,有可能影响着企业的生死存亡。

当相关开发者心中没有安全的相关概念、项目的开发,上线及迭代更新没有相应的规范等等,这些问题都将会是导致出现安全问题

理论上来讲对于安全,无论企业规模大小,无论企业产品的重要程度如何,注重软件安全是非常有必要的。

  1. 通用安全开发规范
  2. python安全编码规范

一,通用安全开发规范

输入验证

  • 对所有输入的信息和内容都需要做必要验证,包括数据类型,长度和范围等
  • 禁止向exec()/eval()方法传递不可信、未净化的数据(当参数中包含空格,双引号,以-或者/符号开头表示一个参数开关时,可能会导致参数注入漏洞)
  • 必要时可以考虑在python中禁用exec或eval方法

输出编码

  • 必要时对所有输出字符进行编码
  • 特别包括SQL,XML,HTML,JavaScript等内容
  • 对于操作系统命令,净化所有不可信数据输出

异常处理

  • 禁止在异常中泄露敏感信息(错误信息,路径,IP,版本,架构等)
  • 发生异常时要恢复到之前的对象状态(业务操作失败时,进行回滚业务;或者避免去修改对象状态,维持对象状态一致性)

身份验证

  • 除了那些特定设为“公开”的内容以外,对所有的网页和资源都要求进行身份验证,并正确设计身份验证功能
  • 所有的身份验证过程必须在服务器后端上执行
  • 所有的身份验证控制应当安全的处理未成功的身份验证,比如给出错误模糊提示,隐藏敏感信息
  • 登录入口应具有防止暴力猜解及撞库猜解(利用已泄漏的密码字典进行批量登录尝试)的措施,超过设定失败次数需要启用锁定或图片随机码进行访问限制
  • 在执行关键操作(如个人信息密码修改操作)时,应对用户身份进行再次验证
  • 为高度敏感或重要的交易账户使用多因子身份验证机制,如支付密码、短信验证码等

短信验证码

  • 发送频率控制(建议60s获取一次)
  • 验证码有效期(建议60s内有效,发短信时进行友好提示)
  • 复杂度(短信验证码建议6位数字)
  • 一次一用,次数限制,防止被黑客恶意消耗短信
  • 在前端校验只能作为辅助手段,很容易被绕过,必须使用服务端代码对输入数据进行最终校验

图形验证码

  • 一次一用
  • 验证码有效期(10分钟内有效,可根据场景兼容安全和体验灵活设置)
  • 复杂度(4位及以上数字、字母交替),根据需要也可采用当下流行的拖拽验证码或计算值的验证方式
  • 服务器端进行认证
  • 从用户体验和安全角度出发,可设计为当用户输3次错误密码后自动弹出验证码输入框进行验证操作

密码管理

  • 所有密码不得明文处理,必须选择加密
  • 禁止使用私有或者弱加密算法,推荐使用AES: 128位,RSA: 2048位,DSA: 2048位
  • 密码重设和更改操作,需要进行二次合法身份验证
  • 密码重设时,应对注册手机号和邮箱进行有效验证,链接只能发送到预先注册的邮件地址或预先绑定的手机号
  • 临时密码和链接应设计一个短暂的有效期(比如5分钟),防止暴力破解
  • 当密码重新设置时,应短信通知用户是否是本人在操作,告知安全风险
  • 密码复杂度设置:建议8个字符以上,包含字母、数字及特殊字符等

会话安全

  • 用户登出后应立即清理会话及其相关登录信息
  • 注销功能应当完全终止相关的会话或连接
  • 会话cookie应设计有效期,超时后立即失效
  • 当设计允许用户在多渠道终端同时登录时,建议应进行常用设备登录限制

访问控制

  • 将具有特权的逻辑从其他应用程序代码中隔离开
  • 限制只有授权的用户才能访问文件资源,url等
  • 服务器端执行的访问控制规则和前端实施的访问控制规则必须匹配
  • 服务器中创建文件时需指定合理的访问权限(读/写/可执行)
  • 当权限重新设置发生变更时,应记录好日志,并短信通知用户是否是本人在操作,告知可能存在的安全风险

日志规范

  • 不要在日志中保存敏感信息,包括系统指纹信息、会话标识符、账号密码、证件、ID等
  • 确保日志记录包含了重要的日志事件数据
  • 记录所有的管理功能操作行为,包含但不限于安全配置设置的变更
  • 禁止将日志直接保存在可被浏览器访问到的WEB目录中

SQL注入

  • 永远不要信任用户的输入,要对用户的所有输入进行校验,包含SQL语句的过滤和转义
  • 永远不要使用动态拼装SQL,可以使用参数化的SQL或者使用存储过程进行数据查询存取
  • 永远不要使用管理员权限进行数据库连接,为每个应用使用单独的非特权权限,且配置有限的数据库连接数
  • 不要把敏感信息明文存放,采用加密或者哈希、混淆等方式对敏感信息进行脱敏存储
  • 应用的异常信息应不带有敏感信息,给出尽可能少的提示

XSS跨站脚本攻击

  • 对输入的数据进行过滤和转义,包含但不限于< >” ‘ % ( ) & + \ ‘ “等危险特殊字符
  • 数据添加到html元素属性或者内容中时,对数据进行HTML转义
  • 数据添加到script脚本中时,对数据进行script转义
  • 数据添加到style中时,对数据进行css转义

CSRF跨站请求伪造

  • 建议在每个关键表单中引入了CSRF Token验证(会话中生成的随机串,提交后校验)
  • 在关键表单提交时要求用户进行二次身份验证(录入密码、插KEY、输入图片验证码、短信验证码)
  • 对请求referer做验证(比如跨域、系统内部应用)

文件上传安全

  • 上传操作应设计身份验证机制,并进行合法身份校验
  • 只允许上传满足业务需要的相关文档类型
  • 通过检查文件头信息,比如JPEG (jpg)文件头信息(十六进制):FFD8FF,验证上传文档是否是所期待的类型
  • 不要把文件保存在与应用程序相同的 Web 环境中,建议将文件保存在专用的文档服务器中,单独给文档服务器配置域名访问更好
  • 限制上传任意可能被 Web 服务器解析的文件 ,比如jsp、php,py等
  • 上传文件以二进制形式下载,建议不提供直接访问(防止木马文件直接执行)
  • 禁止授予上传文件存储目录的可执行权限
  • 禁止客户端自定义文件上传/下载路径(如:使用../../../../进行跳转)
  • 文件上传后重命名(需根据业务实际需求制定命名规则)

接口安全

  • 调用方来源IP控制,比如可通过防火墙、主机host deny、Nginx deny等技术措施进行实施
  • 调用方身份认证,比如key、secret、证书等技术措施进行实施
  • 调用参数认证,需设计参数容错机制,避免出现参数可遍历敏感数据安全问题
  • 采用数字签名保障接口身份来源可信,数据防篡改
  • 调用方权限控制设置,调用频率、有效期进行控制

二,Python安全编码规范

Python开发本身要注意的有,一些危险函数,危险模块的调用处理等,以下是代码中各种容易引发安全问题的调用和处理方式。

1.危险的函数调用

  • eval,任何时候都不要使用eval,这个函数会到时代码上下文出现不可预期的变化,并且在eval的内容不确定时可能会导致黑客直接通过植入代码控制进程甚至是服务器。如非得使用该函数,推荐使用 ast.literal_eval 来进行操作。
  • exec,execfile, 该statement用于在python中执行了一段代码并控制上下文,并可能导致产生与eval相同的问题。
  • pickle.*, marshal.*(包含pickle和cpickle),pickle相关命令用于对包装当前上下文的一个代码处理逻辑,并序列化成一个字符串。在使用pickle.loads一段pickle序列化后的字符串时,如序列化字符串包含 reduce 魔术方法,则会导致pickle执行reduce中的内容,该序列化内容如被修改,则会导致在反序列化时触发恶意代码的注入。
  • os.system, os.exec* , os.popen* , posix.system, ctypes.CDLL等, 在Python中以下类型的方法均可以调用系统命令(ctypes.CDLL包含的_load_library方法存在命令注入),在使用时,需要对传惨内容进行检查。

2.危险的处理方式

  • 对于跨语言进行RPC通信时(如查询SQL时),尽量使用ORM后的接口调用,尽可能避免使用原生的查询代码。
    • 举例: sql = ‘select smcolumn from smtable where name=”%s”’ % columnquery
      • 当columnquery传入可闭合sql语句时,就可以使得SQL条件跳出当前逻辑,从而执行更多其他类型的数据。如 columnquery=’abc” and sleep(1e10000) # 如此即可挂起整个SQL事物,触发异常。
    • 在使用SQL时,请使用预编译绑定方式传入查询参数,一是可以加快sql的查询,二是可以避免大多数危险的突破SQL逻辑的语句产生
    • 同理适用于其他非结构化控制的指令器(bash、mongodb、redis⇒exec)等
    • 也同理适用于操作系统sh命令的执行等
  • 对于正则处理,需要预估传入正则的内容大小以及正则的处理模式,如有大量文本传入正则解析时,会导致CPU飞起来,影响其他协程、事物的处理。
  • 在使用XML解析时候,请关闭外部实体的解析逻辑来防止XXE攻击
  • 对于入参的控制,请使用“检查”而非“过滤”,来避免错误的过滤导致的检查绕过。

3.运行时安全

  • 请尽可能的使用vitualenv,并指定site-package目录,以避免可能产生的攻击。
  • 尽可能的将进程的启动权限压到非root用户,如遇到启动端口等高权方式,请使用setuid将进程降权。

三,Web编程

对应Web编程中安全概念在python web框架中的实现。url跳转,目录遍历,任意文件读取也需要考虑在内。针对不同的框架也需要。

Flask 安全

  • 使用Flask-Security
  • 直接生成 HTML 而不通过使用Jinja2
  • 不要在用户提交的数据上调用Markup
  • 使用 Content-Disposition: attachment 标头去避免上传html文件
  • 防止CSRF,flask本身没有实现该功能

Django 安全

可参考phithon的博客,有较多相关资料。

  • 关闭DEBUG模式
  • 妥善保存SECRET_KEY
  • 设置SECURE_BROWSER_XSS_FILTER输出x-xss-protection头,让浏览器强制开启XSS过滤
  • 设置SECURE_SSL_REDIRECT让HTTP的请求强制跳转到HTTPS
  • 设置SESSION_COOKIE_SECURE使Cookie为Secure,不允许在HTTP中传输
  • 设置CSRF_COOKIE_SECURE使CSRF Token Cookie设置为Secure,不允许在HTTP中传输
  • 设置X_FRAME_OPTIONS返回X-FRAME-OPTIONS: DENY头,以防止被其他页面作为框架加载导致ClickJacking
  • 部署前运行安全性检测 django-admin.py checksecure –settings=production_settings