phpcms v9.6.0 sql注入漏洞分析

前言

作者:血魂

漏洞涉及版本

phpcms v9.6.0

漏洞涉及地址

swfupload_json函数:/phpcms/modules/attachment/attachments.php
set_cookie函数:/phpcms/libs/classes/param.class.php
sys_auth函数:/phpcms/libs/functions/global.func.php
safe_replace函数:/phpcms/libs/functions/global.func.php
wap模块接口:/phpcms/modules/wap/index.php
init函数:/phpcms/modules/content/down.php

整体思路

首先,phpcms对于一些特定参数值进行了加密处理,而加密的过程就是先传递到swfupload_json函数,进行一些处理和过滤,再传入set_cookie函数,最后传入sys_auth函数进行加密和加密结果的输出,
那么只要绕过过滤,并进行一些处理(因为整体过程中会进行一些编码的转换),就可以将危险数据传入sys_auth函数,并输出加密结果,而过滤函数safe_replace函数,因为过滤不严,可以绕过。
但是,swfupload_json函数所在的attachments类的构造函数,会判断$this->userid是否为空,当为空时会跳转到登录界面,所以我们需要一个cookie来做身份认证,不然调用不了swfupload_json函数,而这个cookie还不能是随便凑,因为会用到sys_auth函数进行解密。
而,我们知道set_cookie函数设置的cookie是通过sys_auth函数进行加密的,所以反过来通过set_cookie函数设置的cookie同样能通过sys_auth函数进行解密,所以我们需要找一个通过set_cookie函数设置cookie,并将这个cookie输出了的地方,来得到我们要用的cookie。
而,wap模块的接口,通过siteid这个参数可以得到我们想要的cookie。
然后,我们现在就能生成用危险数据产生的合法加密输出,我们最后就需要找一个用到了加密的方法来传递数据,并将数据带入数据库操作的可控参数,也就是a_k参数。
这样就产生了注入漏洞。

漏洞分析

swfupload_json.PNG
我们主要看src参数,可以看到src参数被接收后,通过safe_replace函数进行了过滤,先不管过滤函数做了什么,在经过过滤后,被代入了arr数组,然后转换了json编码,代入了
json_str变量,最后进入了set_cookie函数(在代码11,16,30行)。然后现在我们在回过头去看看safe_replace函数做了什么。
safe_replace.PNG
safe_replace函数将一些敏感词进行了替换,但是由于只检测一次,所以很容易的就被绕过了,比如’%*27’传递进safe_replace函数后先经过对%27的过滤,因为有星号不会被检测出来,然后星号被替换为空,最后输出就成了%27。绕过safe_replace函数后我们继续往下跟。
set_cookie.PNG
到了set_cookie函数,直接看最后一行代码就好,可以看见通过sys_auth函数进行了加密,ENCODE是加密,DECODE是解密,最后通过setcookie函数以cookie的形式输出。对于sys_auth函数就并不需要太深入的了解了。而我们知道swfupload_json函数是attachments类的,我们来看看attachments类的构造函数来看看调用swfupload_json函数的条件。
attachments.PNG
先不管其他代码,先看最后两行代码,可以看到检查了$this->userid是否为空,为空时执行代码showmessage(L('please_login','','member')),用到了L函数和showmessage函数,主要看showmessage函数,代码如下:
showmessage.PNG
会跳转到登录界面,也就不能调用swfupload_json函数了,那么我们再回去看构造函数的
这一行代码param::get_cookie('_userid') ? param::get_cookie('_userid') : sys_auth($_POST['userid_flash'],'DECODE'),结果一param类的get_cookie函数代码如下:
get_cookie.PNG
一眼看去,可以看到sys_auth函数,而结果二直接用sys_auth函数进行的解密,那么我们需要一个sys_auth函数能解密的cookie来绕过构造函数的限制,在刚才我们知道set_cookie函数是通过sys_auth函数进行加密的,所以反过来通过set_cookie函数设置的cookie同样能通过sys_auth函数进行解密,所以我们需要找一个通过set_cookie函数设置cookie,并将这个cookie输出了的地方,来得到我们要用的cookie。Wap模块有这么一个地方,这样的地方应该有很多。代码如下:
index.PNG
是index类的构造函数,看142,143行代码,将$this->siteid传递进了set_cookie函数,那么最后就会通过sys_auth函数加密出一个合格的cookie并以cookie的形式输出,参数名以siteid结尾,然后,我们现在就能生成用危险数据产生的合法加密输出了,然后我们需要的就是一个利用的地方,做漏洞触发点,就在init函数,因为我们不需要看init函数全部代码,就只贴出来了一小部分,代码如下:
init.PNG
在194行代码接收了a_k参数,在196行代码可以看到代入了sys_auth函数进行解密,在199行代码可以看到代入了parse_str函数处理,parse_str函数会依据&将传入值分割,然后解析到具体变量并注册变量,还会对内容进行url解码操作。然后我们在208行代码看到进入了数据库操作,而那个id变量就是parse_str函数注册的变量。
到此,整个漏洞分析完了。

poc

poc.PNG

执行效果

test.PNG

添加新评论