PHP针对Xss跨域攻击以及sql注入等危险字符串过滤安全模块

由于该模块在项目中的要求是 不能提示任何信息,也不作断点操作,只作记录并且过滤危险参数。

主要功能:拦截攻击者注入恶意代码,可以防御诸如跨站脚本攻击(XSS)、SQL注入攻击等恶意攻击行为。

<?php
/**
 * 安全模块
 * Email:zhangyuan@tieyou.com
 * 主要针对xss跨站攻击、sql注入等敏感字符串进行过滤
 * @author hkshadow
 */
class safeMode{

    /**
     * 执行过滤
     * @param 1 linux/2 http/3 Db/ $group
     * @param 保存路径以及文件名/文件名/null $projectName
     */
    public function xss($group = 1,$projectName = NULL){
        //正则条件
        $referer = empty ( $_SERVER ['HTTP_REFERER'] ) ? array () : array ($_SERVER ['HTTP_REFERER'] );
        $getfilter = "'|<[^>]*?>|^\\+\/v(8|9)|\\b(and|or)\\b.+?(>|<|=|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        $postfilter = "^\\+\/v(8|9)|\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|<\\s*img\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";
        $cookiefilter = "\\b(and|or)\\b.{1,6}?(=|>|<|\\bin\\b|\\blike\\b)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)";

        // $ArrPGC=array_merge($_GET,$_POST,$_COOKIE);

        //遍历过滤
        foreach ( $_GET as $key => $value ) {
            $this->stopAttack ( $key, $value, $getfilter ,$group , $projectName);
        }
        //遍历过滤
        foreach ( $_POST as $key => $value ) {
            $this->stopAttack ( $key, $value, $postfilter ,$group , $projectName);
        }
        //遍历过滤
        foreach ( $_COOKIE as $key => $value ) {
            $this->stopAttack ( $key, $value, $cookiefilter ,$group , $projectName);
        }
        //遍历过滤
        foreach ( $referer as $key => $value ) {
            $this->stopAttack ( $key, $value, $getfilter ,$group , $projectName);
        }
    }

    /**
     * 匹配敏感字符串,并处理
     * @param 参数key $strFiltKey
     * @param 参数value $strFiltValue
     * @param 正则条件 $arrFiltReq
     * @param 项目名 $joinName
     * @param 1 linux/2 http/3 Db/ $group
     * @param 项目名/文件名/null $projectName
     */
    public function stopAttack($strFiltKey, $strFiltValue, $arrFiltReq,$group = 1,$projectName = NULL) {

            $strFiltValue = $this->arr_foreach ( $strFiltValue );
            //匹配参数值是否合法
            if (preg_match ( "/" . $arrFiltReq . "/is", $strFiltValue ) == 1) {
                //记录ip
                $ip = "操作IP: ".$_SERVER["REMOTE_ADDR"];
                //记录操作时间
                $time = " 操作时间: ".strftime("%Y-%m-%d %H:%M:%S");
                //记录详细页面带参数
                $thePage = " 操作页面: ".$this->request_uri();
                //记录提交方式
                $type = " 提交方式: ".$_SERVER["REQUEST_METHOD"];
                //记录提交参数
                $key = " 提交参数: ".$strFiltKey;
                //记录参数
                $value = " 提交数据: ".htmlspecialchars($strFiltValue);
                //写入日志
                $strWord = $ip.$time.$thePage.$type.$key.$value;
                //保存为linux类型
                if($group == 1){
                    $this->log_result_common($strWord,$projectName);
                }
                //保存为可web浏览
                if($group == 2){
                    $strWord .= "<br>";
                    $this->slog($strWord,$projectName);
                }
                //保存至数据库
                if($group == 3){
                    $this->sDb($strWord);    
                }
                //过滤参数
                $_REQUEST[$strFiltKey] = '';
                //这里不作退出处理
                //exit;
            }

            //匹配参数是否合法
            if (preg_match ( "/" . $arrFiltReq . "/is", $strFiltKey ) == 1) {
                //记录ip
                $ip = "操作IP: ".$_SERVER["REMOTE_ADDR"];
                //记录操作时间
                $time = " 操作时间: ".strftime("%Y-%m-%d %H:%M:%S");
                //记录详细页面带参数
                $thePage = " 操作页面: ".$this->request_uri();
                //记录提交方式
                $type = " 提交方式: ".$_SERVER["REQUEST_METHOD"];
                //记录提交参数
                $key = " 提交参数: ".$strFiltKey;
                //记录参数
                $value = " 提交数据: ".htmlspecialchars($strFiltValue);
                //写入日志
                $strWord = $ip.$time.$thePage.$type.$key.$value;
                //保存为linux类型
                if($group == 1){
                    $this->log_result_common($strWord,$projectName);
                }
                //保存为可web浏览
                if($group == 2){
                    $strWord .= "<br>";
                    $this->slog($strWord,$projectName);
                }
                //保存至数据库
                if($group == 3){
                    $this->sDb($strWord);    
                }
                //过滤参数
                $_REQUEST[$strFiltKey] = '';
                //这里不作退出处理
                //exit;
            }
        }

    /**
     * 获取当前url带具体参数
     * @return string
     */
    public function request_uri() {
        if (isset ( $_SERVER ['REQUEST_URI'] )) {
            $uri = $_SERVER ['REQUEST_URI'];
        } else {
            if (isset ( $_SERVER ['argv'] )) {
                $uri = $_SERVER ['PHP_SELF'] . '?' . $_SERVER ['argv'] [0];
            } else {
                $uri = $_SERVER ['PHP_SELF'] . '?' . $_SERVER ['QUERY_STRING'];
            }
        }
        return $uri;
    }

    /**
     * 日志记录(linux模式)
     * @param 保存内容 $strWord
     * @param 保存文件名$strPathName
     */
    public function log_result_common($strWord, $strPathName = NULL) {
        if($strPathName == NULL){
            $strPath = "/var/tmp/";
            $strDay = date('Y-m-d');
            $strPathName = $strPath."common_log_".$strDay.'.log';
        }

        $fp = fopen($strPathName,"a");
        flock($fp, LOCK_EX) ;
        fwrite($fp,$strWord." date ".date('Y-m-d H:i:s',time())."\t\n");
        flock($fp, LOCK_UN);
        fclose($fp);
    }   

    /**
     * 写入日志(支持http查看)
     * @param 日志内容 $strWord
     * @param web页面文件名 $fileName
     */
    public function slog($strWord,$fileName = NULL) {
        if($fileName == NULL){
            $toppath = $_SERVER ["DOCUMENT_ROOT"] . "/log.htm";
        }else{
            $toppath = $_SERVER ["DOCUMENT_ROOT"] .'/'. $fileName;
        }
        $Ts = fopen ( $toppath, "a+" );
        fputs ( $Ts, $strWord . "\r\n" );
        fclose ( $Ts );
    }

    /**
     * 写入日志(数据库)
     * @param 日志内容 $strWord
     */
    public function sDb($strWord){
        //....
    }

    /**
     * 递归数组
     * @param array $arr
     * @return unknown|string
     */
    public function arr_foreach($arr) {
        static $str = '';
        if (! is_array ( $arr )) {
            return $arr;
        }
        foreach ( $arr as $key => $val ) {
            if (is_array ( $val )) {
                $this->arr_foreach ( $val );
            } else {
                $str [] = $val;
            }
        }
        return implode ( $str );
    }
}
?>

使用:

<?php
//实例类库
$safeMode = new safeMode();
//这里的参数指的的时 类型,保存的文件名,具体请看类注视。
$safeMode->xss(2,'test.html');
?>

至此基本上,参数带有危险的字符串的时候,将其过滤,并且保存日志到网站根目录的test.html内,可在浏览器预览查看。

3 Responses to “PHP针对Xss跨域攻击以及sql注入等危险字符串过滤安全模块”

Leave a Reply

(will not be published)