有效防止SQL注入漏洞详细说明

 更新时间:2016年11月25日 15:25  点击:1424

1.如果动态构造的sql语句中包含参数,请必须对参数做如下操作
a.将'(单引号)替换成''(两个单引号)
b.将--(注释符)替换掉
c.将参数加入语句时,一定要在前后各加上引号,如:'select * from table where id='''+@id+''''这样的加法
2.如果动态构造的sql语句中包含表参数,请勿必给表加上[](中括号),如:'select * from ['+@tab+']'这样的做法

3..避免动态sql语句:尤其是从ie客户端获取查询、修改、删除条件的字段最容易被注入,例如上述从客户端获取personid,为了开发方便,直接把从客户端获取的persongid作为sql语句的条件,却没有对personid作必要的检查,所以在开发时执行sql语句时最好使用preparedstatement类。

 

4.  验证数据:在客户端ie使用网页特效验证用户输入数据的合法性作用其实不是很大,一定要在获取客户端数据之后,对数据进行严格的验证,开发人员不要假想用户只会输入合法的数据。确保在应用程序中检查分号、引号、括号、sql关键字等。可以使用正则表达式来进行复杂的模式匹配,运用它可以达到良好的效果。


×××网站地址薄查看程序需要传递一个personid,personid可以通过url参数传递,由于地址本查看程序直接获取personid,没有做任何数据合法性验证,而且personid是字符串变量,获取personid的代码如下:

if (getparameter(req,"personid")!=null){

personid=getparameter(req,"personid").trim();

}else{

personid="";

}

该程序中组合成的动态sql语句如下:

personsql="select * from 表名 where userid="+long.tostring(userid)+" and addrcontactid="+personid;

 

由于程序没有检查personid是否是整数,所以攻击者随便给personid赋一个值,即可继续运行后续的程序逻辑,如果攻击者输入如下网址:

http://www.----------------------?personid=6414 or 2=2

组合成的sql语句如下:

select * from 表名where userid=1433620 and addrcontactid=6414 or 2=2

防范方法

  sql注入漏洞可谓是“千里之堤,溃于蚁穴”,这种漏洞在网上极为普遍,通常是由于程序员对注入不了解,或者程序过滤不严格,或者某个参数忘记检查导致。在这里,我给大家一个函数,代替asp教程中的request函数,可以对一切的sql注入say no,函数如下:

function saferequest(paraname,paratype)
 '--- 传入参数 ---
 'paraname:参数名称-字符型
 'paratype:参数类型-数字型(1表示以上参数是数字,0表示以上参数为字符)

 dim paravalue
 paravalue=request(paraname)
 if paratype=1 then
  if not isnumeric(paravalue) then
   response.write "参数" & paraname & "必须为数字型!"
   response.end
  end if
 else
  paravalue=replace(paravalue,"'","''")
 end if
 saferequest=paravalue
end function

上面函数应用

对于int型的参数,如文章的id等,可以先判断是不是整数。

id =trim(request("id"))
if id<>"" then
  if not isnumeric(id) then
    response.write"请提供数字型参数"
    response.end
  end if
  id = clng(id)
else
  response.write"请输入参数id"
  response.end
end if

首先我们推荐filter_sanitize_string ,filter_sanitize_string 过滤器去除或编码不需要的字符。

这个过滤器删除那些对应用程序有潜在危害的数据。它用于去除标签以及删除或编码不需要的字符。

name: "string"
id-number: 513
可能的选项或标志:

filter_flag_no_encode_quotes - 该标志不编码引号
filter_flag_strip_low - 去除 ascii 值在 32 以下的字符
filter_flag_strip_high - 去除 ascii 值在 32 以上的字符
filter_flag_encode_low - 编码 ascii 值在 32 以下的字符
filter_flag_encode_high - 编码 ascii 值在 32 以上的字符
filter_flag_encode_amp - 把 & 字符编码为 &amp;

*/

$var="<b>bill gates<b>";

var_dump(filter_var($var, filter_sanitize_string));

/*
第二个函数strip_tags
strip_tags() 函数剥去 html、xml 以及 php教程 的标签。

语法
strip_tags(string,allow)
*/

echo strip_tags("hello <b>world!</b>");

//hello world!

function uh($str)
{
    $farr = array(
        "/s+/",                                                                    
                       //过滤多余的空白
        "/<(/?)(script|i?frame|style|html|body|title|link|meta|?|%)([^>]*?)>/isu",
  //过滤 <script 等可能引入恶意内容或恶意改变显示布局的代码,如果不需要插入flash等,还可
以加入<object的过滤
        "/(<[^>]*)on[a-za-z]+s*=([^>]*>)/isu",                                     
//过滤网页特效的on事件
     
   );
   $tarr = array(
        " ",
        "<123>",           //如果要直接清除不安全的标签,这里可以留空
        "12",
   );

  $str = preg_replace( $farr,$tarr,$str);
   return $str;
}

更多详细内容请查看:http://www.111cn.net/phper/19/70dd2a905e74cefc9be9c0f17268dadc.htm
?>


<?php教程
require_once(dirname(__file__)."/../include/common.inc.php");
if(emptyempty($dopost))
{
$dopost = "";
}
if($dopost=="rename")
{
if(rename('dedesql.query.php','arc.sqlquery.class.php')){
echo "成功!";
}else{
echo "失败!";
}
exit();
}
if($dopost=="viewinfo")
{
if(emptyempty($tablename))
{
echo "没有指定表名!";
}
else
{
$dsql->setquery("show create table ".$dsql->dbname.".".$tablename);
$dsql->execute('me');
$row2 = $dsql->getarray('me',mysql教程_both);
$ctinfo = $row2[1];
echo "<xmp>".trim($ctinfo)."</xmp>";
}
exit();
}
if($dopost=="index")
{
require_once(dedeinc.'/arc.partview.class.php');
$envs = $_sys_globals = array();
$envs['aid'] = 0;
$pv = new partview();
$row = $pv->dsql->getone('select * from `#@__homepageset`');
$templet = str_replace("{style}",$cfg_df_style,$row['templet']);
$homefile = dirname(__file__).'/'.$row['position'];
$homefile = str_replace("//","/",str_replace("","/",$homefile));
$fp = fopen($homefile,'w') or die("无法更新网站主页到:$homefile 位置");
fclose($fp);
$tpl = $cfg_basedir.$cfg_templets_dir.'/'.$templet;
$pv->settemplet($tpl);
$pv->savetohtml($homefile);
$pv->close();
echo "成功更新首页!";
exit();
}
else if($dopost=="query")
{
$sqlquery = trim(strips教程lashes($sqlquery));
if(eregi("drop(.*)table",$sqlquery) ||eregi("drop(.*)database",$sqlquery))
{
echo "<span style='font-size:10pt'>删除'数据表'或'数据库教程'的语句不允许在这里执行。</span>";
exit();
}
if(eregi("^select ",$sqlquery))
{
$dsql->setquery($sqlquery);
$dsql->execute();
if($dsql->gettotalrow()<=0)
{
echo "运行sql:{$sqlquery},无返回记录!";
}
else
{
echo "运行sql:{$sqlquery},共有".$dsql->gettotalrow()."条记录,最大返回100条!";
}
$j = 0;
while($row = $dsql->getarray())
{
$j++;
if($j>100)
{
break;
}
echo "<hr size=1 width='100%'/>";
echo "记录:$j";
echo "<hr size=1 width='100%'/>";
foreach($row as $k=>$v)
{
echo "<font color='red'>{$k}:</font>{$v}<br/>rn";
}
}
exit();
}
if($querytype==2)
{
$sqlquery = str_replace("r","",$sqlquery);
$sqls = split(";[ t]{0,}n",$sqlquery);
$nerrcode = "";$i=0;
foreach($sqls as $q)
{
$q = trim($q);
if($q=="")
{
continue;
}
$dsql->executenonequery($q);
$errcode = trim($dsql->geterror());
if($errcode=="")
{
$i++;
}
else
{
$nerrcode .= "执行: <font color='blue'>$q</font> 出错,错误提示:<font color='red'>".$errcode."</font><br>";
}
}
echo "成功执行{$i}个sql语句!<br><br>";
echo $nerrcode;
}
else
{
$dsql->executenonequery($sqlquery);
$nerrcode = trim($dsql->geterror());
echo "成功执行1个sql语句!<br><br>";
echo $nerrcode;
}
exit();
}
if($dopost=="view")
{
;echo '<html>
<head>
<meta http-equiv='content-type' content='text/html; charset=gb2312'>
<title>sql命令行工具</title>
<link href='img/base.css教程' rel='stylesheet' type='text/css'>
</head>
<body background='img/allbg.gif' leftmargin='8' topmargin='8'>
<table width="98%" border="0" align="center" cellpadding="3" cellspacing="1" bgcolor="#d1ddaa">
<tr>
<td height="19" background="img/tbg.gif">
<table width="96%" border="0" cellspacing="1" cellpadding="1">
<tr>
<td width="24%"><strong>sql命令运行器:</strong></td>
<td width="76%" align="right"> <b><a href="sys_data.php"><u>数据备份</u></a></b>
| <b><a href="sys_data_revert.php"><strong><u>数据还原</u></strong></a></b>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="200" bgcolor="#ffffff" valign="top">
<table width="100%" border="0" cellspacing="4" cellpadding="2">
<form action="" method="post" name="infoform" target="stafrm">
<input type='hidden' name='dopost' value='viewinfo' />
<tr bgcolor="#f3fbec">
<td width="15%" height="24" align="center">系统的表信息:</td>
<td>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="35%">
<select name="tablename" id="tablename" style="width:100%" size="6">
';
$dsql->setquery("show tables");
$dsql->execute('t');
while($row = $dsql->getarray('t',mysql_both))
{
$dsql->setquery("select count(*) from ".$row[0]);
$dsql->execute('n');
$row2 = $dsql->getarray('n',mysql_both);
$dd = $row2[0];
echo " <option value='".$row[0]."'>".$row[0]."(".$dd.")</option>rn";
}
;echo ' </select>
</td>
<td width="2%"> </td>
<td width="63%" valign="bottom">
<div style="float:left;margin-right:20px;">
<input type="submit" name="submit1" value="优化选中表" class="coolbg np" onclick="this.form.dopost.value='opimize';" />
<br />
<input type="submit" name="submit2" value="修复选中表" class="coolbg np" onclick="this.form.dopost.value='repair';" style="margin-top:6px;" />
<br />
<input type="submit" name="submit3" value="查看表结构" class="coolbg np" onclick="this.form.dopost.value='viewinfo';" style="margin-top:6px;" />
</div>
<div style="float:left">
<input type="submit" name="submit5" value="优化全部表" class="coolbg np" onclick="this.form.dopost.value='opimizeall';" />
<br />
<input type="submit" name="submit6" value="修复全部表" class="coolbg np" onclick="this.form.dopost.value='repairall';" style="margin-top:6px;" />
</div>
</td>
</tr>
</table></td>
</tr>
<tr>
<td height="200" align="center">返回信息:</td>
<td>
<iframe name="stafrm" frameborder="0" id="stafrm" width="100%" height="100%"></iframe>
</td>
</tr>
</form>
<form action="" method="post" name="form1" target="stafrm">
<input type='hidden' name='dopost' value='query'>
<tr>
<td height="24" colspan="2" bgcolor="#f3fbec"><strong>运行sql命令行:
<input name="querytype" type="radio" class="np" value="0">
单行命令(支持简单查询)
<input name="querytype" type="radio" class="np" value="2" checked>
多行命令</strong></td>
</tr>
<tr>
<td height="118" colspan="2">
<textarea name="sqlquery" cols="60" rows="10" id="sqlquery" style="width:90%"></textarea>
</td>
</tr>
<tr>
<td height="53" align="center"> </td>
<td>
<input name="imagefield" type="image" src="img/button_ok.gif" width="60" height="22" border="0" class='np' />
</td>
</tr>
</form>
</table>
</td>
</tr>
</table>
</body>
</html>
';}
?>

1. php 配置文件 php.ini 中的 magic_quotes_gpc 选项没有打开,被置为 off
  2. 开发者没有对数据类型进行检查和转义
  不过事实上,第二点最为重要。我认为, 对用户输入的数据类型进行检查,向 mysql教程 提交正确的数据类型,这应该是一个 web 程序员最最基本的素质。但现实中,常常有许多小白式的 web 开发者忘了这点, 从而导致后门大开。
  为什么说第二点最为重要?因为如果没有第二点的保证,magic_quotes_gpc 选项,不论为 on,还是为 off,都有可能引发 sql 注入攻击。下面来看一下技术实现:
 一. magic_quotes_gpc = off 时的注入攻击
  magic_quotes_gpc = off 是 php 中一种非常不安全的选项。新版本的 php 已经将默认的值改为了 on。但仍有相当多的服务器的选项为 off。毕竟,再古董的服务器也是有人用的。
  当magic_quotes_gpc = on 时,它会将提交的变量中所有的 '(单引号)、"(双号号)、(反斜线)、空白字符,都为在前面自动加上 。下面是 php 的官方说明:

复制代码 代码如下:
magic_quotes_gpc boolean

sets the magic_quotes state for gpc (get/post/cookie) operations. when magic_quotes are on, all ' (single-quote), " (double quote), (backslash) and nul's are escaped with a backslash automatically

如果没有转义,即 off 情况下,就会让攻击者有机可乘。以下列测试脚本为例:
复制代码 代码如下:

<?
if ( isset($_post["f_login"] ) )
{
// 连接数据库教程...
// ...代码略...

// 检查用户是否存在
$t_struname = $_post["f_uname"];
$t_strpwd = $_post["f_pwd"];
$t_strsql = "select * from tbl_users where username='$t_struname' and password = '$t_strpwd' limit 0,1";

if ( $t_hres = mysql_query($t_strsql) )
{
// 成功查询之后的处理. 略...
}
}
?>

<html><head><title>sample test</title></head>
<body>
<form method=post action="">
username: <input type="text" name="f_uname" size=30><br>
password: <input type=text name="f_pwd" size=30><br>

<input type="submit" name="f_login" value="登录">
</form>
</body> 

 

<?php教程
/*************************
说明:
判断传递的变量中是否含有非法字符
如$_post、$_get
功能:
防注入
**************************/
//要过滤的非法字符  这个过滤的字符 还可以增加
$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="网页特效">alert("非法字符");</script>";
if (empty($strgourl)){
echo "<script language="javascript">history.go(-1);</script>";
}else{
echo "<script language="javascript">window.location="".$strgourl."";</script>";
}
exit;
}
}
?>

[!--infotagslink--]

相关文章

  • phpems SQL注入(cookies)分析研究

    PHPEMS(PHP Exam Management System)在线模拟考试系统基于PHP+Mysql开发,主要用于搭建模拟考试平台,支持多种题型和展现方式,是国内首款支持题冒题和自动评分与教师评分相...2016-11-25
  • ASP/PHP sql注入语句整理大全

    SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作 标准注入语句1.判...2016-11-25
  • PHP防止SQL注入的例子

    防止SQL注入是我们程序开发人员必须要做的事情了,今天我们就来看一篇关于PHP防止SQL注入的例子了,具体的实现防过滤语句可以参考下面来看看吧。 使用prepared以及参...2016-11-25
  • php中Multipart/form-data漏洞补丁修复

    Multipart/form-data是文件上传或数据提交时会用到了,在php中Multipart/form-data是有安全bug的,下面我们来看看如何修复Multipart/form-data的bug吧. 今天在乌云...2016-11-25
  • AngularJS 依赖注入详解及示例代码

    本文主要介绍AngularJS 依赖注入的知识,这里整理了相关的基础知识,并附示例代码和实现效果图,有兴趣的小伙伴可以参考下...2016-08-24
  • PHP中自带函数过滤sql注入代码分析

    SQL注入攻击是黑客攻击网站最常用的手段。如果你的站点没有使用严格的用户输入检验,那么常容易遭到SQL注入攻击。SQL注入攻击通常通过给站点数据库提交不良的数据或...2016-11-25
  • Spring boot 无法注入service问题

    这篇文章主要介绍了Spring boot 无法注入service问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-10-09
  • Spring 配置文件字段注入到List、Map

    这篇文章主要介绍了Spring 配置文件字段注入到List、Map,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-19
  • php sql防注入以及 html 过滤安全函数

    方法一过滤html自定义函数 代码如下 复制代码 function ihtmlspecialchars($string) { if(is_array($string)) { foreach($string as $key =>...2016-11-25
  • sql安全之SQL注入漏洞拖库原理解析

    本文章以自己的一些经验来告诉你黑客朋友们会怎么利用你数据库的sql漏洞来把你的数据库下载哦,有需要的同这参考一下本文章。 在数据库中建立一张表: 代码...2016-11-25
  • .Net防sql注入的几种方法

    这篇文章主要给大家总结介绍了关于.Net防sql注入的几种方法,文中通过示例代码介绍的非常详细,对大家学习或者使用.Net具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧...2021-09-22
  • ASP.NET防止SQL注入的方法示例

    这篇文章主要介绍了ASP.NET防止SQL注入的方法,结合具体实例形式分析了asp.net基于字符串过滤实现防止SQL注入的相关操作技巧,需要的朋友可以参考下...2021-09-22
  • SpringBoot属性注入的多种方式实例

    在 SpringBoot中,提供了一种新的属性注入方式,支持各种java基本数据类型及复杂类型的注入,下面这篇文章主要给大家介绍了关于SpringBoot属性注入的多种方式,需要的朋友可以参考下...2021-10-30
  • spring中向一个单例bean中注入非单例bean的方法详解

    Spring是先将Bean对象实例化之后,再设置对象属性,所以会先调用他的无参构造函数实例化,每个对象存在一个map中,当遇到依赖,就去map中调用对应的单例对象,这篇文章主要给大家介绍了关于spring中向一个单例bean中注入非单例bean的相关资料,需要的朋友可以参考下...2021-07-19
  • .NET Core源码解析配置文件及依赖注入

    这篇文章我们设计了一些复杂的概念,因为要对ASP.NET Core的启动及运行原理、配置文件的加载过程进行分析,依赖注入,控制反转等概念的讲解等...2021-09-22
  • ASP.NET Core依赖注入系列教程之控制反转(IoC)

    这篇文章主要给大家介绍了关于ASP.NET Core依赖注入系列教程之控制反转(IoC)的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-09-22
  • php防注入过滤客户提交$_GET 和$_POST参数

    下面一款防止php页面给sql注入的一个程序代码,有需要的朋友可参考。 以下代码实现过滤php的$_GET 和$_POST参数 代码如下 复制代码 /** *...2016-11-25
  • 浅析依赖注入框架Autofac的使用

    Autofac是一款IOC框架,比起Spring.NET,Unity,Castle等等框架,它很轻量级且性能也很高,下面小编给大家介绍下依赖注入框架Autofac的使用。...2020-06-25
  • 如何获取C#中方法的执行时间以及其代码注入详解

    这篇文章主要给大家介绍了关于如何获取C#中方法的执行时间以及其代码注入的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧...2020-06-25
  • PHP漏洞之SQL注入攻击简单介绍

    SQL注入是一种攻击,允许攻击者增加额外的逻辑表达式和命令,以现有的SQL查询,种攻击能够成功每当用户提交的数据是不正确验证,并粘有一个合法的SQL查询在一起,所以说sql注...2016-11-25