某cms的sql注入漏洞分析

一.前言 某开源商城是基于thinkphp3.2.3,此商城中的sql注入漏洞很多,这篇文章主要举几个比较典型的例子,讲讲对漏洞的分析和自己审计代码时的一些思路。 二.代码审计 0x00.请求过程 ThinkPHP...

一.前言

某开源商城是基于thinkphp3.2.3,此商城中的sql注入漏洞很多,这篇文章主要举几个比较典型的例子,讲讲对漏洞的分析和自己审计代码时的一些思路。

二.代码审计

0x00.请求过程

ThinkPHP的控制器是一个类,而操作则是控制器类的一个公共方法。

控制器类的命名方式:控制器名(驼峰命名法)+Controller

控制器文件的命名方式:类名+.class.php(类文件后缀)

首先通过getControllergetAction两个方法定义CONTROLLER_NAMEACTION_NAME的值

image-20230511173121317

然后通过CONTROLLER_NAME获取当前操作名

image-20230511173341658

然后通过ACTION_NAME获取类所在的路径并创建控制器实例

image-20230511173637375

然后通过反射方法ReflectionMethod获取这个对象下对应的方法, 并且后续没有进行权限判断,导致所有请求都可以通过未授权访问

image-20230511172521716

最后执行对应的应用程序

image-20230511174924625

0x01.sql注入漏洞1

Modules/Home/Controller/ApiuserController.class.php文件中的group_info方法

image-20230426152942973

$order_id通过get请求传入,接着直接拼接进sql语句中,由于没有对参数进行过滤,并且没有对传入的token参数进行校验,直接拼接sql语句进行未授权执行。

漏洞复现:

payload:

http://127.0.0.1/index.php?s=/Apiuser/group\_info&order\_id=1%20and%20updatexml(1,concat(0x7e,database(),0x7e),1

image-20230426153242419

0x02.sql注入漏洞2

Modules/Home/Controller/VipcardController.class.php文件中的get_vipgoods_list方法

image-20230426153721428

order_id通过get请求传入,然后拼接到where语句中,由于是字符串,$this->options['where']的键就是_string

image-20230427150146495

所以导致不会进入到下面的if判断语句中,_parseType方法用来检测传入的类型,由于传入的字符串类型,所以也就不会去判断是否符合字段数据类型

image-20230427150720492

最终拼接成sql语句进行执行

image-20230426160351858

还有注意一点的是,非array传出的参数会被添加(),所以有时候无法闭合的时候可以尝试添加括号看看

漏洞复现

payload:

http://127.0.0.1/index.php?s=Vipcard/get\_vipgoods\_list&gid=1 and updatexml(1,concat(0x7e,database(),0x7e),1)

image-20230427114410368

0x03.sql注入漏洞3

Modules/Home/Controller/ApiuserController.class.php中的set_default_address方法

image-20230427160741552

然后跟进wheresave方法,然后在save方法中跟进_parseOptions方法

image-20230427162110263

_parseOptions方法中,由于这里$val是一个数组,所以is_scalar判断不是标量,也就不会进入_parseType方法用来检测传入的类型

image-20230427152713737

在where子单元分析函数parseWhereItem中,$exp去了array中的第一个值bind,然后在下面的判断语句中拼接$whereStr

image-20230427154802743

最后形成下面的sql语句,但此时的sql语句中任存在:0

image-20230427155145586

execute中,是将:0替换为外部传进来的字符串,所以我们让我们的参数也等于0,这样就拼接了一个:0,然后会通过strtr()被替换为1

image-20230427161521183

漏洞复现

payload:

[http://127.0.0.1/index.php?s=Apiuser/set\_default\_address&id\[0\]=bind&id\[1\]=0%20and%20(updatexml(1,concat(0x7e,user(),0x7e),1](http://127.0.0.1/index.php?s=Apiuser/set%5C_default%5C_address&id%5C%5B0%5C%5D=bind&id%5C%5B1%5C%5D=0%20and%20(updatexml(1,concat(0x7e,user(),0x7e),1)))

image-20230427162255830

三.tp框架下SQL注入漏洞挖掘思路总结

tp框架采用MVC架构,即模型(Model),视图(View),控制器(Controller)。他们大致的运行流程是用户与应用程序交互,向控制器发送请求,然后控制器收到请求分析用户请求,并调用响应的模型操作,模型操作访问数据库或其他数据源,对数据进行处理并返回给控制器控制器接受模型返回的数据,并传递给视图,最后视图将数据呈现给用户。

在MVC架构下对于挖掘sql注入漏洞应该首先关注其模型,因为他是与数据库交互的地方,如果我们能发现其过滤不严导致直接将用户数据带入数据库中执行从而造成sql注入。

1.使用QUERY方法对原生的SQL查询和执行操作

示例代码:

$gid \= $_GPC['gid'];
$sql \= "select xxx from xxx where gid='$id';"
$result \= M()->query($sql);

这种写法如果不对传入的gid变量加以过滤,很容易造成sql注入。

我们可以通过正则M\(.*?\)->query\(.+?\)搜索代码中使用query方法的代码,然后查看传入的参数是否可控.

image-20230426163555537

2.使用字符串作为查询条件

示例代码:

$gid \= $_GPC['gid'];
$resultt \= M('xxx')->where( "pid = {$gid}" )->select();

我们可以通过正则M\(.*?\)->where\(((?!array).)*\)搜索代码中使用where方法且不是通过array传参的代码,然后查看传入的参数是否可控.

image-20230427165636705

3.使用数组作为查询条件

示例代码:

$gid \= $_GPC['gid'];
$resultt \= M('xxx')->where( array('gid' \=> $gid) )->save();

当使用数据进行传参情况就不一样了

如果传参是通过array的话,进入到下面的if判断语句中,会对传入值的类型进行判断,若判断为int类型,参数将直接传唤为int类型将丢失后面的payload,

image-20230427151141569

image-20230427145520525

就算传入的类型可以为字符型也还会对传入的参数关键字符进行转义

所以这里我们只能另辟蹊径,只能通过tp3.2.3框架的几个sql注入漏洞来利用

例如这里我们可以使用tp3.2.3框架的bind注入,漏洞所在的地方一般都需要update的操作

我们可以通过正则M\(.*?\)->where\(.+?\).>save\(.+?\)搜索代码中使用where方法且不是通过array传参的代码,然后查看传入的参数是否可控.

image-20230427163129100

另外tp3.2.3中还可以通过exp注入,原理和上面的bind注入差不多,但其条件参数必须是通过全局数组传参,而不是I()函数,因为I()函数会调用think_filter()函数,其中过滤了exp。在这一套cms中所有参数都是通过I()函数传参的,所以无法使用exp注入。

  • 发表于 2023-05-30 09:00:00
  • 阅读 ( 6851 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
中铁13层打工人
中铁13层打工人

79 篇文章

站长统计