0X01 普通注入

SQL参数拼接,未做任何过滤

<?php
$con = mysql_connect("localhost","root","root");
if (!$con){die('Could not connect: ' . mysql_error());}
mysql_select_db("test", $con);
$id = stripcslashes($_REQUEST[ 'id' ]);
$query = "SELECT * FROM users WHERE id = $id ";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>');
while($row = mysql_fetch_array($result))
{
echo $row[''] . " " . $row[''];
echo "<br />";
}
echo "<br/>";
echo $query;
mysql_close($con);
?>

测试语句:id=1 UNION SELECT user(),2,3,4 from users

0x02 宽字节注入

A、MYSQL中的宽字符注入

示例代码:

<?php
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES 'gbk'");
mysql_select_db("test", $con);
$id = isset($_GET['id']) ? addslashes($_GET['id']) : ;
$query = "SELECT * FROM users WHERE id ='{$id}' ";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>');
while($row = mysql_fetch_array($result))
{
echo $row[''] . " " . $row[''];
echo "<br />";
}
echo "<br/>";
echo $query;
mysql_close($con);
?>

测试语句:%df%27

mysql的特性,因为gbk是多字节编码,两个字节代表一个汉字,所以%df和后面的\也就是%5c变成了一个汉字“運”,而’逃逸了出来。

根据gbk编码,第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以.

gb2312编码的取值范围。它的高位范围是0xA1~0xF7,低位范围是0xA1~0xFE,而\是0x5c,是不在低位范围中的。所以,0x5c根本不是gb2312中的编码,所以不会造成宽字节注入。扩展到世界上所有多字节编码,只要低位的范围中含有0x5c的编码,就可以进行宽字符注入。

宽字符注入的修复:

方案一:指定php连接mysql的字符集

mysql_set_charset('gbk',$conn);

$id =mysql_real_escape_string($_GET['id']);

方案二:将character_set_client设置为binary(二进制)

mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $conn);

将character_set_client设置成binary,就不存在宽字节或多字节的问题了,所有数据以二进制的形式传递,就能有效避免宽字符注入。

B、PHP 编码转换

示例代码:

<?php
$con = mysql_connect("localhost","root","root");
mysql_query("SET NAMES 'gbk'");
mysql_select_db("test", $con);
mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $con);
$id = isset($_GET['id']) ? addslashes($_GET['id']) : ;
$id=iconv('utf-8','gbk',$id);
$query = "SELECT * FROM users WHERE id ='{$id}' ";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>'); while($row = mysql_fetch_array($result))
{
echo $row[''] . " " . $row[''];
echo "<br />";
}
echo "<br/>";
echo $query; mysql_close($con); ?>

测试语句: 錦'

錦这个字:它的utf-8编码是%e9%8c%a6,它的gbk编码是%e5%5c

錦被iconv从utf-8转换成gbk后,变成了%e5%5c,而后面的’被addslashes变成了%5c%27,这样组合起来就是%e5%5c%5c%27,两个%5c就是\\,正好把反斜杠转义了,导致’逃逸出单引号,产生注入。

$id=iconv('gbk','utf-8',$id);  //使用%df%27来测试

一个gbk汉字2字节,utf-8汉字3字节,如果我们把gbk转换成utf-8,则php会每两个字节一转换。所以,如果\’前面的字符是奇数的话,势必会吞掉\,’逃出限制。

其他函数:

mb_convert_encoding($id,'utf-8','gbk')  //GBK To UTF-8与 iconv('gbk','utf-8',$id)一样

参考文章:

  PHP字符编码绕过漏洞总结   http://www.cnblogs.com/Safe3/archive/2008/08/22/1274095.html

  浅析白盒审计中的字符编码及SQL注入    http://www.freebuf.com/articles/web/31537.html

0x03 编码解码

找一些编码解码的函数来绕过防护,,如urldecode() 、rawurldecode()、base64_decode()

<?php
$con = mysql_connect("localhost","root","root");
mysql_select_db("test", $con);
$id = addslashes($_REQUEST['id']);
$id = urldecode($id);//$id = base64_decode($id);
$query = "SELECT * FROM users WHERE id = '{$id}'";
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>'); while($row = mysql_fetch_array($result))
{
echo $row[''] . " " . $row[''];
echo "<br />";
}
echo "<br/>";
echo $query;
mysql_close($con);
?>

测试语句:

  1'union select 1,2,3,4%23    单引号Urlencode           1%2527union select 1,2,3,4%23

  1'union select 1,2,3,4# Base64 Encode MSd1bmlvbiBzZWxlY3QgMSwyLDMsNCM=

0x04 二次注入

  入库后转义符就会消失,变成hack',查询出库的就是hack',如果拼接到SQL语句,成功引入了单引号闭合前面字符,导致注入。

测试:

   CREATE TABLE  test (user VARCHAR(20) NOT NULL);

  INSERT INTO test values('hack\'');

  

示例代码:

//测试数据
create table test(
id INT NOT NULL,
user VARCHAR(100) NOT NULL,
pass VARCHAR(100) NOT NULL
)
INSERT INTO test values(1,'hack','hack'); //测试代码
<?php
$con = mysql_connect("localhost","root","root");
mysql_select_db("test", $con);
mysql_query("SET character_set_connection=gbk, character_set_results=gbk,character_set_client=binary", $con);
//update入库
if (isset($_GET['key'])){
$key=addslashes($_REQUEST['key']);
$query ="update test set user='{$key}' where id=1";
echo "INSERT SQL: ".$query."<br/>";
$result = mysql_query($query);
}
//select 出库,并带入查询
$query = "SELECT * FROM test WHERE id = 1";
$result = mysql_query($query);
$row = mysql_fetch_row($result);
echo "<br/>";
$query = "SELECT * FROM test WHERE user = '{$row[1]}'";
print_r('SELECT SQL: '.$query.'<br/>');
$result = mysql_query($query)or die('<pre>'.mysql_error().'</pre>');;
echo "<br/>";
print_r(mysql_fetch_row($result));
mysql_close($con);
?>

测试截图:

0x05 全局防护盲点

1、str_replace函数  过滤单引号等,可能造成注入;

2、stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。stripslashes函数使用不当,可能造成注入;

①注入点类似id=1这种整型的参数就会完全无视GPC的过滤;
②注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防护;
③有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER。

①FILES注入,全局只转义掉GET、POST等传来的参数,遗漏了FILES;
②变量覆盖,危险函数:extract()、parse_str()、$$。

0X06 漏洞防护

  基本思路:输入(解决数字型注入)-------转义处理(解决字符型注入)-------输出(解决数据库报错)

1、检查输入的数据是否具有所期望的数据格式。PHP 有很多可以用于检查输入的函数,从简单的变量函数和字符类型函数(比如 is_numeric(),ctype_digit())到复杂的 Perl 兼容正则表达式函数都可以完成这个工作。如果程序等待输入一个数字,可以考虑使用 is_numeric() 来检查,或者直接使用 settype() 来转换它的类型,也可以用 sprintf() 把它格式化为数字。

2、PHP内置转义函数

Addslashes()   http://php.net/manual/zh/function.addslashes.php

magic_quote_gpc http://php.net/manual/zh/info.configuration.php#ini.magic-quotes-gpc

mysql_real_escape_string()  http://php.net/manual/zh/function.mysql-real-escape-string.php

mysql_escape_string()      http://php.net/manual/zh/function.mysql-escape-string.php

3、数据库报错信息泄露防范:

  把php.ini文件display_errors = Off

  数据库查询函数前面加一个@字符

最有效可预防SQL注入攻击的防御方式:预处理技术进行数据库查询:

代码示例:

<?php
$mysqli = new MySQLi("localhost","root","root","test");
if(!$mysqli){
die($mysqli->error);
}
$sql = "select id,username,password from users where id=?";////创建一个预定义的对象 ?占位
$mysqli_stmt = $mysqli->prepare($sql);
$id=$_REQUEST['id'];
$mysqli_stmt->bind_param("i",$id);////绑定参数
$mysqli_stmt->bind_result($id,$username,$password);////绑定结果集
$mysqli_stmt->execute();//执行
while($mysqli_stmt->fetch()){ //取出绑定的结果集
echo $id." ".$username ." ". $password;
}
echo "<br/>";
echo $sql;
$mysqli_stmt->free_result(); ////关闭结果集
$mysqli_stmt->close();
$mysqli->close();
?>

关于我:一个网络安全爱好者,致力于分享原创高质量干货,欢迎关注我的个人微信公众号:Bypass--,浏览更多精彩文章。

PHP代码审计笔记--SQL注入的更多相关文章

  1. 代码审计之SQL注入:BlueCMSv1.6 sp1

    Preface 这是一篇纪录关于BlueCMSv1.6 sp1两个SQL注入的审计过程,原文来自代码审计之SQL注入:BlueCMSv1.6 sp1 ,主要纪录一下个人在参考博文复现这两个漏洞经过. ...

  2. PHP代码审计之SQL注入

    代码审计之SQL注入 SQL注入攻击(SQLInjection),是攻击者在表单中提交精心构造的sql语句,改变原来的sql语句,如果web程序没有对提交的数据经过检查,那么就会造成sql注入攻击. ...

  3. Web安全学习笔记 SQL注入下

    Web安全学习笔记 SQL注入下 繁枝插云欣 --ICML8 SQL注入小技巧 CheatSheet 预编译 参考文章 一点心得 一.SQL注入小技巧 1. 宽字节注入 一般程序员用gbk编码做开发的 ...

  4. Web安全学习笔记 SQL注入上

    Web安全学习笔记 SQL注入上 繁枝插云欣 --ICML8 SQL注入分类 SQL注入检测 一.注入分类 1.简介 SQL注入是一种代码注入技术用于攻击数据驱动的应用程序在应用程序中,如果没有做恰当 ...

  5. Web安全学习笔记 SQL注入中

    Web安全学习笔记 SQL注入中 繁枝插云欣 --ICML8 权限提升 数据库检测 绕过技巧 一.权限提升 1. UDF提权 UDF User Defined Function,用户自定义函数 是My ...

  6. PHP代码审计 -1.SQL注入总结

    0x01 背景          最近在学习PHP代码审计,这里做一个SQL注入总结,是对自己学习知识的总结,也是为自己学习的笔记,方便自己反复翻阅. 0x02 PHP代码审计-SQL注入 挖掘SQL ...

  7. ZZZPHP1.61 代码审计-从SQL注入到Getshell

    近期有很多小伙伴在后台留言想看关于代码审计的文章,其实有关审计的文章网上资源是比较多的,但是从代码审计开始到结束的这类文章却少之甚少. 今天要讲解的ZZZPHP1.61这套审计漏洞比较多,SQL注入漏 ...

  8. [代码审计]某租车系统JAVA代码审计[前台sql注入]

    0x00 前言 艰难徘徊这么久,终于迈出第一步,畏畏缩缩是阻碍大多数人前进的绊脚石,共勉. 系统是租车系统,这个系统是Adog师傅之前发在freebuf(http://www.freebuf.com/ ...

  9. 代码审计之SQL注入及修复

    在新手入门web安全的时候,sql注入往往是最先上手的一个漏洞,它也是危害相当大的一个漏洞,存在此漏洞的话,将有被脱裤的风险. 以下所有代码都是我自己写的,可能有不美观,代码错误等等问题,希望大家可以 ...

随机推荐

  1. Navi.Soft31.WebMVC框架(含示例地址)

    1概述 1.1应用场景 互联网高速发展,互联网软件也随之越来越多,Web程序越来越被广泛使用.它部署简单,维护方便,深得众多软件公司使用 Bootstrap前端框架,是最近非常流行的框架之一.它简洁, ...

  2. 为已经存在的本地项目添加git,以及从远程仓库拉取代码并切换远程分支

    前提:先去gitlab或github网站上创建一个新项目,完毕后记得添加.ignore: 1.打开终端​,cd到已存在项目的目录 ​​​2.输入以下命令行,初始化一个本地仓库: ​git init 3 ...

  3. 100 行代码实现的 JavaScript MVC 样式框架

    介绍 使用过 JavaScript框架(如 AngularJS, Backbone 或者Ember)的人都很熟悉在UI(用户界面,前端)中mvc的工作机理.这些框架实现了MVC,使得在一个单页面中实现 ...

  4. Sword protobuf学习二

    编写protobuf消息文件 文件格式: xxx.proto //标明使用哪个版本的protobuf,默认2.0版本 syntax = "proto3"; //类似于c++中的na ...

  5. 解决jar包乱码 in 创新实训 智能自然语言交流系统

    今天用eclipse的fat jar插件,打成jar包.之后再命令行运行...程序的功能是切分大的文件...结果是切分的很正确,但是里面的中文都变成了乱码. 最开始以为是在Eclipse中的编码设置有 ...

  6. Opengl绘制我们的小屋(三)纹理绘制

    本准备先说光照相关实现,但是发现对那个模型实在看不下去了,于是先绘制纹理. 先看下基本纹理贴上去的显示效果.具体模型图请看上篇文章的实现,这篇只讲纹理实现. 我们常见的纹理绘制差不多如下,先写一个纹理 ...

  7. Maven存储库

    什么是Maven资源库? 在 Maven 术语里存储库是一个目录,即目录中保存所有项目的 jar 库,插件或任何其他项目特定文件,并可以容易由 Maven 使用. Maven库中有三种类型 local ...

  8. Maven依赖机制

    案例分析 让我们看一个案例研究,以了解它是如何工作的.假设你想使用 Log4j 作为项目的日志.这里你要做什么? 1.在传统方式 访问 http://logging.apache.org/log4j/ ...

  9. CSS3和jQuery实现的自定义美化Checkbox和Radiobox

    现在经常可以在网络上看到一些非常奇特的表单元素,例如Checkbox复选框和Radiobox单选框,浏览器默认的样式确实是太丑了,而且更让人蛋疼的是各个浏览器的样式还不统一,考虑到现在越来越多的用户使 ...

  10. 3d md5 demo

    描述:场景3dmax做的,随便拖的几个东西 模型玩过游戏的都知道是doom3的怪兽猪脚 音频是openal播放的wav文件 下载地址:http://pan.baidu.com/s/1eQ8SYI2