PHP如何防止XSS攻擊

OldBoy~發表於2017-05-17

PHP防止XSS跨站指令碼攻擊的方法:是針對非法的HTML程式碼包括單雙引號等,使用htmlspecialchars()函式 。

在使用htmlspecialchars()函式的時候注意第二個引數, 直接用htmlspecialchars($string) 的話,第二個引數預設是ENT_COMPAT,函式預設只是轉化雙引號(“), 不對單引號(‘)做轉義.

所以,htmlspecialchars函式更多的時候要加上第二個引數, 應該這樣用: htmlspecialchars($string,ENT_QUOTES).當然,如果需要不轉化如何的引號,用htmlspecialchars($string,ENT_NOQUOTES).

另外, 儘量少用htmlentities, 在全部英文的時候htmlentities和htmlspecialchars沒有區別,都可以達到目的.但是,中文情況下, htmlentities卻會轉化所有的html程式碼,連同裡面的它無法識別的中文字元也給轉化了。

htmlentities和htmlspecialchars這兩個函式對 '之類的字串支援不好,都不能轉化, 所以用htmlentities和htmlspecialchars轉化的字串只能防止XSS攻擊,不能防止SQL隱碼攻擊.

所有有列印的語句如echo,print等 在列印前都要使用htmlentities() 進行過濾,這樣可以防止Xss,注意中文要寫出htmlentities($name,ENT_NOQUOTES,GB2312) 。

(1).網頁不停地重新整理 '<meta http-equiv="refresh" content="0;">'

(2).嵌入其它網站的連結 <iframe src=http://xxxx width=250 height=250></iframe>  除了通過正常途徑輸入XSS攻擊字元外,還可以繞過JavaScript校驗,通過修改請求達到XSS攻擊的目的.

 

<?php
//php防注入和XSS攻擊通用過濾
$_GET     && SafeFilter($_GET);
$_POST    && SafeFilter($_POST);
$_COOKIE  && SafeFilter($_COOKIE);
  
function SafeFilter (&$arr) 
{
   $ra=Array('/([\x00-\x08,\x0b-\x0c,\x0e-\x19])/','/script/','/javascript/','/vbscript/','/expression/','/applet/'
   ,'/meta/','/xml/','/blink/','/link/','/style/','/embed/','/object/','/frame/','/layer/','/title/','/bgsound/'
   ,'/base/','/onload/','/onunload/','/onchange/','/onsubmit/','/onreset/','/onselect/','/onblur/','/onfocus/',
   '/onabort/','/onkeydown/','/onkeypress/','/onkeyup/','/onclick/','/ondblclick/','/onmousedown/','/onmousemove/'
   ,'/onmouseout/','/onmouseover/','/onmouseup/','/onunload/');
     
   if (is_array($arr))
   {
     foreach ($arr as $key => $value) 
     {
        if (!is_array($value))
        {
          if (!get_magic_quotes_gpc())  //不對magic_quotes_gpc轉義過的字元使用addslashes(),避免雙重轉義。
          {
             $value  = addslashes($value); //給單引號(')、雙引號(")、反斜線(\)與 NUL(NULL 字元)
             加上反斜線轉義
          }
          $value       = preg_replace($ra,'',$value);     //刪除非列印字元,粗暴式過濾xss可疑字串
          $arr[$key]     = htmlentities(strip_tags($value)); //去除 HTML 和 PHP 標記並轉換為 HTML 實體
        }
        else
        {
          SafeFilter($arr[$key]);
        }
     }
   }
}
?>
$str = 'www.90boke.com<meta http-equiv="refresh" content="0;">';
SafeFilter ($str); //如果你把這個註釋掉,提交之後就會無休止重新整理
echo $str;
//------------------------------php防注入和XSS攻擊通用過濾-----Start--------------------------------------------//
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;
}
//php防注入和XSS攻擊通用過濾 
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;
}

//------------------php防注入和XSS攻擊通用過濾-----End--------------------------------------------//

 

PHP中的設定 

PHP5.2以上版本已支援HttpOnly引數的設定,同樣也支援全域性的HttpOnly的設定,在php.ini中

----------------------------------------------------- 
 session.cookie_httponly = 
-----------------------------------------------------

設定其值為1或者TRUE,來開啟全域性的Cookie的HttpOnly屬性,當然也支援在程式碼中來開啟: 

<?php ini_set("session.cookie_httponly", 1);   
// or session_set_cookie_params(0, NULL, NULL, NULL, TRUE);   
?>

Cookie操作函式setcookie函式和setrawcookie函式也專門新增了第7個引數來做為HttpOnly的選項,開啟方法為: 

<?php  
setcookie("abc", "test", NULL, NULL, NULL, NULL, TRUE);   
setrawcookie("abc", "test", NULL, NULL, NULL, NULL, TRUE);  
?>

老版本的PHP就不說了。沒企業用了吧。

相關文章