问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
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
阅读 ( 6853 )
分类:
漏洞分析
1 推荐
收藏
0 条评论
请先
登录
后评论
Arthur
8 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!