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、禁止在 HTTP 头中泄漏 PHP 版本信息 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
8、if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST[‘lastname’]);
} else {
$lastname = $_POST[‘lastname’];
}
get_magic_quotes_gpc
过滤后不用 addslashes 以免重复过滤
例式 1
<?php
/**
* php 防止 sql 注入
* by https://www.huizhanii.com/33552.html
*/
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 https://www.huizhanii.com/33552.html
*/
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(">", "", $str);
$str = str_replace("<", "", $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 https://www.huizhanii.com/33552.html
*/
/* 过滤所有 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 注入
* byhttps://www.huizhanii.com/33552.html
*/
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 前加上反斜杠进行转义。
例如,如果变量$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 执行成功后,插入到数据库中的数据是不带有转义字符\的。如果插入到数据库中的是一些JavaScript脚本,当这些脚本被读取出来时仍然会被执行。
因此,我们可以对读取出来的数据使用 htmlspecialchars()进行过滤,避免执行被注入的脚本。
转载请注明:汇站网 » PHP 防止 SQL 注入的代码,PHP 预防跨站请求伪造(CSRF)、跨站脚本攻击(XSS)、SQL 注入攻击
不错。