网络安全-XSS跨站脚本攻击

1.  XSS攻击原理
XSS原称为CSS(Cross-Site Scripting),因为和层叠样式表(Cascading Style Sheets)重名,所以改称为XSS(X一般有未知的含义,还有扩展的含义)。XSS攻击涉及到三方:攻击者,用户,web server。用户是通过浏览器来访问web server上的网页,XSS攻击就是攻击者通过各种办法,在用户访问的网页中插入自己的脚本,让其在用户访问网页时在其浏览器中进行执行。攻击者通过插入的脚本的执行,来获得用户的信息,比如cookie,发送到攻击者自己的网站(跨站了)。所以称为 跨站脚本攻击 。XSS可以分为反射型XSS和持久性XSS,还有DOM Based XSS。(一句话,XSS就是在用户的浏览器中执行攻击者自己定制的脚本。)
1.1  反射型XSS
反射性XSS,也就是非持久性XSS。用户点击攻击链接,服务器解析后响应,在返回的响应内容中出现攻击者的XSS代码,被浏览器执行。一来一去, XSS攻击脚本被web server反射回来给浏览器执行 ,所以称为反射型XSS。
特点:
1> XSS攻击代码非持久性,也就是没有保存在web server中,而是出现在URL地址中;
2> 非持久性,那么攻击方式就不同了。一般是攻击者通过邮件,聊天软件等等方式发送攻击URL,然后用户点击来达到攻击的;
1.2   持久型XSS
区别就是XSS恶意代码 存储在web server中 ,这样,每一个访问特定网页的用户,都会被攻击。
特点:
1> XSS攻击代码存储于web server上;
2> 攻击者,一般是通过网站的留言、评论、博客、日志等等功能(所有能够向web server输入内容的地方),将攻击代码存储到web server上的;
有时持久性XSS和反射型XSS是同时使用的,比如先通过对一个攻击url进行编码(来绕过xss filter),然后提交该web server(存储在web server中), 然后用户在浏览页面时,如果点击该url,就会触发一个XSS攻击。当然用户点击该url时,也可能会触发一个CSRF(Cross site request forgery)攻击。
1.3  DOM based XSS
基于DOM的XSS, 也就是web server不参与,仅仅涉及到浏览器的XSS 。比如根据用户的输入来动态构造一个DOM节点,如果没有对用户的输入进行过滤,那么也就导致XSS攻击的产生。过滤可以考虑采用 esapi4js
参见:http://www.freebuf.com/articles/web/29177.html , http://www.zhihu.com/question/26628342/answer/33504799

2.   XSS 存在的原因
XSS 存在的根本原因是,对URL中的参数,对用户输入提交给web server的内容,没有进行充分的过滤。如果我们能够在web程序中,对用户提交的URL中的参数,和提交的所有内容,进行充分的过滤,将所有的不合法的参数和输入内容过滤掉,那么就不会导致“在用户的浏览器中执行攻击者自己定制的脚本”。
但是, 其实充分而完全的过滤,实际上是无法实现的 。因为攻击者有各种各样的神奇的,你完全想象不到的方式来绕过服务器端的过滤,最典型的就是对URL和参数进行各种的编码,比如escape, encodeURI, encodeURIComponent, 16进制,10进制,8进制,来绕过XSS过滤。那么我们如何来防御XSS呢?

3.   XSS 攻击的防御
XSS防御的总体思路是: 对输入(和URL参数)进行过滤,对输出进行编码
也就是对提交的所有内容进行过滤,对url中的参数进行过滤,过滤掉会导致脚本执行的相关内容;然后对动态输出到页面的内容进行html编码,使脚本无法在浏览器中执行。 虽然对输入过滤可以被绕过,但是也还是会拦截很大一部分的XSS攻击


4、XSS过滤函数总结:
strip_tags( string $str [, string $allowable_tags ] ) 该函数尝试返回给定的字符串 str 去除空字符、HTML 和 PHP 标记后的结果。
(allowable_tags
使用可选的第二个参数指定不被去除的字符列表。
例如: strip_tags ( $text '<p><a>' ); // 允许 <p> 和 <a>
htmlspecialchars 把预定义的字符 "<" (小于)和 ">" (大于)转换为 HTML 实体
预定义的字符是:
  • & (和号)成为 &
  • " (双引号)成为 "
  • ' (单引号)成为 '
  • < (小于)成为 <
  • > (大于)成为 >
htmlentities 把字符转换为 HTML 实体


5、特殊设置预防
(1) HttpOnly防止劫取Cookie
HttpOnly最早由微软提出,至今已经成为一个标准。浏览器将禁止页面的Javascript访问带有HttpOnly属性的Cookie。目前主流浏览器都支持,HttpOnly解决是XSS后的Cookie支持攻击。


6、 过滤函数总结
(1)通用的XSS攻击过滤函数
<?php function RemoveXSS ($val) { // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed // this prevents some character re-spacing such as <java\0script> // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs $val = preg_replace( '/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/' , '' , $val ); // straight replacements, the user should never need these since they're normal characters // this prevents like <IMG SRC=@avascript:alert('XSS')> $search = 'abcdefghijklmnopqrstuvwxyz' ; $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' ; $search .= '1234567890!@#$%^&*()' ; $search .= '~`";:?+/={}[]-_|\'\\' ; for ( $i = 0 ; $i < strlen( $search ); $i ++) { // ;? matches the ;, which is optional // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars // @ @ search for the hex values $val = preg_replace( '/(&#[xX]0{0,8}' .dechex(ord( $search [ $i ])). ';?)/i' , $search [ $i ], $val ); // with a ; // @ @ 0{0,7} matches '0' zero to seven times $val = preg_replace( '/(&#0{0,8}' .ord( $search [ $i ]). ';?)/' , $search [ $i ], $val ); // with a ; } // now the only remaining whitespace attacks are \t, \n, and \r $ra1 = Array ( 'javascript' , 'vbscript' , 'expression' , 'applet' , 'meta' , 'xml' , 'blink' , 'link' , 'style' , 'script' , 'embed' , 'object' , 'iframe' , 'frame' , 'frameset' , 'ilayer' , 'layer' , 'bgsound' , 'title' , 'base' ); $ra2 = Array ( 'onabort' , 'onactivate' , 'onafterprint' , 'onafterupdate' , 'onbeforeactivate' , 'onbeforecopy' , 'onbeforecut' , 'onbeforedeactivate' , 'onbeforeeditfocus' , 'onbeforepaste' , 'onbeforeprint' , 'onbeforeunload' , 'onbeforeupdate' , 'onblur' , 'onbounce' , 'oncellchange' , 'onchange' , 'onclick' , 'oncontextmenu' , 'oncontrolselect' , 'oncopy' , 'oncut' , 'ondataavailable' , 'ondatasetchanged' , 'ondatasetcomplete' , 'ondblclick' , 'ondeactivate' , 'ondrag' , 'ondragend' , 'ondragenter' , 'ondragleave' , 'ondragover' , 'ondragstart' , 'ondrop' , 'onerror' , 'onerrorupdate' , 'onfilterchange' , 'onfinish' , 'onfocus' , 'onfocusin' , 'onfocusout' , 'onhelp' , 'onkeydown' , 'onkeypress' , 'onkeyup' , 'onlayoutcomplete' , 'onload' , 'onlosecapture' , 'onmousedown' , 'onmouseenter' , 'onmouseleave' , 'onmousemove' , 'onmouseout' , 'onmouseover' , 'onmouseup' , 'onmousewheel' , 'onmove' , 'onmoveend' , 'onmovestart' , 'onpaste' , 'onpropertychange' , 'onreadystatechange' , 'onreset' , 'onresize' , 'onresizeend' , 'onresizestart' , 'onrowenter' , 'onrowexit' , 'onrowsdelete' , 'onrowsinserted' , 'onscroll' , 'onselect' , 'onselectionchange' , 'onselectstart' , 'onstart' , 'onstop' , 'onsubmit' , 'onunload' ); $ra = array_merge( $ra1 , $ra2 ); $found = true ; // keep replacing as long as the previous round replaced something while ( $found == true ) { $val_before = $val ; for ( $i = 0 ; $i < sizeof( $ra ); $i ++) { $pattern = '/' ; for ( $j = 0 ; $j < strlen( $ra [ $i ]); $j ++) { if ( $j > 0 ) { $pattern .= '(' ; $pattern .= '(&#[xX]0{0,8}([9ab]);)' ; $pattern .= '|' ; $pattern .= '|(&#0{0,8}([9|10|13]);)' ; $pattern .= ')*' ; } $pattern .= $ra [ $i ][ $j ]; } $pattern .= '/i' ; $replacement = substr( $ra [ $i ], 0 , 2 ). '<x>' .substr( $ra [ $i ], 2 ); // add in <> to nerf the tag $val = preg_replace( $pattern , $replacement , $val ); // filter out the hex tags if ( $val_before == $val ) { // no replacements were made, so exit the loop $found = false ; } } } return $val ; }

(2) Discuz系统中 防止XSS漏洞攻击,过滤HTML危险标签属性的PHP函数
function  string_remove_xss( $html ) {
     preg_match_all( "/\<([^\<]+)\>/is" $html $ms );
 
     $searchs [] =  '<' ;
     $replaces [] =  '&lt;' ;
     $searchs [] =  '>' ;
     $replaces [] =  '&gt;' ;
 
     if  ( $ms [1]) {
         $allowtags  =  'img|a|font|div|table|tbody|caption|tr|td|th|br|p|b|strong|i|u|em|span|ol|ul|li|blockquote' ;
         $ms [1] =  array_unique ( $ms [1]);
         foreach  ( $ms [1]  as   $value ) {
             $searchs [] =  "&lt;" . $value . "&gt;" ;
 
             $value  =  str_replace ( '&amp;' '_uch_tmp_str_' $value );
             $value  = string_htmlspecialchars( $value );
             $value  =  str_replace ( '_uch_tmp_str_' '&amp;' $value );
 
             $value  =  str_replace ( array ( '\\' '/*' ),  array ( '.' '/.' ),  $value );
             $skipkeys  =  array ( 'onabort' , 'onactivate' , 'onafterprint' , 'onafterupdate' , 'onbeforeactivate' , 'onbeforecopy' , 'onbeforecut' , 'onbeforedeactivate' ,
                     'onbeforeeditfocus' , 'onbeforepaste' , 'onbeforeprint' , 'onbeforeunload' , 'onbeforeupdate' , 'onblur' , 'onbounce' , 'oncellchange' , 'onchange' ,
                     'onclick' , 'oncontextmenu' , 'oncontrolselect' , 'oncopy' , 'oncut' , 'ondataavailable' , 'ondatasetchanged' , 'ondatasetcomplete' , 'ondblclick' ,
                     'ondeactivate' , 'ondrag' , 'ondragend' , 'ondragenter' , 'ondragleave' , 'ondragover' , 'ondragstart' , 'ondrop' , 'onerror' , 'onerrorupdate' ,
                     'onfilterchange' , 'onfinish' , 'onfocus' , 'onfocusin' , 'onfocusout' , 'onhelp' , 'onkeydown' , 'onkeypress' , 'onkeyup' , 'onlayoutcomplete' ,
                     'onload' , 'onlosecapture' , 'onmousedown' , 'onmouseenter' , 'onmouseleave' , 'onmousemove' , 'onmouseout' , 'onmouseover' , 'onmouseup' , 'onmousewheel' ,
                     'onmove' , 'onmoveend' , 'onmovestart' , 'onpaste' , 'onpropertychange' , 'onreadystatechange' , 'onreset' , 'onresize' , 'onresizeend' , 'onresizestart' ,
                     'onrowenter' , 'onrowexit' , 'onrowsdelete' , 'onrowsinserted' , 'onscroll' , 'onselect' , 'onselectionchange' , 'onselectstart' , 'onstart' , 'onstop' ,
                     'onsubmit' , 'onunload' , 'javascript' , 'script' , 'eval' , 'behaviour' , 'expression' , 'style' , 'class' );
             $skipstr  = implode( '|' $skipkeys );
             $value  = preg_replace( array ( "/($skipstr)/i" ),  '.' $value );
             if  (!preg_match( "/^[\/|\s]?($allowtags)(\s+|$)/is" $value )) {
                 $value  =  '' ;
             }
             $replaces [] =  empty ( $value ) ?  ''  :  "<"  .  str_replace ( '&quot;' '"' $value ) . ">";
         }
     }
     $html  =  str_replace ( $searchs $replaces $html );
 
     return   $html ;
}
 
function  string_htmlspecialchars( $string $flags  = null) {
     if  ( is_array ( $string )) {
         foreach  ( $string   as   $key  =>  $val ) {
             $string [ $key ] = string_htmlspecialchars( $val $flags );
         }
     else  {
         if  ( $flags  === null) {
             $string  =  str_replace ( array ( '&' '"' '<' '>' ),  array ( '&amp;' '&quot;' '&lt;' '&gt;' ),  $string );
             if  ( strpos ( $string '&amp;#' ) !== false) {
                 $string  = preg_replace( '/&amp;((#(\d{3,5}|x[a-fA-F0-9]{4}));)/' '&\\1' $string );
             }
         else  {
             if  (PHP_VERSION <  '5.4.0' ) {
                 $string  = htmlspecialchars( $string $flags );
             else  {
                 if  (!defined( 'CHARSET' ) || ( strtolower (CHARSET) ==  'utf-8' )) {
                     $charset  =  'UTF-8' ;
                 else  {
                     $charset  =  'ISO-8859-1' ;
                 }
                 $string  = htmlspecialchars( $string $flags $charset );
             }
         }
     }
 
     return   $string ;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值