XSS是跨站脚本攻击,主要特点是开发者之外的人向页面内容注入了脚本执行。
XSS攻击有两个要素,一是来自用户或者三方的内容,二是被当做html或者javascript代码执行。
在面对XSS攻击时,需要牢记的一句话是:一切输入和输出都是敌对的!
XSS 攻击的输入点
开发者之外的人可以通过以下输入点向页面中注入攻击脚本:
window.location/document.location/document.referrer
- 来自url的内容,因为链接可能来自外部页面,所以页面url应当视为外部用户内容。
- 后端接口返回数据
- 来自服务端的数据,这些数据可能由其它系统提供,其中可能包含用户的直接输入,所以应该把通过后端接口请求得到的数据视为外部用户产生内容。
document.cookie
cookie
有较多渠道被写入,为安全起见,应当视为用户产生内容。
input.value/textarea.value
- 用户产生内容。
XSS 攻击的输出点
XSS 攻击输出点是开发者在代码中写的语句,这些语句可能会将用户输入的内容作为代码执行,进而发生XSS 攻击。XSS 攻击主要有以下输出点:
document.write/document.writeln:直接向文档流写入html内容,不提倡使用.
- 如果希望用这种方式输出文本,在写入之前,应当使用document.createTextNode+appendChild将之转换成html文本语法。
- 如果确有特殊设计,希望用这种方式输出html,在写入之前,应当过滤html语法字符。
innerHTML/$el.html():直接向文档节点内插入html内容,除使用模板外,不提倡使用。
- 如果希望用这种方式输出文本,应当使用innerText或者document.createTextNode+appendChild代替。
- 如果确有特殊设计,希望用这种方式输出html,在写入之前,应当过滤html语法字符。
new Function:通过参数字符串创建新函数,除特殊场景外,不提倡使用。如果来自不安全的输入的字符需要拼接成字符串,建议使用JSON.stringify处理。
eval:把字符串当做函数执行,除特殊场景外,不提倡使用。如果来自不安全的输入的字符需要拼接成字符串,建议使用JSON.stringify处理。
setTimeout/setInterval:时间相关函数,如果第一个参数是字符串,那么效果类似eval,任何场景下,不提倡这样使用,第一个参数应该永远是函数类型。
image.src/link.href/a.href:设置url,因为可能是javascript协议,建议使用lib.httpurl解析url的结构和参数,确定域名属于安全域名。
window.location:跳转url,因为uri可能是javascript协议,建议使用lib.httpurl解析url的结构和参数,确定域名属于安全域名。
XSS 攻击实例
HTML 攻击
输出点
<img src="[代码]">
现在弹个窗:
<img src="x" onerror="alert(1)">
原code:
<img src="x" onerror="alert(1)">