vlambda博客
学习文章列表

代码审计(二)——SQL注入代码

代码审计第二课来啦,🚗滴滴滴!快快上车吧!



什么是SQL注入



01

SQL注入原理

当访问动态网页时,以MVC框架为例,浏览器提交查询到控制器(①),如是动态请求,控制器将对应sql查询送到对应模型(②),由模型和数据库交互得到查询结果返回给控制器(③),最后返回给浏览器(④)。


代码审计(二)——SQL注入代码


现行的网页、程序多是基于以上这样的设计模式。正常情况下,这种网站内部直接发送的SQL请求不会有危险,但实际情况是很多时候需要结合用户的输入数据动态构造 SQL语句,如果用户输入的数据被构造成恶意 SQL 代码,Web 应用又未对动态构造的 SQL语句使用的参数进行审查,则会造成一种很常见的漏洞——SQL注入

SQL注入是现在最常见最简单的漏洞,SQL注入就是通过把恶意SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令的目的。简单一点说就是将原本输入的查询变量的地方插入了SQL查询语句,破坏原SQL语句从而来实现自己的SQL查询。

SQL注入与其他常见Web漏洞一样,均是由外部可控的参数引起的。由于程序没有经过任何过滤就将外部可控的参数拼接进入SQL语句,直接放入数据库执行,达到了欺骗服务器执行黑客恶意SQL命令的目的。


02

SQL注入带来的威胁

  • 数据库信息泄露,SQL注入会导致数据库中存放的用户隐私信息,网站敏感信息被盗取。

  • 数据库被恶意篡改,攻击者可以通过修改数据库中的值进而修改系统管理员的账户,控制数据库。

  • 服务器被远程控制,被安装后门。经由数据库服务器提供的操作系统支持,让黑客得以修改或控制操作系统。

  • 注入可以借助数据库的存储过程进行提权等操作。


03

SQL注入形式

SQL注入可以简单分为普通注入和编码注入两种。

a. 普通注入

●数字型SQL注入

当程序的变量没有做处理而直接拼接在SQL注入语句中,没有单引号的保护,就容易造成SQL注入。

$id = $_GET['id'];   
$query = "select username,password from user where id=$id";

攻击者可通过构造以下输入来达到SQL注入

输入:1 or 1=1
“select username,password from user where id=1 or 1=1”          



●字符型SQL注入

当程序的变量没有做处理而直接拼接在SQL注入语句中,虽然有单引号的保护,但我们如果能闭合SQL,也就产生了SQL注入漏洞。

$id = $_GET['id'];
$query = "select username,password from user where id='$id'";

攻击者可通过构造以下输入来达到SQL注入

输入:1' or 1=1 --
"select username,password from user where id='1' or 1=1 -- "        

代码审计(二)——SQL注入代码


b. 编码注入

编码注入包括宽字节注入、URLdecode注入等,利用程序的编码规则缺陷,输入与转码函数不兼容的特殊字符,导致输入的字符拼接成为了恶意的SQL语句。

●宽字节注入

宽字节注入是利用mysql的特性,即不同编码方式造成的转换错误。例如 PHP的编码方式为UTF-8,而 mysql的被设置了使用GBK编码时,由于mysql在使用GBK编码的时候,会产生宽字节自主漏洞,即将两个ascii字符误认为是一个宽字节字符(如汉字)。

假设网站对输入使用addshlashes()函数,即对GET、POST、COOKIE、REQUSET 提交的参数中的单引号(')、双引号(")、反斜杠(\)与 NUL(NULL 字符)会有以下转义操作:

单引号(')= (\')
双引号(") = (\")
反斜杠(\) = (\\)

这时输入'时网页的处理将会是:

' --> \' --> %5C%27

当在前面引入一个ASCII大于128的字符(比如%df),url编码变为:

%df '--> %df \ ' --> %df%5c%27

若MYSQL使用gbk编码的话,%df%5C会被当作一个汉字处理,从而使%27(单引号)成功绕过

%df '--> %df \ ' --> %df%5c%27--(GBK)-->運'

代码审计(二)——SQL注入代码

● 二次URLdecode注入

二次URLdecode注入即对用户提交的变量进行二次URL解码而导致的SQL注入。现在绝大多数基于PHP的Web程序都会使用addslashes()等过滤函数对用户提交的变量等进行过滤,如果某处同时又采用了urldecode()函数进行了url解码,那么将会大概率的导致URLdecode注入。

PHP本身在处理提交的数据之前会进行一次解码,而urldecode()函数是相对应地对已编码的URL进行解码。

如果我们构建一个输入:

%27--(php编码)-->%2527-->%2527

php第一次解码

%2527-->%27

URLdecode二次解码,成功注入'

%27-->'

代码审计(二)——SQL注入代码
代码审计(二)——SQL注入代码



代码审计(二)——SQL注入代码

审计方法


01

敏感函数回溯法

a. 审计流程:

代码审计(二)——SQL注入代码

b. 审计重点函数

函数类型 举例函数或敏感关键词
SQL操作类 Select……, mysql_query…
文件操作类 Move_uploaded_file,copy,/upload/等
命令执行类 System,popen等常见的系统命令做关键词
代码执行类 eval,preg_replace等
引起XSS类 echo等
…… ……

下面重点列出在PHP中可能设计SQL注入的相关函数。


c. PHP中常见的数据库扩展

Mysql,Mysqli extension, PDO(Php Data Objects)


代码审计(二)——SQL注入代码

①mysql扩展:

从PHP5.5.0起此扩展已被废弃,并且从PHP7.0.0开始被废除,使用mysqli或者pdo-mysql进行替代。

mysql常用函数:

Mysql_connect
连接数据库
Mysql_query
执行SQL语句
Mysql_fetch_array/mysql_fetch_assoc
返回从结果集取得的行生成的数组
Mysql_db_query
发送一条mysql查询


代码审计(二)——SQL注入代码

②Mysqli扩展:

mysqli扩展允许我们访问mysql4.1及以上版本提供的功能,是目前PHP开发中常用的数据库操作扩展之一。

mysqli常用函数:

Mysqli(hostname,username,password,db_name)
实例化mysqli对象
Mysqli::connect_error
检测连接是否成功
mysqli::query
执行SQL查询
Mysqli::result::fetch_assoc/mysqli_result::fetch_array
返回从结果集取得的行生产的数组
Mysqli::prepare
预编译 防止SQL注入



代码审计(二)——SQL注入代码

③PDO扩展:

PHP数据对象(PDO)扩展为PHP访问数据库定义了一个轻量级的一致接口。

PDO提供了一个数据访问抽象层,即不管是用那种数据库,都可以用相同的函数(方法)来查询和获取数据。

P DO随PHP5.1发行,在PHP5.0中的PECL扩展中也可以使用,无法运行于之前的PHP版本。PDO扩展也为开发者经常使用的扩展,例如thinkphp框架就是使用的PDO扩展。

PDO常用函数:

PDO(dsn,username,password) 
数据库连接
PDO::query
执行SQL语句
PDO::statement::fetch/fetchAll
取出结果集中数据
PDO::prepare
预处理
PDO::statement::execute
执行预处理语句
PHD::exec
执行一条SQL语句并返回受影响的行数    
代码审计(二)——SQL注入代码



02

功能点定向审计

a. 审计流程

代码审计(二)——SQL注入代码

b.审计重点功能点

功能 出现漏洞类型
文件上传功能 任意文件上传
查询/文章功能 SQL注入
密码找回功能 逻辑漏洞
登陆认证功能 SQL注入,逻辑漏洞
评论功能 XSS漏洞
…… ……

代码审计(二)——SQL注入代码



代码审计(二)——SQL注入代码

SQL注入审计方法总结


1. 快速定位函数,关键字如下:

Function:
query
fetch_assoc
select|update|delete|insert|mysql_query|mysql_db_query|
query|execute|exec|get_one
Mysql_query
Mysql_fetch_assoc

Wide:
mysql_query
mysql_set_charset
mysqli_set_charset
iconv("GBK","UTF-8")

2. 正则快速查询

通过一些查询语句的特征,用正则匹配源代码中的SQL语句所在位置

3. 辅助工具

使用Seay源代码审计系统的自动审计功能来辅助我们快速找到SQL注入可能存在的位置。

4. 功能点寻找输入参数

在前段页面中查找各种功能点是否存在可控输入参数,例如文章、用户资料、登陆处等等。



代码审计(二)——SQL注入代码

审计实例


01

实验准备

CMS:MetInfo 6.0.0

Php:5.4

Mysql:5.4


02

分析过程

1.定位函数

使用phpstorm中的ctrl + shift + F 选择Regex正则搜索,快速定位敏感函数

(update|select|insert|delete|).*?where.*=\{

代码审计(二)——SQL注入代码

  1. 根据代码上下文审计是否存在漏洞。

下图中,id参数直接进行了拼接,有可能存在SQL注入的,这里是两处sql执行操作一处是select,一处是update。

代码审计(二)——SQL注入代码

$query="select * from {$_M[table][feedback]} where id={$_M[form][id]}";

id直接拼接变量名

$query="update {$_M[table][feedback]} set useinfo='$useinfo' where id={$_M[form][id]}";

只对$useinfo变量做了单引号的包裹,对$_M[form][id]没有包裹处理。

  1. 追溯参数,寻找参数$_M[form][id]是如何传递而来的。

通过MetInfo官方文档可知$_M[form][id]是通过GET,POST,COOKIE 提交而来,且文档中说$_M[form][id]是经过过滤的数组。

代码审计(二)——SQL注入代码

看一下对$_M[form][id]的过滤处理,发现只是对其进行了addslashes转义

代码审计(二)——SQL注入代码

结合使用来看对$_M[form][id]的处理,发现虽然对传入的参数进行了过滤但是此处的SQL语句是直接拼接了参数并没有‘’或者“”的包裹,所以$_M[form][id]存在数字型注入,而用于防范字符型注入的过滤函数addslashes失效。


03

实验验证

尝试注入,根据dosentemail函数所在的文件夹来构造:

n: 目录      c: controller     a: action     id:通过get传递的参数

Sleep()时间注入

?n=feedback&c=feedback_admin&a=dosentemail&id=1 and sleep(5)

代码审计(二)——SQL注入代码

页面延时5s,注入成功。



代码审计(二)——SQL注入代码
代码审计(二)——SQL注入代码

有关SQL注入的代码审计的内容到此就告一段落了,下一课将给大家带来更多漏洞的代码审计讲解,敬请期待~



待续