8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png
Metinfo6.0.0-6.1.2前台注入漏洞生命线
aiyun 2018-11-19

前言

这个前台注入漏洞存在已久,从MetInfo发布的6.0版本就存在,且后来官方的修复代码,也可以直接绕过。笔者于7月份提交了当时最新 MetInfo 6.1.0版本SQL注入漏洞,该漏洞直到6.1.3版本才被修复。如下漏洞分析,权当思路分享。

1

漏洞分析

2018-1-29, MetInfo官方重写后台及前台代码,并发布了MetInfo6.0。然而这一新版代码,却存在一个严重的前台SQL注入漏洞,我们来看一下具体详情。

首先漏洞存在于app\system\message\web\message.class.php文件中,变量{$_M[form][id]} 直接拼接在SQL语句中,且验证码检测函数是在SQL语句查询之后,这也就造成了我们可以无视验证码检测函数,进行SQL注入。具体问题函数代码如下:

2

那么实际上,开发者是有考虑到SQL注入问题,并写了sqlinsert 来检测SQL注入攻击的,甚至还对{$_M[form][id]}进行了is_numeric判断处理,但是为什么最终还是存在SQL注入呢?下面我们具体来看看 {$_M[form][id]}    变量的获取过程。

想要触发这个SQL注入漏洞,我们可以通过前台的在线留言在线反馈两个功能来触发。我们这里先分析在线留言处的程序逻辑。我们填写留言处的表单,并在最下方添加上id字段,其值对应我们的攻击payload,具体如下:(为了避免图片太长,我把一些参数的值给略去)

3

然后我们在message\index.php文件中打下断点,会发现在app\system\include\class\common.class.php的构造方法中,加载了表单,具体的调用链即代码如下:

4

此时this对象指的是web类,我们继续跟进web类的load_form方法。

5

我们会发现common基类的load_form方法将GETPOSTCOOKIE获取的所有数据存放在$_M['form']中,数据仅用daddslashes函数处理。而web类的load_form方法重写了common类的load_form方法,对$_M['form']中的所有数据进行了sqlinsert处理,并且在后面判断$_M['form']['id']是否为数字,如果不是数字就直接设置为空字符串。这些过滤函数具体代码如下:

6

7

可以看到sqlinsert函数对sleep关键字进行了处理,但是我们还是可以使用MYSQL中的benchmark函数轻松绕过(这两个函数都能利用在时间盲注中,具体可以参考:https://xz.aliyun.com/t/2288)。但是我们的payload却绕不过is_numeric函数,所以此时的$_M['form']['id']会被设置成空字符串。那为什么还存在SQL攻击呢?我们接着看程序逻辑。

在跟进程序的过程中,我们会发现在执行完load::sys_class(‘upfile’, ‘new’)代码后,$_M['form']['id']的值又变成了我们传入的payload,这说明这里面一定是又重新进行了表单赋值。

8

果不其然,程序中加载的upfile类又重新载入了$_M['form']的值,而且并没有进行除了基类中daddslashes方法以外的消毒处理,这也是造成SQL注入的原因。

9

我们可以根据上面的漏洞原理,轻松的写出攻击脚本:

10

接着,我们再来对比一下5月份的修复代码,此时MetInfo官方并没有更新版本号,而是偷偷修复了代码,修复代码如下右图:

11

可以清晰的看见daddslashes方法开始对每个参数进行sqlinsert处理。而上面我们说过,这个消毒函数是可以绕过的,所以我们依然可以进行SQL注入。

虽然可以进行盲注,但是还是太耗费时间了,我们是否有办法将其转换成布尔盲注呢?答案是可以的,接下来我们就来看看,如何将这一处时间盲注变成布尔盲注。

app\system\message\web\message.class.php文件中,我们会发现如果SQL语句查询结果中的value字段非空,则会进行验证码的检测,否则会直接返回反馈已经被关闭

12

13

这样子,我们就可以根据不同的返回结果,进行布尔盲注。现在我们来看一下如何找到满足查询结果中的value字段非空的columnid,直接在MYSQL中做如下查询:

14

15

这样子我们就找到了两个可用的columnid最终我们同样可以写出攻击脚本,如下:

16

我们再来看另一处注入点,前面我们分析的是在线留言处的SQL注入问题,这次我们要分析在线反馈处的SQL注入,漏洞的成因都是类似的。不过在利用这个漏洞时,我们需要经过feedbackcheck_field方法的检测。

17

这里实际上可用的id有两个,如下:

18

例如这里我想利用id=71,那么需要构造如下数据包,才会进入漏洞触发处。

19

现在绕过了check_field方法的检测,我们就顺利来到了触发SQL注入漏洞的feedback累的add方法,其位置在app\system\feedback\web\feedback.class.php,具体代码如下:

20

我们会发现这次的验证码校验,位置在注入点前面,所以利用起来比较麻烦。这里我们可以使用爆破验证码结合时间盲注的方式进行攻击,用以下程序生成全排列验证码字典:

from itertools import product
rand_chrs="A2B3C4D5E6F7G8H9iJKLMNPQRSTUVWXYZ"with open("codes.txt",'w') as f:    for code in product(rand_chrs,rand_chrs,rand_chrs,rand_chrs):
        code = ''.join(list(code))
        print(code)
        f.write(code+'\n')

21

但是这样的攻击成本还是太高了,如果大家会机器学习,可以加入相关算法来自动识别验证码。

最后我们来看一下MetInfo 6.1.3最新版的修复情况如何,具体情况如下DIFF图:

22

结语

文章中提到的这个漏洞点,实际上也可以从其他入口点进行触发,之前也已经有师傅放出分析文章,漏洞的成因都是一样的,具体可以参阅文末的相关文章,这里不再赘述。本文分析到此结束,如有不当还望各位斧正。另外,我们团队正在招收代码审计成员,如果您在这方面有丰富的经验,欢迎加入我们。(可以发邮件至:[email protected])。对代码审计感兴趣的朋友,也可以关注我们的代码审计项目:PHP-Audit-Labs

相关文章

Metinfo 6.1.2 SQL注入

[代码审计]METINFO 6.1.2 SQL注入

最新回复 (0)
    • Ai云
      2
        立即登录 立即注册
返回