应用安全指南
大约 6 分钟
应用安全指南
1. 漏洞描述
OWASP开放互联应用安全项目组织每四年更新常见的应用安全风险的统计,OWASP Top 10包含了常见的应用安全漏洞XSS(跨站脚本):恶意脚本内容注入页面,可以偷Cookie或数据,也可以用于进一步实现CSRF- 考虑转义来自服务器或用户的需要注入内容
- 加
CSP头限制脚本来源 - 对需要直接显示的页面结构或需要执行的代码进行清洗,最好在前后端均进行过滤,避免注入,前端可以使用
DOMPurify进行过滤,后端根据语言选择过滤工具 - 使用沙箱技术运行
- 对
cookie使用SameSite=Lax,避免cookie被第三方网站窃取
CSRF(跨站伪造):诱导用户在登录状态下执行恶意操作(如转账)- 对表单添加
CSRF Token,对于非默认构建的表单拒绝执行 - 有副作用的请求不应该使用
get,避免直接向URL使用简单请求就完成重要操作
- 对表单添加
SQL注入:用户输入内容直接拼进SQL,可以操控数据库- 不信任所有的输入内容,使用预构建语句,进行参数化查询,避免直接拼接输入
- 限制数据库用户权限,先进行验证再执行
- 认证/会话漏洞:弱密码或
Token被偷,导致账户劫持- 使用
https加密连接,并进行JWT/OAuth2认证 - 启用更强加密,比如
TLS 1.3+ - 配置好全局安全请求头
- 错误处理不暴露内部错误信息,使用通用错误码,避免暴露内部细节
- 检查
Origin、Referer和User-Agent,拒绝异常来源
- 使用
- 文件上传漏洞:上传恶意文件,执行代码入侵服务器
- 检测文件头、文件名和大小,存到非页面所在目录,使用随机名称
- 进行安全检查,禁用执行权限,仅在确认安全时提供文件下载
SSRF(服务器伪造请求):服务器直接请求,导致数据泄露- 限速和白名单策略,禁止快速大量请求
- 检查
Origin、Referer和User-Agent,拒绝异常来源
- 架构或依赖缺陷:导致架构级漏洞或引入已知
CVE漏洞- 根据风险评估,更新依赖
- 敏感信息加密存储,必要时进行数据脱敏,避免泄露
- 做好安全日志审计
- 访问控制失败:权限控制漏洞,不安全
API访问,谁都能调API或获取敏感资源,导致用户访问未授权资源,泄露数据- 避免暴露敏感点
- 进行用户验证再获取资源
DDoS:攻击者通过大量请求瘫痪服务- 使用
CDN分担流量 - 部署
WAF过滤恶意请求 - 配置服务器限流和自动扩展机制
- 使用
2. 安全的 HTTPS 连接
3. CSP 内容安全策略
Content-Security-Policy允许网站管理员控制用户代理在给定页面中可加载的资源。除少数选项例外,策略大多涉及指定服务器源和脚本节点。这有助于防止跨站脚本攻击,见MDN中的CSP描述CSP可以作为HTTP响应头使用,应该设置到所有请求回复中,部分选项也可以作为页面的元数据配置
在
CSP响应头中,包含大量选项,每个选项之间应该使用;分隔,选项和值之间使用空格分隔default-src:指定默认的资源加载源行为,作为兜底的默认配置- 常见的子资源类别有
script-src、style-src、img-src、frame-src等 - 取值有,每个值之间使用空格分隔:
none不允许任何资源加载self或其他源地址列表:仅允许从指定源加载资源,self表示当前源- 资源哈希值列表:要求资源标签的
integrity属性与列表中的值能匹配,如果有多个哈希值对应一个资源(标签的integrity中包含多个值,使用不同的哈希算法),需要都写在列表中浏览器会对
integrity属性进行验证,如果验证失败,也拒绝加载资源,哈希值应该为校验算法-值,常见的校验算法是sha256
- 常见的子资源类别有
script-src:指定脚本加载源行为。一般情况下,还需要设置脚本的加载行为,因为这里有更多的关于脚本独有的配置项- 除了
default-src的取值外还支持nonce值列表:nonce是可用于内联脚本和内联样式上的标识符,CSP支持设置允许明确的值来加载可信资源,这个值应该和标签上的信息一致并在后端动态生成unsafe-inline允许内联脚本,一般不建议,内联脚本即直接在页面中的脚本<script>...</script>或是onclick=...这样的内联事件处理属性unsafe-eval:允许使用eval()执行脚本,一般不建议,同时有些函数可以传入脚本字符串执行,比如setTimeout('alert("Hello World")', 1000),也会被同步设置strict-dynamic:必须使用nonce值或哈希值来指定加载的资源,否则会被拒绝,已允许的脚本可以加载其他脚本
- 除了
frame-src:指定允许的frame嵌入的源- 取值:
none:不允许self:允许同源- 域名列表:允许的域名列表,每个域名之间使用空格分隔
- 老版响应头为
X-Frame-Options,DENY表示禁止、SAMEORIGIN表示允许同源、ALLOW-FROM表示允许指定源,一次只能设置单个源
- 取值:
frame-ancestors:指定允许作为frame嵌入哪些父源,包括frame、iframe、object、embed等标签都受此影响- 取值
none:不允许- 域名列表:允许的域名列表,每个域名之间使用空格分隔
- 取值
upgrade-insecure-requests:将不安全的请求升级为安全的请求,浏览器会自动提升页面中的所有资源使用的http请求为https,此属性没有值sandbox:指定请求的资源需要的沙箱行为,类似iframe的沙箱属性,对资源(一般是页面)操作增加限制,包括拒绝弹窗、阻止插件和脚本执行,默认全拒绝- 取值
allow-same-origin:允许沙箱化的资源保留源属性,否则沙箱化的资源的源属性origin为null,无法访问任何存储资源和某些apiallow-popups:允许弹窗allow-downloads:允许下载资源,包括用户点击和通过脚本下载allow-forms:允许提交表单,否则页面虽然正常显示,但无法提交allow-scripts:允许脚本执行,但不能创建弹窗
最终示例
Content-Security-Policy: default-src 'self'; base-uri 'self'; object-src 'none'; script-src 'self' 'nonce-$request_id' 'strict-dynamic'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self' https://api.example.com; frame-ancestors 'none'; upgrade-insecure-requests;- 取值
