PHP代码审计-dedecms

此篇文章主要记录了dedecms的漏洞分析和复现,便于进一步学习代码审计的知识。

一、 环境搭建:

框架介绍:

此项目为dede自研系统,其中所有功能点都由dede自开发,访问对应PHP文件即可找到对应功能点。

二、代码审计

1.任意文件写入

通过搜索 fwrite() 函数,发现这里存在可疑写入点,而我们知道得知dede的路由可以通过直接访问。


这个数组是怎么传入的。

直接访问该文件发现如下功能点,而这里的验证码设置功能处正是传入参数的地方
这里抓包看到此处参数可控的地方在代码的中是存在过滤的,但是我们发现可以进行绕过。

我们在看一下要写入的文件内容

漏洞复现:

2.目录遍历

全局搜索 read() 函数,发现存在参数可控的地方,接着我们进入 select_images.php 文件。

漏洞复现:

3.数据库操作getshell

在测试功能点模块管理时,发现一处可以操作数据库的地方,我们点击修改。
其实我们可以直接在删除程序处输入我们想要执行的SQL语句进行测试
这里传入了两个参数 action 以及 hash。

这里通过uninstall执行该处分支,然后通过上面传入的hash参数值来定位文件, GetFileLists() 获取

跟进 GetFileLists() 函数。'


在该函数中首先包含了 modulescache.php 文件,并通过 $hash 返回xml文件内容。

查看一下modulescache.php,

查看该xml内容,该文件内容中就是相应模块的配置信息。


发现执行了 uninstallok 分支。该分支就是卸载模块的分支,这里最重要的是通过 GetSystemFile() 获取文件内容,这里传入了另一个参数 delsql ,跟进该函数。


通过 GetHashFile() 函数获取文件内容。

delsql内容中正是删除程序处的文件的base64内容

最后在代码518行执行SQL语句,所以我们可以通过Mysql日志文件来getshell,而这里需要网站的绝对路径,通过之前的目录遍历,可以获取到绝对路径。

漏洞复现:


最后访问cyw.php,获取敏感信息。

4.任意文件写入2

全局搜索危险函数 fwrite() 时发现在 article_string_mix.php 中存在可以控制写入内容。


在 article_string_mix.php 中 $allsource 写入的内容是可控的,但在代码中存在危险函数过滤,但在过滤函数中过滤不严格导致绕过,实现代码执行。

漏洞复现:

通过 preg_replace() 绕过危险函数过滤,造成代码执行。

写入downmix.data.php

访问dede/article_template_rand.php文件,执行phpinfo()。

5.任意文件写入漏洞3

在dedecms中使用 fwrite() 函数写入配置文件的操作是很多的,在该系统中我们只需要观察两点即可,一写入的位置为可解析的php文件,二写入的内容我们是可控的即可。

在函数 ReWriteConfig() 中,我们可以发现代码的第38行和第42行都是用了 fwrite() 函数,向上回溯发现该处的值是从代码3的 sysconfig 表中拿到的,我们去看看该表中的内容。


该处存储了网站的配置信息,上面的代码中可以看到type为 number 时会将 varname 字段的值以及value字段的值写入配置文件,如果类型不为type时,这里会存在一个小小的过滤,这里的单引号会被替换为空。
绕过思路:
1.我们可以直接在type=number类型的字段中直接插入我们要执行的代码

2.通过\反斜杠来转义原本的单引号,然后使我们的代码逃逸出来

在 dopost 参数为 save 时,发现这里接收了post传入的参数,并且将传入的内容写入到sysconfig 表中。在代码中执行了上面分析的 ReWriteConfig() 函数。

漏洞复现:

访问/dede/sys_info.php文件,发现该处功能点确实是配置系统参数处,所以我们直接在type=number参数处插入我们的代码。

第二种方法可以通过\反斜杠转义原有的单引号,使我们的代码逃逸出来。


6.数据库操作getshell(2)

在测试系统功能点的时候,发现一处可以操作数据库的地方,下面的功能可以执行SQL语句。

漏洞分析:

这里执行到query分支,代码中存在过滤,这里过滤了drop关键字,然后执行SQL语句。

漏洞复现:


利用条件:**
set global general_log = on;
set global general_log_file = 'D:/phpstudy_pro/WWW/www.dedecms12.com/uploads/shell.php';

7.文件上传漏洞

此处首先具有前端限制,上传 .jpg 后缀文件,结合brup抓包,发现处理上传功能的文件为dede/archives_do.php

然后结合抓包,来看看具体代码

入口文件通过 config.php 会实现权限认证和一些外部参数过滤注册,这里上传文件会带有$_FILES参数,通过全局分析得知会触发uploadsafe.inc.php的过滤,过滤后,通过AdminUpload()实现最终文件上传。

进入include/helpers/upload.helper.php

最终实现文件上传的AdminUpload()来自upload.helper.php,传入AdminUpload()的$ftype固定为imagelit,则一定会进入对应的检测判断。

漏洞复现:

进入添加文档,该功能可以发布文章,而且具有文件上传的功能。

8.xss漏洞

在qrcode.php及加载的文件都没有做xss过滤,通过common.inc.php会注册全局变量。进入qrcode.php,qrcode.php及加载的文件都没有做xss过滤,通过common.inc.php会注册全局变量。

$id只能为整数类型,$type类型可控,加载模板qrcode.htm,利用视图类格式化输出$id,$type的值,$type可控,这里就存在xss漏洞。


可以看到这里的触发点$dtp->SetVar('type',$type);

9.url 重定向漏洞

进入plus/download.php,发现对$link做了base64解码

发现有一个很奇怪的限制,in_array($linkinfo['host'], $allowed),然而download.php中却没有$linkinfo这个参数

10.会员中心任意用户密码修改

在用户密码重置功能处,php存在弱类型比较,导致如果用户没有设置密保问题的情况下可以绕过验证密保问题,直接修改密码(管理员账户默认不设置密保问题)。值得注意的是修改的密码是member表中的密码,即使修改了管理员密码也是member表中的管理员密码,仍是无法进入管理。

代码分析

php弱类型比较问题很常见,在不同类型比较时,如果使用的是\==,php会将其中一个数据进行强制转换为另一个。

'' == 0 == false '123' == 123 //'123'强制转换为123
'abc' == 0 //intval('abc')==0
'123a' == 123 //intval('123a')==123
'0x01' == 1 //被识别为十六进制
'0e123456789' == '0e987654321' //被识别为科学计数法
[false] == [0] == [NULL] == ['']
NULL == false == 0
true == 1

dedecms的/member/resetpassword.php就是用来处理用户密码重置的问题。


先从数据库取出相关用户的密保问题及密保答案,在对用户输入做了一些处理后,进行了关键性的判断if($row['safequestion'] == $safequestion && $row['safeanswer'] == $safeanswer) ,就在这里用了弱类型判断\==。

跟踪newmail。
在sn函数中将send参数设置了'N',其实就是生成了暂时密码并插入了数据库中,并进行跳转:

漏洞复现:

在找回密码处,点击通过安全问题取回。

11.任意用户登陆漏洞

dedecms的会员模块的身份认证使用的是客户端session,在Cookie中写入用户ID并且附上ID__ckMd5,用做签名。主页存在逻辑漏洞,导致可以返回指定uid的ID的Md5散列值。

代码分析

在/member/index.php中会接收uid和action参数。uid为用户名,进入index.php后会验证Cookie中的用户ID与uid(用户名)并确定用户权限。

看到当uid存在值时就会进入我们现在的代码中,当cookie中的last_vid中不存在值为空时,就会将uid值赋予过去,$last_vid = $uid;,然后PutCookie。

进入/include/memberlogin.class.php


$this->M_ID等于Cookie中的DedUserID,我们继续看看GetCookie函数它不但读了cookie还验证了md5值。这样,由于index.php中我们可以控制返回一个输入值和这个输入值经过服务器处理后的md5值。那么如果我们伪造DedUserID和它对应的MD5就行了。

漏洞复现:

主要思路就是:
访问member/index.php?uid=0000001并抓包(注意cookie中last_vid值应该为空)。
1. 先从member/index.php中获取伪造的DedeUserID和它对于的md5 2. 使用它登录****

REF:
https://www.freebuf.com/articles/web/281747.html
https://blog.szfszf.top/article/25/

  • 发表于 2023-04-11 09:00:02
  • 阅读 ( 7293 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
Arthur
Arthur

8 篇文章

站长统计