安全编码核心原则

安全编码不是独立的活动,而是贯穿开发全程的思维方式。最小权限原则:代码只获取完成任务所需的最小权限,不请求多余的资源或数据访问。纵深防御原则:不在任何单一防御环节上放置所有信任,每一层都独立防御。默认安全原则:默认配置应该是安全的,开发人员需要主动选择才能降低安全级别。

输入验证规范

所有外部输入都是不可信的。输入验证有两个层面:语法验证(确保数据格式正确)和语义验证(确保数据含义合理)。例如用户年龄字段,语法上必须是正整数,语义上应在0-150范围内。

白名单优于黑名单:定义允许的输入模式而非禁止的模式。例如允许的字符集[a-zA-Z0-9_@.-],拒绝所有不在白名单中的字符。正则表达式验证时注意ReDoS(正则拒绝服务攻击)风险,避免使用嵌套量词。

输出编码

输出编码是将用户可控数据输出到不同上下文时的安全处理。HTML上下文编码<>&"'字符;JavaScript上下文对字符串字面量编码;URL上下文对参数值进行Percent编码;SQL上下文使用参数化查询。错误的编码上下文转换是XSS漏洞的常见来源。

文件安全操作

文件上传:验证文件MIME类型和魔数(Magic Number),不要仅依赖文件扩展名。将上传文件存储到Web根目录之外的目录。使用随机文件名避免路径遍历和覆盖攻击。使用ClamAV等病毒扫描工具对上传文件进行安全检查。

文件下载:对下载请求进行路径规范化处理,防止../路径遍历攻击。使用白名单限制可下载的文件列表,而非直接接受用户输入的文件路径。

内存安全与并发

使用未初始化的内存可能导致敏感信息泄露。安全敏感操作(如密码处理)后立即清除内存中的敏感数据。Python中敏感字符串使用bytearray而非不可变的str,处理完毕后手动覆写。

并发编程中注意竞态条件(Race Condition)。检查-使用的非原子操作可能导致TOCTOU(Time-of-Check Time-of-Use)漏洞。使用锁或原子操作保证检查和使用之间的原子性。

错误处理与日志

不要向用户暴露详细的错误信息。生产环境禁用调试输出,配置自定义错误页面。日志记录身份验证失败、权限检查失败和输入验证失败等安全事件,但不要记录密码、信用卡号等敏感信息。

依赖管理

定期扫描第三方依赖的安全漏洞。使用npm auditpip safety或Snyk等工具自动化漏洞检测。锁定依赖版本(lock文件)防止意外的恶意更新。订阅安全公告关注依赖库的漏洞披露。