企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
1.服务端进行CSRF防御 服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。 (1).Cookie Hashing(所有表单都包含同一个伪随机值): 这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了 (2).验证码   这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄…这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。 (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)   在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。 2.预防xss攻击 php防止XSS跨站脚本攻击的方法:是针对非法的HTML代码包括单双引号等,使用htmlspecialchars()函数 。 在使用htmlspecialchars()函数的时候注意第二个参数, 直接用htmlspecialchars($string) 的话,第二个参数默认是ENT_COMPAT,函数默认只是转化双引号(“), 不对单引号(‘)做转义 3.预防sql注入 1、php.ini 中把 safe_mode 打开 2、 safe_mode_gid = off 3、 关闭危险函数 ``` disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown ``` 4、 关闭PHP版本信息在http头中的泄漏 expose_php = Off 5、 打开magic_quotes_gpc来防止SQL注入 magic_quotes_gpc = On 这个默认是关闭的,如果它打开后将自动把用户提交对sql的查询进行转换 比如把 ’ 转为 '等,这对防止sql注射有重大作用 6、错误信息控制 error_reporting = E_WARNING & E_ERROR 只显示警告以上 7、 错误日志 建议在关闭display_errors后能够把错误信息记录下来,便于查找服务器运行的原因 ``` log_errors = On error_log = D:/usr/local/apache2/logs/php_error.log if (!get_magic_quotes_gpc()) { $lastname = addslashes($_POST[‘lastname’]); } else { $lastname = $_POST[‘lastname’]; } get_magic_quotes_gpc ``` 过滤后不用 addslashes 以免重复过滤 ``` <?php /** * php防止sql注入 * by www.httple.net */ function post_check( $post ) { if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开 { $post = addslashes ( $post ); // 进行magic_quotes_gpc没有打开的情况对提交数据的过滤 } $post = str_replace ( "_" , "\_" , $post ); // 把 '_'过滤掉 $post = str_replace ( "%" , "\%" , $post ); // 把' % '过滤掉 $post = nl2br ( $post ); // 回车转换 $post = htmlspecialchars( $post ); // html标记转换 return $post ; } ?> ``` 关于SQL注入,不得不说的是现在大多虚拟主机都会把magic_quotes_gpc选项打开,在这种情况下所有的客户端GET和POST的数据都会自动进行addslashes处理,所以此时对字符串值的SQL注入是不可行的,但要防止对数字值的SQL注入,如用intval()等函数进行处理 例式2 ———————————————— ``` 防止sql注入的函数,过滤掉那些非法的字符,提高sql安全性,同时也可以过滤XSS的攻击。 /** * php防止sql注入 * by www.httple.net */ function filter($str) { if (empty($str)) return false; $str = htmlspecialchars($str); $str = str_replace( '/', "", $str); $str = str_replace( '"', "", $str); $str = str_replace( '(', "", $str); $str = str_replace( ')', "", $str); $str = str_replace( 'CR', "", $str); $str = str_replace( 'ASCII', "", $str); $str = str_replace( 'ASCII 0x0d', "", $str); $str = str_replace( 'LF', "", $str); $str = str_replace( 'ASCII 0x0a', "", $str); $str = str_replace( ',', "", $str); $str = str_replace( '%', "", $str); $str = str_replace( ';', "", $str); $str = str_replace( 'eval', "", $str); $str = str_replace( 'open', "", $str); $str = str_replace( 'sysopen', "", $str); $str = str_replace( 'system', "", $str); $str = str_replace( '$', "", $str); $str = str_replace( "'", "", $str); $str = str_replace( "'", "", $str); $str = str_replace( 'ASCII 0x08', "", $str); $str = str_replace( '"', "", $str); $str = str_replace( '"', "", $str); $str = str_replace("", "", $str); $str = str_replace("&gt", "", $str); $str = str_replace("&lt", "", $str); $str = str_replace("<SCRIPT>", "", $str); $str = str_replace("</SCRIPT>", "", $str); $str = str_replace("<script>", "", $str); $str = str_replace("</script>", "", $str); $str = str_replace("select","",$str); $str = str_replace("join","",$str); $str = str_replace("union","",$str); $str = str_replace("where","",$str); $str = str_replace("insert","",$str); $str = str_replace("delete","",$str); $str = str_replace("update","",$str); $str = str_replace("like","",$str); $str = str_replace("drop","",$str); $str = str_replace("DROP","",$str); $str = str_replace("create","",$str); $str = str_replace("modify","",$str); $str = str_replace("rename","",$str); $str = str_replace("alter","",$str); $str = str_replace("cas","",$str); $str = str_replace("&","",$str); $str = str_replace(">","",$str); $str = str_replace("<","",$str); $str = str_replace(" ",chr(32),$str); $str = str_replace(" ",chr(9),$str); $str = str_replace(" ",chr(9),$str); $str = str_replace("&",chr(34),$str); $str = str_replace("'",chr(39),$str); $str = str_replace("<br />",chr(13),$str); $str = str_replace("''","'",$str); $str = str_replace("css","'",$str); $str = str_replace("CSS","'",$str); $str = str_replace("<!--","",$str); $str = str_replace("convert","",$str); $str = str_replace("md5","",$str); $str = str_replace("passwd","",$str); $str = str_replace("password","",$str); $str = str_replace("../","",$str); $str = str_replace("./","",$str); $str = str_replace("Array","",$str); $str = str_replace("or 1='1'","",$str); $str = str_replace(";set|set&set;","",$str); $str = str_replace("`set|set&set`","",$str); $str = str_replace("--","",$str); $str = str_replace("OR","",$str); $str = str_replace('"',"",$str); $str = str_replace("*","",$str); $str = str_replace("-","",$str); $str = str_replace("+","",$str); $str = str_replace("/","",$str); $str = str_replace("=","",$str); $str = str_replace("'/","",$str); $str = str_replace("-- ","",$str); $str = str_replace(" -- ","",$str); $str = str_replace(" --","",$str); $str = str_replace("(","",$str); $str = str_replace(")","",$str); $str = str_replace("{","",$str); $str = str_replace("}","",$str); $str = str_replace("-1","",$str); $str = str_replace("1","",$str); $str = str_replace(".","",$str); $str = str_replace("response","",$str); $str = str_replace("write","",$str); $str = str_replace("|","",$str); $str = str_replace("`","",$str); $str = str_replace(";","",$str); $str = str_replace("etc","",$str); $str = str_replace("root","",$str); $str = str_replace("//","",$str); $str = str_replace("!=","",$str); $str = str_replace("$","",$str); $str = str_replace("&","",$str); $str = str_replace("&&","",$str); $str = str_replace("==","",$str); $str = str_replace("#","",$str); $str = str_replace("@","",$str); $str = str_replace("mailto:","",$str); $str = str_replace("CHAR","",$str); $str = str_replace("char","",$str); return $str; } 更加简便的防止sql注入的方法(推荐使用这个): if (!get_magic_quotes_gpc()) // 判断magic_quotes_gpc是否为打开 { $post = addslashes($name); // magic_quotes_gpc没有打开的时候把数据过滤 } $name = str_replace("_", "\_", $name); // 把 '_'过滤掉 $name = str_replace("%", "\%", $name); // 把' % '过滤掉 $name = nl2br($name); // 回车转换 $name= htmlspecialchars($name); // html标记转换 return $name; ``` ## 例式3 ``` <?php /** * php防止sql注入 * by www.httple.net */ //要过滤的非法字符 $ArrFiltrate=array("‘",";","union"); //出错后要跳转的url,不填则默认前一页 $StrGoUrl=""; //是否存在数组中的值 function FunStringExist($StrFiltrate,$ArrFiltrate) { foreach ($ArrFiltrate as $key=>$value) { if (eregi($value,$StrFiltrate)) { return true; } } return false; } //合并$_POST 和 $_GET if(function_exists(array_merge)) { $ArrPostAndGet=array_merge($HTTP_POST_VARS,$HTTP_GET_VARS); } else { foreach($HTTP_POST_VARS as $key=>$value) { $ArrPostAndGet[]=$value; } foreach($HTTP_GET_VARS as $key=>$value) { $ArrPostAndGet[]=$value; } } //验证开始 foreach($ArrPostAndGet as $key=>$value) { if (FunStringExist($value,$ArrFiltrate)) { echo "<script language="javascript">alert("非法字符");</script>"; if (emptyempty($StrGoUrl)) { echo "<script language="javascript">history.go(-1);</script>"; } else { echo "<script language="javascript">window.location="".$StrGoUrl."";</script>"; } exit; } } ?> ``` ## 例式4 ``` <?php /** * php防止sql注入 * by www.httple.net */ /* 过滤所有GET过来变量 */ foreach ($_GET as $get_key=>$get_var) { if (is_numeric($get_var)) { $get[strtolower($get_key)] = get_int($get_var); } else { $get[strtolower($get_key)] = get_str($get_var); } } /* 过滤所有POST过来的变量 */ foreach ($_POST as $post_key=>$post_var) { if (is_numeric($post_var)) { $post[strtolower($post_key)] = get_int($post_var); } else { $post[strtolower($post_key)] = get_str($post_var); } } /* 过滤函数 */ //整型过滤函数 function get_int($number) { return intval($number); } //字符串型过滤函数 function get_str($string) { if (!get_magic_quotes_gpc()) { return addslashes($string); } return $string; } ?> ``` ## 例式5 ``` <?php /** * php防止sql注入 * by www.httple.net */ class sqlsafe { private $getfilter = "'|(and|or)\\b.+?(>|<|=|in|like)|\\/\\*.+?\\*\\/|<\\s*script\\b|\\bEXEC\\b|UNION.+?SELECT|UPDATE.+?SET|INSERT\\s+INTO.+?VALUES|(SELECT|DELETE).+?FROM|(CREATE|ALTER|DROP|TRUNCATE)\\s+(TABLE|DATABASE)"; private $postfilter = "\\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)"; private $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)"; /** * 构造函数 */ public function __construct() { foreach($_GET as $key=>$value){$this->stopattack($key,$value,$this->getfilter);} foreach($_POST as $key=>$value){$this->stopattack($key,$value,$this->postfilter);} foreach($_COOKIE as $key=>$value){$this->stopattack($key,$value,$this->cookiefilter);} } /** * 参数检查并写日志 */ public function stopattack($StrFiltKey, $StrFiltValue, $ArrFiltReq){ if(is_array($StrFiltValue))$StrFiltValue = implode($StrFiltValue); if (preg_match("/".$ArrFiltReq."/is",$StrFiltValue) == 1){ $this->writeslog($_SERVER["REMOTE_ADDR"]." ".strftime("%Y-%m-%d %H:%M:%S")." ".$_SERVER["PHP_SELF"]." ".$_SERVER["REQUEST_METHOD"]." ".$StrFiltKey." ".$StrFiltValue); showmsg('您提交的参数非法,系统已记录您的本次操作!','',0,1); } } /** * SQL注入日志 */ public function writeslog($log){ $log_path = CACHE_PATH.'logs'.DIRECTORY_SEPARATOR.'sql_log.txt'; $ts = fopen($log_path,"a+"); fputs($ts,$log."\r\n"); fclose($ts); } } ?> ``` ## PHP防XSS 防SQL注入的代码 ``` /** * 过滤参数 * @param string $str 接受的参数 * @return string */ static public function filterWords($str) { $farr = array( "/<(\\/?)(script|i?frame|style|html|body|title|link|meta|object|\\?|\\%)([^>]*?)>/isU", "/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU", "/select|insert|update|delete|\'|\/\*|\*|\.\.\/|\.\/|union|into|load_file|outfile|dump/is" ); $str = preg_replace($farr,'',$str); return $str; } /** * 过滤接受的参数或者数组,如$_GET,$_POST * @param array|string $arr 接受的参数或者数组 * @return array|string */ static public function filterArr($arr) { if(is_array($arr)){ foreach($arr as $k => $v){ $arr[$k] = self::filterWords($v); } }else{ $arr = self::filterWords($v); } return $arr; } ``` 在防止被注入攻击时,常会用到两个函数:htmlspecialchars()和addslashes() 、trim()函数。这两个函数都是对特殊字符进行转义。 1)addslashes()作用及使用 addslashes()通常用于防止sql注入,它可对通过get,post和cookie传递过来的参数的单引号和双引号已经null前加“\”进行转义 如:如变量s t r = str=str=_POST[“str”];的值为:bb’ or 1=‘1。通过addslashes()函数过滤后会变为:bb’ or 1='1; 2)htmlspecialchars()作用及使用 htmlspecialchars()也是对字符进行转义,与addslashes()不同的是htmlspecialchars()是将特殊字符用引用实体替换。 如通过htmlspecialchars()过滤后为 3)addslashes()与htmlspecialchars()的区别 除了两个函数的转义方式不同外,它们的使用也不同。 addslashes()通过用于防止sql语句注入,在执行sql语句前对通过get、post和cookie传递来的参数中的单引号,双引号,\ 和null进行转义。 但sql执行成功后,插入到数据库中的数据是不带有转义字符\的。这是如果插入到数据库中的是一些js脚本,当这些脚本被读取出来时还是会被执行。 这是我们可对读取出来的数据使用htmlspecialchars()进行过滤,避免执行被注入的脚本。