现在市面浏览器都对XSS做了一些防范措施,如firefox的CSP、Noscrip扩展和IE8内置的XSS Filter等等。但是对于一个站点来说,这往往是不够的,还需要做出更优秀更好的方案防止XSS攻击。如httponly、输入检查、输出检查等等。
httponly是由微软提出来的,目前很多浏览器都支持该功能。带有httponly标识将禁止javascript访问cookie。通常情况下httponly是在服务端返回set-cookie时标记:
Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]
有时候服务器可能会设置多个cookie,这时httponly可以选择性的加在任何有必要的关键cookie值上:
<?php
header("Set-Cookie: cookie1=test1;");
header("Set-Cookie: cookie2=test2;httponly",
false);
?>
<script>
alert(document.cookie);
</script>
这样javascript能读取到cookie1却不能读取cookie2。
附不同语言中cookie添加httponly代码:
java EE:
response.setHeader("Set-Cookie",
"cookiename=value;
Path=/;Domain=domainvalue;Max-Ag
e=seconds;HTTPOnly");
C#
HttpCookie myCookie = new
HttpCookie("myCookie");
myCookie.HttpOnly = true;
Response.AppendCookie(myCookie);
VB.NET
Dim myCookie As HttpCookie = new
HttpCookie("myCookie")
myCookie.HttpOnly = True
Response.AppendCookie(myCookie)
PHP4
header("Set-Cookie: hidden=value; httpOnly");
PHP5
setcookie("abc", "test", NULL, NULL, NULL,
NULL, TRUE); //最后一个参数为httponly属性。
输入检查
一般情况下,常见的web漏洞例如XSS、SQL injection等在构造攻击代码时都含有一些特殊字符,而这些字符可能是正常用户不会用到的,那么输入检查在一定程度上提高了攻击门槛。
输入检查的逻辑必须是在服务端中实现,在客户端使用javascript进行检查是很容易就被攻击者绕过。目前很多web开发普遍做法是同时在服务端代码与客户端javascript中实现输入检查。其实输入检查还是存在很多问题,比如攻击者可以将攻击代码放在远端,在用户浏览器插入正常URL,URL一般不会包含特殊字符,同样也可实施XSS攻击。
输入检查
既然输入检查存在问题,那么输出检查呢???
一般来说,输了富文本的输出外,在变量输出到HTML页面时可以使用编码方式或转义方式来防御XSS攻击。常见的HTMLEncode中转换如下字符:
& --> &
< --> <
> --> >
" --> "
' --> ' ' 不推荐
/ --> / 包含反斜线是因为它可能会闭合一些HTML entity
PHP中htmlentities()和htmlspe-cialchars()两个函数可以满足安全要求
JavaScript的编码方式可以使用JavascriptEncode
下面对比一下:
var x = escapeJavascript($evil);
var y = '"'+escapeJavascript($evil)+'"';
第二行进行了转义,那么两行代码输出结果为:
var x = 1;alert(2);
var y = "1;alert(2)";
第一行执行额外代码,第二行则是安全的,那么对于后者来说,攻击者需要逃逸出引号的范围,显然攻击门槛又提高了。出去转义外,还可以使用十六进制“\xHH”的方式进行编码:
var x = 1;alert(2);使用十六进制编码后:var x = 1\x3balert\x282\x29;这样就安全很多。
如何正确的防御XSS攻击??
为了更好的设计防御XSS攻击方案,需要认清XSS产生的本质原因。XSS的本质还是一种“HTML注入”,即是用户的数据被当成HTML代码一部分来执行,从而混淆了原本的语义。例如:
<div>$var</div>
<a href=# >$var</a>
在这种场景下,$var表示用户数据,但是输出时未做任何处理,那么XSS攻击者构造一个<script>标签即可让脚步被执行:
<div><script>alert(/xss/)</script></div>或者<a href=# ><img src=# onerrot=alert(1) /></a>。此时,应该采用HtmlEncode,确保输出的变量在引号中:
<script>
var x = "$var";
</script>
攻击者的攻击代码需要先闭合引号才能实施XSS攻击:
<script>
var x = "";alert(/xss/);//"
</script>
同理<a href=# οnclick="funcA('$var')" >test</a>
httponly是由微软提出来的,目前很多浏览器都支持该功能。带有httponly标识将禁止javascript访问cookie。通常情况下httponly是在服务端返回set-cookie时标记:
Set-Cookie: <name>=<value>[; <Max-Age>=<age>]
[; expires=<date>][; domain=<domain_name>]
[; path=<some_path>][; secure][; HttpOnly]
有时候服务器可能会设置多个cookie,这时httponly可以选择性的加在任何有必要的关键cookie值上:
<?php
header("Set-Cookie: cookie1=test1;");
header("Set-Cookie: cookie2=test2;httponly",
false);
?>
<script>
alert(document.cookie);
</script>
这样javascript能读取到cookie1却不能读取cookie2。
附不同语言中cookie添加httponly代码:
java EE:
response.setHeader("Set-Cookie",
"cookiename=value;
Path=/;Domain=domainvalue;Max-Ag
e=seconds;HTTPOnly");
C#
HttpCookie myCookie = new
HttpCookie("myCookie");
myCookie.HttpOnly = true;
Response.AppendCookie(myCookie);
VB.NET
Dim myCookie As HttpCookie = new
HttpCookie("myCookie")
myCookie.HttpOnly = True
Response.AppendCookie(myCookie)
PHP4
header("Set-Cookie: hidden=value; httpOnly");
PHP5
setcookie("abc", "test", NULL, NULL, NULL,
NULL, TRUE); //最后一个参数为httponly属性。
输入检查
一般情况下,常见的web漏洞例如XSS、SQL injection等在构造攻击代码时都含有一些特殊字符,而这些字符可能是正常用户不会用到的,那么输入检查在一定程度上提高了攻击门槛。
输入检查的逻辑必须是在服务端中实现,在客户端使用javascript进行检查是很容易就被攻击者绕过。目前很多web开发普遍做法是同时在服务端代码与客户端javascript中实现输入检查。其实输入检查还是存在很多问题,比如攻击者可以将攻击代码放在远端,在用户浏览器插入正常URL,URL一般不会包含特殊字符,同样也可实施XSS攻击。
输入检查
既然输入检查存在问题,那么输出检查呢???
一般来说,输了富文本的输出外,在变量输出到HTML页面时可以使用编码方式或转义方式来防御XSS攻击。常见的HTMLEncode中转换如下字符:
& --> &
< --> <
> --> >
" --> "
' --> ' ' 不推荐
/ --> / 包含反斜线是因为它可能会闭合一些HTML entity
PHP中htmlentities()和htmlspe-cialchars()两个函数可以满足安全要求
JavaScript的编码方式可以使用JavascriptEncode
下面对比一下:
var x = escapeJavascript($evil);
var y = '"'+escapeJavascript($evil)+'"';
第二行进行了转义,那么两行代码输出结果为:
var x = 1;alert(2);
var y = "1;alert(2)";
第一行执行额外代码,第二行则是安全的,那么对于后者来说,攻击者需要逃逸出引号的范围,显然攻击门槛又提高了。出去转义外,还可以使用十六进制“\xHH”的方式进行编码:
var x = 1;alert(2);使用十六进制编码后:var x = 1\x3balert\x282\x29;这样就安全很多。
如何正确的防御XSS攻击??
为了更好的设计防御XSS攻击方案,需要认清XSS产生的本质原因。XSS的本质还是一种“HTML注入”,即是用户的数据被当成HTML代码一部分来执行,从而混淆了原本的语义。例如:
<div>$var</div>
<a href=# >$var</a>
在这种场景下,$var表示用户数据,但是输出时未做任何处理,那么XSS攻击者构造一个<script>标签即可让脚步被执行:
<div><script>alert(/xss/)</script></div>或者<a href=# ><img src=# onerrot=alert(1) /></a>。此时,应该采用HtmlEncode,确保输出的变量在引号中:
<script>
var x = "$var";
</script>
攻击者的攻击代码需要先闭合引号才能实施XSS攻击:
<script>
var x = "";alert(/xss/);//"
</script>
同理<a href=# οnclick="funcA('$var')" >test</a>