按照百度说法,SQL注入是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。其实就是就是提交精心构造的数据库语句,使其反馈一些有用的数据。说白了就是去欺骗数据库,假如只有web服务器的话,是没法进行SQL注入的。
    网上常用的注入手法有两种,一种是猜测,让数据库暴出用户名、密码等信息;另一种直接绕过认证,取得权限。相对应,要想修复此类漏洞,就必须禁止特殊数据的提交或将特殊提交的数据修改。
    下面是不同脚本语言下的防注入过滤代码,其实思想是一致的。

 

1、    PHP防注入过滤代码

/*************************
说明:        判断传递的变量中是否含有非法字符 如$_POST、$_GET 
功能:        防注入
使用方法:    将下列代码保存为ak,php,调用方式 在数据提交页加上include("ak.php");
**************************/ 

<?php
function dowith_sql($str)
//实现将特征码两边加.

$refuse_str="exec|and|or|select|update|from|where|order|by|*|delete|'|insert|into|values|create|table|

database|set|char|asc|cast|declare|<script|script|iframe|3bomb|c.js|;";
//定义防注入的字符
   $arr=explode("|",$refuse_str);
//将$refuse_str中的值单独取出
   for($i=0;$i<count($arr);$i++)
   {
     $replace="[".$arr[$i]."]";
     $str=str_replace($arr[$i],$replace,$str);
//在变量$str中搜索字符串$arr[$i],并将其替换为字符串[$replace]
   }
   return $str;
}
foreach ($_GET as $key=>$value)
//遍历获GET方法获得的参数$_GET的值传给$key,并赋值给$value
{
  $_GET[$key]=dowith_sql($value);
//将$value中的特征码处理传个$_GET[$key]
}
foreach ($_POST as $key=>$value)
{
  $_POST[$key]=dowith_sql($value);
}
?>



    上面的防注入的方法只是防了GET与POST方法提交的数据,但是,WEB服务器读取数据的顺序是,先取GET中的数据,没有再去POST中的数据,没有还会再去COOKIES中的数据,上面的代码还没有防cookies注入。防cookies注入就比较简单了,cookies的id值一般只为阿拉伯数字,但是cookies注入必须得在id中构造代码,只要在获得参数UID后,对其进行过滤就可以了,代码如下:

<?php
if($_COOKIE['id']!=null) {
//判断cookies不为空
foreach ($_COOKIE['id'] as $key=>$id){
//读取cookies中的值
if (if_numeric($id)<0){
echo "<script language=\\"javascript\\">alert(\\"请不要输入非法字符!\\");</script>" history.go(-1);</script>"; 
}
}
?>


    将上述代码保存为hk.php。所以在平时应用时,在网页上加上include("ak.php");与include("hk.php");


2、asp防注入过滤代码
'--------说明------------------
'使用方法:  在需要防注的页面头部用 <!--#Include File="sql2.asp"-->包含就可以了
'友情提示:把代码复制到CONN.asp(数据库连接文件) 那么,只要包含了CONN的所有文件都防注了

<%
Dim xf_Post,xf_Get,xf_In,xf_Inf,xf_Xh,xf_db,xf_dbstr
'自定义需要过滤的字串,用 "|" 分隔
xf_In = "'|;|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare"
xf_Inf = split(xf_In,"|")
If Request.Form<>"" Then
For Each xf_Post In Request.Form

For xf_Xh=0 To Ubound(xf_Inf)
If Instr(LCase(Request.Form(xf_Post)),xf_Inf(xf_Xh))<>0 Then
Response.Write "<Script Language=JavaScript>alert('请不要在参数中包含非法字符尝试注入');</Script>"
Response.Write "非法操作!系统做了如下记录↓<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"
Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:POST<br>"
Response.Write "提交参数:"&xf_Post&"<br>"
Response.Write "提交数据:"&Request.Form(xf_Post)
Response.End
End If
Next
Next
End If
If Request.QueryString<>"" Then
For Each xf_Get In Request.QueryString
For xf_Xh=0 To Ubound(xf_Inf)
If Instr(LCase(Request.QueryString(xf_Get)),xf_Inf(xf_Xh))<>0 Then
Response.Write "<Script Language=JavaScript>alert('请不要在参数中包含非法字符尝试注入');</Script>"
Response.Write "非法操作!系统已经给你做了如下记录↓<br>"
Response.Write "操作IP:"&Request.ServerVariables("REMOTE_ADDR")&"<br>"
Response.Write "操作时间:"&Now&"<br>"

Response.Write "操作页面:"&Request.ServerVariables("URL")&"<br>"
Response.Write "提交方式:GET<br>"
Response.Write "提交参数:"&xf_Get&"<br>"
Response.Write "提交数据:"&Request.QueryString(xf_Get)
Response.End
End If
Next
Next
End If
%>



    同样,再将cookies防一下,代码加在数据提交页。
if(Request.Cookies["uid"]!=null)
{
uid=Request.Cookies["uid"].value;
isnumeric cooidesID = new isnumeric();
//这是一个类
if (cooidesID.reIsnumeric(ruid))
//如果是数字就运行下面的
{
string str="select * from userTable where id="+uid;
...
}
}


3、    JSP防注入过滤代码
<script language="javascript">
<!--
var url = location.search;
// 函数location.search作用是取?之后的参数值,取得 QueryString 部分
var re=/^?(.*)(select%20|insert%20|delete%20from%20|count(|drop%20table|update%20truncate%20|asc(|mid(|char(|xp_cmdshell|exec%20master|net%20localgroup%20administrators|"|:|net%20user||%20or%20)(.*)$/gi;
//定义特殊字符串
var e = re.test(url);
//test()字符串中是否有匹配正则表达式的子字符串。返回true或false。
if(e) {
    alert("地址中含有非法字符~");
    location.href="error.asp";
}
//-->
<script>


    当然,我们也可以定义过滤函数,直接应用到用户名、密码等提交的数据参数上,函数如下:
function checkuseravoid(str){
var inj_str="‘|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|;|or|-|+|,";
var sarray=new Array();
sarray=inj_str.split('|');
for (var i=0 ;i <inj_stra.length ;i++ ) {
if (str.indexOf(inj_stra)>=0)
return true;
}
return false;
}


4、C#防注入过滤代码
//这个例子里暂定为=号和号,可继续添加
bool CheckParams(params object[] args)
{
     string[] Lawlesses={"=",""};
     if(Lawlesses==null||Lawlesses.Length<=0)return true;

     构造正则表达式,例:Lawlesses是=号和号,则正则表达式为 .*[=}].*
     另外,由于我是想做通用而且容易修改的函数,所以多了一步由字符数组到正则表达式,实际使用中,直接写正则表达式亦可;

     string str_Regex=".*[";
     for(int i=0;i< Lawlesses.Length-1;i++)
         str_Regex+=Lawlesses+"|";
     str_Regex+=Lawlesses[Lawlesses.Length-1]+"].*";
     //
     foreach(object arg in args)
     {
         if(arg is string)
//如果是字符串,直接检查
         {
             if(Regex.Matches(arg.ToString(),str_Regex).Count>0)
             return false;
         }
         else if(arg is ICollection)
//如果是一个集合,则检查集合内元素是否字符串,是字符串,就进行检查
         {
             foreach(object obj in (ICollection)arg)
             {
                 if(obj is string)
                 {
                     if(Regex.Matches(obj.ToString(),str_Regex).Count>0)
                     return false;
                 }
             }
         }
     }
     return true;