审计环境
PHP7.0
Apache
PHPSTORM
这里需要注意的是
dedecms在php5.4以上会因为session_register()等函数已移除,无法正常运行
在include/userlogin.class.php中代码替换,被替换代码大致在288到304行之间,代码如下:
代码如下:
1 | @session_register($this->keepUserIDTag); |
替换为如下代码:
1 | $_SESSION[$this->keepUserIDTag] = $this->keepUserIDTag; |
364到368替换如下:
1 | unset($this->keepUserIDTag); |
cookie伪造导致任意前台用户登录
漏洞分析
跟进
PutCookie
方法,在该方法中的第27行中将值与配置文件中的$cfg_cookie_encode
进行拼接,然后进行MD5和截断处理substr(md5($cfg_cookie_encode.$value),0,16)
,然后下发到客户端而在
include/common.inc.php
使用的外部变量注册的方法进行变量声明,因此此处的$uid是用户可控的。这里我们就可以获取到任意用户的
last_vid
last_vid__ckMd5
而在文件
include/helpers/cookie.helper.php
中的第54-72行的GetCookie方法的代码块,其中第63行用于校验客户端cookie是否进行了伪造,因此要进行cookie就自然想到要获取uploads/data/config.cache.inc.php
文件中的内容,需要存在任意文件读取或下载的漏洞,当然还有另外一种方式,就是控制$uid
,利用PutCookie直接生成cookie,这样的cookie定会通过GetCookie方法。
接着查看登录相关的代码,看它的cookie生成方法是否是PutCookie。在include/memberlogin.class.php
498行PutLoginInfo方法处理正确输入用户名和密码的情况
继续跟进PutLoginInfo方法,果然用的是PutCookie方法,存在cookie伪造漏洞
在文件include/memberlogin.class.php
的第160-242行发现代码块,其中第170行检测cookie中的DedeUserID参数的值,178行将这个值转换为整数,185行通过这个给值来查询用户。我们通过伪造DedeUserID即可任意用户登录了。
漏洞复现
情况一:
由于mid在数据库中是int,所以要进行cookie的伪造需要注册用户名为要越权的用户mid数值,而admin默认为1。因此可以直接登录为admin。
需要注册用户名为对应数据库中dede_member表中mid对应的值。如注册用户名为0001对应dede_member表中mid为1,便是admin的mid。
然后访问/member/index.php?uid=0001
获取伪造的cookie
最后访问/member/index.php
并带上cookie即可
情况二:
在member/index.php
文件第124行,当uid不为空时会require_once(DEDEMEMBER.'/inc/config_space.php')
跟进member/inc/config_space.php
在第29行调用了GetUserSpaceInfos方法
跟进GetUserSpaceInfos方法,其SQL查询语句使用了like
获取数据,通过构造特殊的用户名即可让其下发伪造cookie
这里我们假设要登录mid为5的用户
我们先注册类似于xx5xx
的用户
然后访问/member/index.php?uid=%5%
获取伪造cookie
加上cookie访问/member/index.php
任意修改前台用户密码
漏洞分析
在
member/resetpassword.php
75-99行,进行安全问题的判断。默认$row['safequestion']
在数据库的内容为'0'
,$row['safeanswer']
在数据库中的结果为''
,且变量$safeanswer
与$safequestion
是用户可控制的变量,又使用了 ==进行判断, 因此该判断规则存在弱类型问题。如果用户在注册时设置了密保问题则没有这个问题这里打印下$row
对于
$safeanswer
我们不传值,经过85行处理也会为空,从而相等。对于
$safequestion
我们需要传一个值使其绕过empyt()
且等于‘0’
。根据手册,我们可以构造出
1
2
3
4
50.0(作为字符串)
0x0
0e0
0e1
...
漏洞复现
先进行如下请求获取key
/member/resetpassword.php?dopost=safequestion&safequestion=0x0&safeanswer=&id=2
任意重置后台用户密码
漏洞分析
在
member/edit_baseinfo.php
118-123行修改前端密码同时也会修改后端密码
前台任意文件删除
漏洞分析
问题出在
member/inc/inc_batchup.php
的DelArc
方法,对于$licp['litpic']
直接拼接在目录后面只检测文件存不存在,没有检查文件类型就直接删除。重点在于这个litpic
我们是否可控接着全局搜索了
litpic
变量,发现member/inc/archives_check_edit.php
发现79-93行可以通过控制$oldlitpic
来litpic
。在$litpic
为空的情况下,$litpic=$oldlitpic
。接着全局搜索
archives_check_edit
也就是这四个功能受影响
而在上传图集的功能里,同样可控
litpic
在member/album_add.php
88-103行,在$formhtml==1 && $ddisfirst==1 && $litpic=='' && !empty($litpicname)
下$litpic==$litpicname
$formhtml
可传参控制,$ddisfirst
默认为1,至于$litpic
我们跟进archives_check.php
,在100-102行跟进
MemberUploads
方法,在include/helpers/upload.helper.php
118-240行,其中215-222行是关键在不上传缩略图的情况下会进入else分支,同时MemberUploads
的handname
参数默认为空。即返回值也为空。所以$litpic
可控最后全局搜索
DelArc
函数查找触发点,在member/archives_do.php
,有个issystem
的判断数据库查询一下,默认情况下出了
infos
其他都会调用DelArc
删除文件。漏洞复现
情况一:
以文章为例
先发表文章,内容随意填
再修改文章同时加上
oldlitpic
的值数据库:
最后删除文章即可删除
oldlitpic
指向的文件。情况二:
上传图集时添加
formhtml
和litpicname
即可删除图集
前台任意文件上传
漏洞分析
上传需要admin权限,有点鸡肋。但配合之前的cookie伪造也还行。
问题在
include/dialog/select_images_post.php
对于后缀的处理逻辑有问题。在36行获取文件名,然后过滤。这个文件名就是我们上传的文件名,具体的调用是
1
select_images_post.php -> config.php -> common.inc.php -> uploadsafe.inc.php
接着在58到64行进行后缀拼接和上传。直接通过
.
来分割文件名,将最后一个后缀作为文件后缀。通过构造类似
1
2
3
4
5p%hp
p*hp
p<hp
p?hp
...即可绕过上传。
漏洞利用
后台文件写入
漏洞分析
又是需要后台admin权限,太鸡肋了。DedeCMS后台本来就带有文件管理器,本着学习的态度就记录一下。
问题出在
dede/sys_verifies.php
,fwrite
的参数未经过过滤,导致文件写入,配合require_once
getshell
漏洞复现
访问
/dede/sys_verifies.php?action=getfiles&refiles[]=\";eval($_GET[a]);die();//
写入文件访问
/dede/sys_verifies.php?action=down&a=phpinfo();
执行命令
后台二次注入getshell
漏洞分析
在
dede/ad_add.php
80-83行,参数$normbody
未经过滤就放入数据库中而在
plus/ad_js.php
21-44行,查询结果直接包含。复现漏洞