sql注入的代码修复

文章主要以php环境讲述sql注入的修复,从简单到复杂,当然网上也有相应的绕过方法。首先我们写一个存在sql注入的php文件。

<?php
$id =$_GET['id'];
$con=mysqli_connect("localhost","root","root","jj");
$query = "select id,name, pass from user where id = $id";
echo "执行的sql语句为:<br>";
echo ($query)."<br>";
$result = mysqli_query ($con,$query);
if (mysqli_num_rows($result) > 0) {
   echo "查询结果为:<br>";
    while($row = mysqli_fetch_assoc($result)) {
        echo "id:" . $row["id"]."<br>",
        "username:" . $row["name"]."<br>",
        "password " . $row["pass"]. "<br>";
    }
} else {
    echo "no information";
}
?>

mysqli_real_escape_string()

函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:

  • \
  • "
  • \x00
  • \n
  • \r
    其实实际过程中,主要还是过滤前三个字符,函数语法如下:mysqli_real_escape_string($ con,$ id);
    $con是数据库连接参数,对应的php语句为:
    $con = mysqli_connect(“localhost”,“root”,“root”,“db”);
    id为接受的参数,也可以是字符串"str"。
    我们将函数加在获取id之后 $ id = mysqli_real_escape_string($ con,$id);
    我们在执行一下看下效果 '被转换成 ’ sql查询错误
    '被转变'

is_numeric()

函数用于检测变量是否为数字或数字字符串。
函数语法 is_numeric( $id ) id为接收的参数也可为字符串
该函数可以基本过滤掉一般的注入语句,如果不是数字型则不带入查询直接结束。

if(is_numeric( $id )) {
$query = "select id,name, pass from user where id = $id";
echo "执行的sql语句为:<br>";
echo ($query)."<br>";
$result = mysqli_query ($con,$query);

if (mysqli_num_rows($result) > 0) {
   echo "查询结果为:<br>";
    while($row = mysqli_fetch_assoc($result)) {
        echo "id:" . $row["id"]."<br>",
        "username:" . $row["name"]."<br>",
        "password " . $row["pass"]. "<br>";
    }
} else 
    echo "no information";

这个方法的局限在于只能接收数字型参数,如果想使用字符型参数则不能使用这个函数。

preg_replace()

函数执行一个正则表达式的搜索和替换。
函数语法 echo preg_replace (‘a’,‘b’,‘c’) 函数一个三个变量 第一个a是匹配的内容,b是要转换后的内容,c为转换的目标。
通俗一点说就是匹配到就替换,c中如果有包含a内容的字符串,就将其转换成b。下面是过滤一些危险语句的正则替换。

$pregs = '/select|insert|update|CR|document|LF|eval|delete|script|alert|\'|\/\*|\#|\--|\ --|\/|\*|\-|\+|\=|\~|\*@|\*!|\$|\%|\^|\&|\(|\)|\/|\/\/|\.\.\/|\.\/|union|into|load_file|outfile/';

PDO

PDO全名PHP Data Object
PHP 数据对象 (PDO) 扩展为PHP访问数据库定义了一个轻量级的一致接口。
PDO 提供了一个数据访问抽象层,这意味着,不管使用哪种数据库,都可以用相同的函数(方法)来查询和获取数据。
PDO可以说是基本杜绝了sql注入,因为它将查询语句与接受的参数分离开来,哪怕输入恶意的sql查询语句,也起不到查询作用。
使用PDO访问MySQL数据库时,真正的real prepared statements 默认情况下是不使用的。为了解决这个问题,你必须禁用 prepared statements的仿真效果。下面是使用PDO创建链接的例子:

$pdo=new PDO("mysql:host=localhost;dbname=db","user","pass");
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);

这行代码极其重要,如果没有禁用prepared statements的仿真效果,本地就会将查询的sql语句模板和经过本地转义的参数id 拼接然后发送到mysql进行查询,这还会导致sql注入。
防范sql注入通过预处理的一些方式以及bindParameter()方法绑定参数来防止SQL注入,本文主要举例bindParmeter()方法

<?php
$id =$_GET['id'];
$pdo=new PDO("mysql:host=localhost;dbname=jj","root","root");
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$query = "select id,name, pass from user where id = :id";
echo "执行的sql语句为:<br>";
echo ($query)."<br>";
$stmt=$pdo->prepare($query);
$stmt->bindParam(":id",$id,PDO::PARAM_STR);
$stmt->execute();
$row = $stmt->fetch();
if( $stmt->rowCount() == 1 ) {
	echo "查询结果为:<br>";
	$id=$row['id'];
	$user=$row['name'];
	$pass=$row['pass'];
echo 'id:'.$id.'<br>',"name:".$user."<br>","pass:".$pass."<br>";}
else
	echo 'no information';
?>

上面这段代码就可以防范sql注入。为什么呢?
当调用 prepare() 时,查询语句已经发送给了数据库服务器,此时只有查询模板中的:id 发送过去,没有用户提交的数据id;当调用到 execute()时,用户提交过来的值才会传送给数据库,他们是分开传送的,两者独立的,SQL攻击者没有一点机会。我们执行一下看下结果。
在这里插入图片描述
我们给id赋值为 1 and 1=2 但发送到mysql的语句仍为select id,name,pass from user where id=:id,随后接收的id再单独发送至数据库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值