跨站脚本攻击(XSS)的修复指引
1、漏洞简介
跨站脚本漏洞,是指业务代码接收外部参数后,没有对参数进行严格校验,导致攻击者可以插入恶意JavaScript脚本,窃取用户信息。根据触发方式又可分为下面三种子类型:
a)反射型XSS漏洞:简单的把用户输入的数据“反射”给浏览器
b)存储型XSS漏洞:储存型XSS会把用户输入的数据“储存”在服务器端、具有很强的稳定性
c)DOM型XSS漏洞:客户端的脚本程序可以通过DOM动态地检查和修改页面内容,它不依赖于提交数据到服务器端,而从客户端获得DOM中的数据在本地执行,如果DOM中的数据没有经过严格确认,就会产生DOM-based XSS漏洞。
2、漏洞危害
2.1、窃取用户信息
a)可以获取用户的登录凭证,如用户名和密码。攻击者通过在目标网站注入恶意脚本,当用户登录时,脚本会将输入的账号密码等信息发送到攻击者控制的服务器。
b)窃取用户的敏感数据,例如用户的个人信息(姓名、身份证号、银行卡号等)。如果网站存储了这些信息且存在XSS漏洞,恶意脚本就能够读取并传输这些数据。
2.2、劫持用户会话
a)攻击者利用XSS漏洞注入脚本后,可以劫持用户的会话。例如,在用户登录电商网站后,攻击者通过劫持会话,能够以用户的身份进行购物、修改收货地址等操作,造成用户的财产损失。
2.3、恶意软件传播
a)强制用户在不知情的情况下下载和安装恶意软件。比如,当用户访问被注入恶意脚本的网页时,脚本可能会利用浏览器的漏洞自动下载并安装木马程序,从而进一步控制用户的计算机。
3、漏洞修复,具体修复措施:
3.1、【必须】对输入和输出的内容进行验证,转义或者重新编码<、>、'、"等字符
a)使用各语言、开发框架提供的转义函数,例如:PHP 的htmlspecialchars
b)编码方式可参考JavaScript安全规范,原生DOM-API的安全操作-DOMXSS防御
c)使用公司安全开发套件库sec_api
d)参考下方的修复代码示例
3.2、【必须】设置 Cookie 的 HttpOnly 和 Secure 属性
3.3、【建议】部署 CSP 内容安全防护策略
a)CSP(Content Security Policy)是一系列指令告诉客户端(浏览器)在页面内只允许加载和执行指令集中限定的内容,类似白名单机制,不满足限定条件的资源和内容将被客户端阻断或不被执行。
b)代码层面的过滤和转义都是从黑名单的角度进行 XSS 攻击防御,CSP 可以从白名单的角度更大限度控制页面行为,进一步提升安全水位。
3.4、针对反射-XSS(Content-Sniffing型)
a)确认响应头Content-Type与内容保持一致。 比如,API响应数据类型是json,则响应头使用application/json;若为 XML,则设置为 text/xml。
b)添加响应头X-Content-Type-Options: nosniff
4、示例代码(建议用法)
4.1、PHP
1 <?php 2 3 $tst = $_GET["tst"]; 4 5 //调用htmlspecialchars函数对外部变量进行过滤 6 echo '<h1> Hello, ' . htmlspecialchars($tst, ENT_QUOTES, "UTF-8") . '!</h1>'; 7 ?>
4.2、Golang
package main import ( "html" "net/http" ) func xss(w http.ResponseWriter, req *http.Request){ a := req.FormValue("a") //实现实体编码 b := html.EscapeString(a) //或者 template.JSEscape(w io.Writer, b []byte) w.WriteHeader(200) w.Header().Set("Content-type","text/javascript") w.Write([]byte(b)) } func main(){ http.HandleFunc("/xss",xss) http.ListenAndServe("127.0.0.1:8888",nil) }
4.3、NodeJS
//安装xss-filters //npm install xss-filters --save var express = require('express'); var app = express(); var xssFilters = require('xss-filters'); app.get('/', function(req, res){ var tst = req.query.tst; //调用xssFilters.inHTMLData对外部变量进行过滤 res.send('<h1> Hello, ' + xssFilters.inHTMLData(tst) + '!</h1>'); }); app.listen(3000);

浙公网安备 33010602011771号