首页
社区
课程
招聘
[旧帖] [原创]浅谈php防sql注入 0.00雪花
发表于: 2016-4-29 11:55 2315

[旧帖] [原创]浅谈php防sql注入 0.00雪花

2016-4-29 11:55
2315
本人菜鸟一只,懂的不多(毕竟还在临时版本....),只是发表一下自己的理解,说的不对不好的地方,希望各位不要怪罪!如果能给予以指正,更是万分感谢!谢谢~

sql注入是目前公认的危害比较大的一个漏洞了,主要是利用的sql语句处理以及字符过滤不当的缺陷,今天以php为例简要说一下sql注入的一些方法:

数字型注入

php中一般比较常用有sql连接是使用mysql_connect这种面向过程的函数来进行连接,一个简单的例子(此处不考虑规范)

<?php
$c = mysql_connect("localhost","root","123456");
if(!$c){
  echo "connect error....".mysql_error();
  exit();
}
mysql_select_db("test");

$id = isset($_GET['id'])?$_GET['id']:1;
$sql = mysql_query("select * from test where id={$id}");
if(!$sql){
  echo mysql_error();
  exit;
}
while($row = mysql_fetch_array($sql)){
  echo "id:".$row['id']."<br/>";
  echo "content:".$row['content']."<br/>";
}


在这段程序里,他接受了一个用户输入的id参数,通过id来查询数据库中的对象,大体结果如下:



由于没有经过过滤,说明完全信任了用户的输入,而此时有不法用户输入了一些可以干扰原语句执行的字符,如一个单引号 ‘,就会产生如下效果:



这说明我们人为加入的单引号已经打乱了其原有的结构,我们再接着输入or 1=1–



可以看到所有结果都列出来了,再接着判断,输入and 1=2–



可以看到页面不显示任何东西了,因为这是个永假的语句,这样,我们就基本可以断定这是个注入点,我们使用sqlmap来跑一下看看







我们所有的数据库都被列举了出来,可见sql注入的危害性,下面我们来试着对其进行防护:

php中内置了字符串过滤参数可以过滤字符串,函数为addslashes()和htmlspecialchars(),我们试试对数字型的过滤,看可不可以

<?php
$c = mysql_connect("localhost","root","123456");
if(!$c){
  echo "connect error....".mysql_error();
  exit();
}
mysql_select_db("test");

$id = isset($_GET['id'])?$_GET['id']:1;
$id = addslashes(htmlspecialchars($id));
$sql = mysql_query("select * from test where id={$id}");
if(!$sql){
  echo mysql_error();
  exit;
}
while($row = mysql_fetch_array($sql)){
  echo "id:".$row['id']."<br/>";
  echo "content:".$row['content']."<br/>";
}


结果显示,依然无压力:



既然我们这个参数只接受数字类型,我们可以设置个过滤,把一些不必要的参数拦截:

<?php
$c = mysql_connect("localhost","root","123456");
if(!$c){
  echo "connect error....".mysql_error();
  exit();
}
mysql_select_db("test");

$id = isset($_GET['id'])?$_GET['id']:1;
if(preg_match("/[a-zA-Z]|\W/", $id)){
  exit("input error!");
}
$sql = mysql_query("select * from test where id={$id}");
if(!$sql){
  echo mysql_error();
  exit;
}
while($row = mysql_fetch_array($sql)){
  echo "id:".$row['id']."<br/>";
  echo "content:".$row['content']."<br/>";
}


sqlmap结果



可以看到,sqlmap使用普通注入已经找不到漏洞了,这里因为我们接收的是数值型的,所以我们可以匹配是否有字母或者字符,如果有,就禁止执行,这样可以达到防注入的效果。

 
字符型注入

下面我们将之前的脚本更改一下

<?php
$c = mysql_connect("localhost","root","123456");
if(!$c){
  echo "connect error....".mysql_error();
  exit();
}
mysql_select_db("test");

$content = isset($_GET['content'])?$_GET['content']:"test1";
$sql = mysql_query("select * from test where content='$content'");
if(!$sql){
  echo mysql_error();
  exit;
}
while($row = mysql_fetch_array($sql)){
  echo "id:".$row['id']."<br/>";
  echo "content:".$row['content']."<br/>";
}


我们用sqlmap来跑一下:



肯定是能注入的,下面我们使用addslashes()和htmlspecialchars()来过滤一下

<?php
$c = mysql_connect("localhost","root","123456");
if(!$c){
  echo "connect error....".mysql_error();
  exit();
}
mysql_select_db("test");

$content = isset($_GET['content'])?$_GET['content']:"test1";
$content = addslashes(htmlspecialchars($content));
$sql = mysql_query("select * from test where content='$content'");
if(!$sql){
  echo mysql_error();
  exit;
}
while($row = mysql_fetch_array($sql)){
  echo "id:".$row['id']."<br/>";
  echo "content:".$row['content']."<br/>";
}


使用sqlmap跑出的结果



可以看到普通的注入已经无法注入了,可以说明这两个函数可以在一定程度上阻止sql注入,如果想绕过,基本是不可能的,不过不排除绕过的可能性。

最终方法

在php5.3(或者5.4,记不清了。。。::>_<::)之后的版本,如果使用mysql_connect连接就会出现以下的提示



官方会移除mysql_connect这种函数(php7应该移除了,我也不清楚,没用过),建议我们使用pdo或者mysqli,在这两个中,有一种叫做预处理的东西,我们再结合addslaches()和htmlspecial()这两个函数,可以杜绝sql注入的发生,而且这种方法适对数字型或者字符型的注入都适用,代码如下:
<?php
$host="localhost";
$user="root";
$pass="123456";
$db="test";
$mysqli = new mysqli($host,$user,$pass,$db) or die("connect error....");
$sql="select * from test where content=?";
$stmt = $mysqli->prepare($sql);
$content = isset($_GET['content'])?$_GET['content']:"test1";
$content = addslashes(htmlspecialchars($content));
$stmt->bind_param('s',$content);
$stmt->bind_result($id,$content1);
$stmt->execute();
while ($stmt->fetch()) {
  echo "id:".$id."<br/>";
  echo "content:".$content1."<br/>";
}


希望大家指出错误!谢谢!
</End>

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 43
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
预处理是比较好的处理方式,但很多开发人员都喜欢直接改发生注入的文件,导致修复不完全
2016-6-2 11:26
0
雪    币: 5
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
楼主对于sql注入漏洞的理解很清晰,支持
2016-6-2 11:36
0
游客
登录 | 注册 方可回帖
返回
//