tp框架I函数与whereparse审计小记

经过初步的分析,在tp框架上,做登陆认证的形式:

首先从动态参数获取来看:

TP自带了一个I函数,用于获取用户传的动态参数

这一点之前做过tp相关项目的开发,也用过I函数,知道这个函数有一定抵抗攻击的能力,但是没有仔细审计过这个函数。

I函数定义在/ThinkPHP/Common/functions.php里

首先先对开发者写在里面的数据类型/method进行判断,

然后是对传入的数据进行处理,$filter是开发者所控的,用来对获取到的参数进行处理,比

如可以使用htmlspecialchars进行实体化

当然,如果开发者没有输入filter,就会有个默认的filter

然后是依据上面获得的数据类型进行强制类型转换

最后,如果输入是数组,就会进行

我们看一下think_filter

如果数组某个值等于如上某个关键词,就会在关键词后面加空格

也就是说,tp框架下开发者要获取用户认证所需的用户名密码,

一般分为

  1. I函数获取。
  2. 直接$_POST[]或$_REQUEST[]获取

然后从数据查询的角度看

首先翻一下文档,查询的方式有这么多

大多数开发者使用tp原生的数据查询方式

即 M/D()->where(…)……->find()/select()

我们可以发现传入where的是一个条件数组,那where又是如何解析的呢?

可跟到/Db/Driver.class.php

前面都是对_logic的处理,属于开发者可控,用户不可控的

这里也是开发者可控的部分

关键点:

这个分支前面只做了

直接把$val带入parseWhereItem

这里对应着表达式查询

检查了$val[0]是否是字符串,是的进入正则检验,如果是eq|neq|gt|egt|lt|elt中的某一个

$whereStr .= $key.' '.$this->exp[$exp].' '.$this->parseValue($val[1]);

看一下parseValue

值得注意的有

还有

接着回去看parseWhereItem

notlike|like分支

都进行了parseValue操作

接下来是bind exp

可以看到直接拼接进去了,没有做escapestring

后面的notin|not in|in分支

如果$val[2]即username[2]是exp的话也是直接进行拼接

否则是要parseValue的

notbetween|not between|between分支

也是进行parseValue操作的

整个表达式查询已经结束

接下来是where 后面的拼接、字段模糊匹配

最后直接带入sql语句

到这里,可想的利用点有:

  1. 刚才提到了I()最后一个filter的处理,正是防范这些表达式查询,如果不用I()来获取数据,就可能会发生危险,结合刚才分析的where的操作

发生的危险大概如下:

 

首先是注入问题

我们看到 这些表达式大多数都加了escapestring,而拼接到sql语句中又都加了引号,所以这里引号逃逸就很困难,但是注意到exp和bind表达式没有做escapestring处理

测试一下

成功,而且本身也没有什么引号的束缚

可以进行注入

如果有些开发者机制的检查并拦截数组【0】上为exp怎么办?

刚才审计in/not in那个分支的时候可以发现,会检查数组第三个值是否为exp,如果是exp则直接拼接

如下

另一个问题就是既然表达式可控,那我们就干脆别想着注入了,直接利用表达式达成自己的目的,例如登陆验证,其实只是一个验证,我们只要构造一个万能密码就好。

其实这种东西比较像mongo注入,应该也是有一定的利用场景的。

那如果开发者用了I函数会怎样?

我们看到,I函数把每个关键字后面都加了空格,这样导致在parseWhereItem的时候正则匹配不到关键词,而且就仅仅因为一个尾空格,而I函数又是先进行trim处理,后进行filter的,所以感觉不可利用,具体的还要具体审计一遍再说。

  • 用支付宝打我
  • 用微信打我

发表评论

电子邮件地址不会被公开。 必填项已用*标注