学习打卡——wuzhicms代码审计

郎贤坤   ·   发表于 2022-08-08 22:40:37   ·   学习杂记

wuzhicms代码审计

1.前台sql注入

源码分析
1搜索关键字select发现mysql.class文件下有一个变函数里面有select 并且后面没有过滤


全局搜索一下发现在sms_check文件里调用了这个函数get_one

  1. get_one('sms_checkcode',"`code`='$code' AND `posttime`>$posttime",'*',0,'id DESC');
  2. if($r) {
  3. exit('{"info":"验证通过","status":"y"}');
  4. } else {
  5. exit('{"info":"验证失败","status":"n"}');

通过$code api查看

  1. get_one('sms_checkcode',"`code`='$code' AND `posttime`>$posttime",'*',0,'id DESC');
  2. if($r) {
  3. exit('{"info":"验证通过","status":"y"}');
  4. } else {
  5. exit('{"info":"验证失败","status":"n"}');
  6. ?>

通过$GLOBALS获取param的值,然后通过strip_tags过滤html标签
然后引入db类,再次对传入的值进行过滤,如果是数组则进入if,把括号 单引号这些过滤掉。不是则走else 过滤 %20 %27

  1. ?>
  2. $val) {//foreach,每次循环中,当前单元的值被赋给$val
  3. $val = str_replace("%20", '', $val);//str_replace,替换字符串中的一些字符(区分大小写)
  4. $val = str_replace("%27", '', $val);
  5. $val = str_replace("(", '', $val);
  6. $val = str_replace(")", '', $val);
  7. $val = str_replace("'", '', $val);
  8. $sql .= $sql ? " AND `$key` = '$val' " : " `$key` = '$val' ";
  9. }
  10. return $sql;
  11. } else {
  12. $data = str_replace("%20", '', $data);
  13. $data = str_replace("%27", '', $data);
  14. return $data;
  15. }
  16. }
  17. ?>

出现漏洞的地方就在这个过滤上面,我们传入的值不是数组,所以不走if
而else只过滤了%20和%27,我们的传参会经过一url编码,但服务器也会解码一次,如果是二次编码else才会起过滤作用

2.后台任意文件读取,删除

coreframe\app\attachment\admin\index.php中存在dir方法

  1. */
  2. public function dir()
  3. {
  4. $dir = isset($GLOBALS['dir']) && trim($GLOBALS['dir']) ? str_replace(array('..\\', '../', './', '.\\'), '', trim($GLOBALS['dir'])) : '';
  5. $dir = str_ireplace(array('%2F', '//'), '/', $dir);
  6. $lists = glob(ATTACHMENT_ROOT . $dir . '/' . '*');//glob该函数返回一个包含有匹配文件 / 目录的数组。如果出错返回 false
  7. if (!empty($lists)) rsort($lists);//rsort对数组中的元素按字母进行降序排序:
  8. $cur_dir = str_replace(array(WWW_ROOT, DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR), array('', DIRECTORY_SEPARATOR), ATTACHMENT_ROOT . $dir . '/');
  9. include $this->template('dir', M);
  10. }
  11. 分析逻辑发现,将../,./,.\,..\替换成空再添加/结尾,这里可以通过多写绕过
  12. ![](https://nc0.cdn.zkaq.cn/md/9250/db670ba073f79877ecb445a601ceff46_95358.png)
  13. ![](https://nc0.cdn.zkaq.cn/md/9250/a283af8986788c10b3085f38c77dd1f9_65398.png)
  14. 读到的文件也可以删除,找到del方法
  15. ```php
  16. public function del()
  17. {
  18. $id = isset($GLOBALS['id']) ? $GLOBALS['id'] : '';
  19. $url = isset($GLOBALS['url']) ? remove_xss($GLOBALS['url']) : '';
  20. if (!$id && !$url) MSG(L('operation_failure'), HTTP_REFERER, 3000);
  21. if ($id) {
  22. if(!is_array($id)) {
  23. $ids = array($id);
  24. } else {
  25. $ids = $id;
  26. }
  27. foreach($ids as $id) {
  28. $where = array('id' => $id);
  29. $att_info = $this->db->get_one('attachment', $where, 'usertimes,path');
  30. if ($att_info['usertimes'] > 1) {
  31. $this->db->update('attachment', 'usertimes = usertimes-1', $where);
  32. }
  33. else {
  34. $this->my_unlink(ATTACHMENT_ROOT . $att_info['path']);
  35. $this->db->delete('attachment', $where);
  36. $this->db->delete('attachment_tag_index', array('att_id'=>$id));
  37. }
  38. }
  39. MSG(L('delete success'), HTTP_REFERER, 1000);
  40. }
  41. else {
  42. if (!$url) MSG('url del ' . L('operation_failure'), HTTP_REFERER, 3000);
  43. $path = str_ireplace(ATTACHMENT_URL, '', $url);
  44. if ($path) {
  45. $where = array('path' => $path);
  46. $att_info = $this->db->get_one('attachment', $where, 'usertimes,id');
  47. if (empty($att_info)) {
  48. $this->my_unlink(ATTACHMENT_ROOT . $path);
  49. MSG(L('operation_success'), HTTP_REFERER, 3000);
  50. }
  51. if ($att_info['usertimes'] > 1) {
  52. $this->db->update('attachment', 'usertimes = usertimes-1', array('id' => $att_info['id']));
  53. }
  54. else {
  55. $this->my_unlink(ATTACHMENT_ROOT . $path);
  56. $this->db->delete('attachment', array('id' => $att_info['id']));
  57. MSG(L('operation_success'), HTTP_REFERER, 3000);
  58. }
  59. }
  60. else {
  61. MSG(L('operation_failure'), HTTP_REFERER, 3000);
  62. }
  63. }
  64. }

全局搜索删除文件的函数unlink
然后发现这里调用了函数并赋给$path
$this->my_unlink(path:ATTACHMENT_ROOT . $path);
2.在del函数里找到了调用删除文件函数
$path = str_ireplace(ATTACHMENT_URL, ‘’, $url);
然后来分析调用的过程 调用删除的时候通过把$path和ATTACHMENT_ROOT 拼接

而ATTACHMENT_ROOT是前面定义的一个默认路径
path则是前面的$url 来的
在看前面的if 如果path有值则进入到if里面 然后经过的数据库的get_one查询操作 应该这里是要查出一个东西
但是因为我数据库是空的 则进入的是第一个if里面 哪怕是查出1条 也是可以的
这里也没有其他过滤


然后网上看url的来源
GLOBALS 那就可以直接通过传参的 前面也介绍了 id为空的话 也就进入到了else里面

到这里也就可以构造payload了

$path = str_ireplace(ATTACHMENT_URL, ‘’, $ur
通过url获取路径后,检测了ATTACHMENT_URL参数,替换为空
后面没有其他过滤,直接传入my_unlink:

  1. private function my_unlink($path)
  2. {
  3. if(file_exists($path)) unlink($path);//file_exists,检查文件或者目录是否存在
  4. //unlink,删除文件
  5. }
  6. 先在目录下建一个1.txt文件
  7. ![](https://nc0.cdn.zkaq.cn/md/9250/d26bb59bef72fd715ff3bd440f7d301c_28589.png)
  8. 然后构造http://127.0.0.1/wuzhicms-wuzhicms-v4.1.0-0-g0a9144f/wuzhicms-wuzhicms-0a9144f/www/index.php?m=attachment&f=index&v=del&_su=wuzhicms&url=../1.txt
  9. ![](https://nc0.cdn.zkaq.cn/md/9250/ca38110296b2d4f6c845028afa9755df_16047.png)
  10. ![](https://nc0.cdn.zkaq.cn/md/9250/003c0e79fc7aba2e269d1c208824369d_79094.png)

逻辑漏洞

在api/uc.php中


通过传参可以调用uc_note类的任意方法:
可以任意更改用户名和密码

后台RCE

在coreframe\app\core\libs\function\common.func.php中set_cache方法:


写入缓存后面没有过滤,跟进函数,看看哪里调用了set_cache
找到一处调用set_cache的地方


根据代码,可以直接获取setting写入缓存

打赏我,让我更有动力~

3 条回复   |  直到 2022-9-10 | 866 次浏览

郎贤坤
发表于 2022-8-15

对于任意文件删除那一部分还是有些不理解,希望路过的师傅可以指点一下,这是文件删除的源码

  1. /**
  2. * 删除文件
  3. *
  4. * @author tuzwu
  5. * @createtime
  6. * @modifytime
  7. * @param
  8. * @return
  9. */
  10. public function del()
  11. {
  12. $id = isset($GLOBALS['id']) ? $GLOBALS['id'] : '';
  13. $url = isset($GLOBALS['url']) ? remove_xss($GLOBALS['url']) : '';
  14. if (!$id && !$url) MSG(L('operation_failure'), HTTP_REFERER, 3000);
  15. if ($id) {
  16. if(!is_array($id)) {
  17. $ids = array($id);
  18. } else {
  19. $ids = $id;
  20. }
  21. foreach($ids as $id) {
  22. $where = array('id' => $id);
  23. $att_info = $this->db->get_one('attachment', $where, 'usertimes,path');
  24. if ($att_info['usertimes'] > 1) {
  25. $this->db->update('attachment', 'usertimes = usertimes-1', $where);
  26. }
  27. else {
  28. $this->my_unlink(ATTACHMENT_ROOT . $att_info['path']);
  29. $this->db->delete('attachment', $where);
  30. $this->db->delete('attachment_tag_index', array('att_id'=>$id));
  31. }
  32. }
  33. MSG(L('delete success'), HTTP_REFERER, 1000);
  34. }
  35. else {
  36. if (!$url) MSG('url del ' . L('operation_failure'), HTTP_REFERER, 3000);
  37. $path = str_ireplace(ATTACHMENT_URL, '', $url);
  38. if ($path) {
  39. $where = array('path' => $path);
  40. $att_info = $this->db->get_one('attachment', $where, 'usertimes,id');
  41. if (empty($att_info)) {
  42. $this->my_unlink(ATTACHMENT_ROOT . $path);
  43. MSG(L('operation_success'), HTTP_REFERER, 3000);
  44. }
  45. if ($att_info['usertimes'] > 1) {
  46. $this->db->update('attachment', 'usertimes = usertimes-1', array('id' => $att_info['id']));
  47. }
  48. else {
  49. $this->my_unlink(ATTACHMENT_ROOT . $path);
  50. $this->db->delete('attachment', array('id' => $att_info['id']));
  51. MSG(L('operation_success'), HTTP_REFERER, 3000);
  52. }
  53. }
  54. else {
  55. MSG(L('operation_failure'), HTTP_REFERER, 3000);
  56. }
  57. }
  58. }
  59. /**
  60. * 预览附件的缩略图
  61. *
  62. * @author tuzwu
  63. * @createtime
  64. * @modifytime
  65. * @param
  66. * @return
  67. */
  68. public function thumb()
  69. {
  70. $id = isset($GLOBALS['id']) ? intval($GLOBALS['id']) : '';
  71. $url = isset($GLOBALS['url']) ? remove_xss($GLOBALS['url']) : '';
  72. if (!$id && !$url) MSG(L('operation_failure'), HTTP_REFERER, 3000);
  73. }
  74. * 附件删除,要同时删除缩略图,同时做一些安全认证
  75. *
  76. * @author tuzwu
  77. * @createtime
  78. * @modifytime
  79. * @param
  80. * @return
  81. private function my_unlink($path)
  82. {
  83. if(file_exists($path)) unlink($path);
  84. }

评论列表

  • 加载数据中...

编写评论内容

君叹
发表于 2022-8-26

wuzhi漏洞,wuzhi不行,wuzi不行???

评论列表

  • 加载数据中...

编写评论内容

st2021
发表于 2022-9-10

请问uc.php的逻辑漏洞,楼主是怎么编写code的?我是从网上找了个大神写的一个脚本,编写所需传参然后生成code完成逻辑漏洞复现的。

评论列表

  • 加载数据中...

编写评论内容
登录后才可发表内容
返回顶部 投诉反馈

© 2016 - 2024 掌控者 All Rights Reserved.