前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >代码审计(二)——SQL注入代码

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

作者头像
黑伞安全
发布2022-01-26 14:01:32
6.9K0
发布2022-01-26 14:01:32
举报
文章被收录于专栏:黑伞安全

什么是SQL注入

01

SQL注入原理

当访问动态网页时,以MVC框架为例,浏览器提交查询到控制器(①),如是动态请求,控制器将对应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注入。

代码语言:javascript
复制
$id = $_GET['id'];   
$query = "select username,password from user where id=$id";

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

代码语言:javascript
复制
输入:1 or 1=1
“select username,password from user where id=1 or 1=1”          

●字符型SQL注入

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

代码语言:javascript
复制
$id = $_GET['id'];
$query = "select username,password from user where id='$id'";

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

代码语言:javascript
复制
输入:1' or 1=1 --
"select username,password from user where id='1' or 1=1 -- "        

b. 编码注入

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

●宽字节注入

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

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

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

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

代码语言:javascript
复制
' --> \' --> %5C%27

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

代码语言:javascript
复制
%df '--> %df \ ' --> %df%5c%27

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

代码语言:javascript
复制
%df '--> %df \ ' --> %df%5c%27--(GBK)-->運'

● 二次URLdecode注入

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

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

如果我们构建一个输入:

代码语言:javascript
复制
%27--(php编码)-->%2527-->%2527
php第一次解码
%2527-->%27
URLdecode二次解码,成功注入'
%27-->'

审计方法

01

敏感函数回溯法

a. 审计流程:

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)

①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查询

②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注入

③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语句并返回受影响的行数

02

功能点定向审计

a. 审计流程

b.审计重点功能点

功能

出现漏洞类型

文件上传功能

任意文件上传

查询/文章功能

SQL注入

密码找回功能

逻辑漏洞

登陆认证功能

SQL注入,逻辑漏洞

评论功能

XSS漏洞

……

……

SQL注入审计方法总结

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

代码语言:javascript
复制
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. 功能点寻找输入参数

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

审计实例

01

实验准备

CMS:MetInfo 6.0.0

Php:5.4

Mysql:5.4

02

分析过程

1.定位函数

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

代码语言:javascript
复制
(update|select|insert|delete|).*?where.*=\{
  1. 根据代码上下文审计是否存在漏洞。

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

代码语言:javascript
复制
$query="select * from {$_M[table][feedback]} where id={$_M[form][id]}";

id直接拼接变量名

代码语言:javascript
复制
$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]是经过过滤的数组。

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

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

03

实验验证

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

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

Sleep()时间注入

代码语言:javascript
复制
?n=feedback&c=feedback_admin&a=dosentemail&id=1 and sleep(5)

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

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

待续

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑伞攻防实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档