路漫漫其修远兮

yccms - Sql Injection

2019.06.15

Vulnerability Report: yccms 3.3 sql injection

This paper describes yccms(yccms is a PHP version of lightweight CMS station building system, the program page design is simple, generate static html, powerful background functions, conducive to optimization, super-strong collection, super-strong ranking, suitable for keyword ranking, Taobao guest program, is an ideal choice for individuals and enterprises to build a station.

Sql injection vulnerability in the project, no_top function’s improper judgment of the request parameters, triggering a sql injection vulnerability

Test Environment

  • yccms: 3.3 website: http://www.yccms.net/
  • php: 7.2.9
  • os and hardware: Mac OS X 10_12_6

Vulnerability Location

The vulnerability lies in the index function in the yccms_v3.3/controller/SystemAction.class.php file, which calls the setSystem to save system setting.

In the SystemModel class, data is saved by the method system, although there is an interceptor (_set) in the constructor to filter the relevant characters without filtering; , So we can use the system to set parameters, and we can set our own paylaod 2;select sleep(5) for the parameter page_size_index.

	public function index(){
		if(isset($_POST['send'])){
			if(validate::isNullString($_POST['title'])) Tool::t_back('ERROR:网站标题为空!!','?a=system');
			if(validate::isNullString($_POST['url'])) Tool::t_back('ERROR:网站域名为空!!','?a=system');
			if(validate::isNullString($_POST['thumb'])) Tool::t_back('ERROR:logo为空!!','?a=system');
			if(validate::isNullString($_POST['keywords'])) Tool::t_back('ERROR:关键字为空!!','?a=system');
			if(validate::isNullString($_POST['description'])) Tool::t_back('ERROR:描述为空!!','?a=system');
			if(validate::isNullString($_POST['footer'])) Tool::t_back('ERROR:底部信息为空!!','?a=system');
			if(validate::isNullString($_POST['page_size'])) Tool::t_back('ERROR:后台分页条数为空!!','?a=system');
			if(validate::isNullString($_POST['page_size_index'])) Tool::t_back('ERROR:前台分页条数为空!!','?a=system');
			$this->_model->title=$_POST['title'];
			$this->_model->url=$_POST['url'];
			$this->_model->thumb=$_POST['thumb'];
			$this->_model->keywords=$_POST['keywords'];
			$this->_model->description=$_POST['description'];
			$this->_model->footer=$_POST['footer'];
			$this->_model->webname=$_POST['webname'];
			$this->_model->page_size=$_POST['page_size'];
			$this->_model->page_size_index=$_POST['page_size_index'];
			if($this->_model->setSystem()){
				//Tool::alertLocation('设置已保存!', '?a=system');
				tool::layer_alert('设置已保存!','?a=system',6);
			}else{
				//Tool::alertLocation('保存失败!', '?a=system');
				tool::layer_alert('保存失败!','?a=system',5);
			}
		}
	
	......
	
	class SystemModel extends Model{
	private $title;
	private $url;
	private $thumb;
	private $webname;
	private $page_size;
	private $page_size_index;
	private $keywords;
	private $description;
	private $footer;
	private $index_main;
	//拦截器(__set)
	public function __set($_key, $_value) {
		$this->$_key = tool::setFormString($_value);
	}
	
	//拦截器(__get)
	public function __get($_key){
		return $this->$_key;
	}

	//查询系统设置
	public function system(){
		$_sql="SELECT *
					FROM
						my_system
					WHERE
						id=1
						LIMIT 1";
		return parent::select($_sql);
	}
	//系统设置
	public function setSystem(){
		$_sql="UPDATE
					my_system
				SET
					title='$this->title',
					url='$this->url',
					thumb='$this->thumb',
					keywords='$this->keywords',
					description='$this->description',
					footer='$this->footer',
					webname='$this->webname',
					page_size='$this->page_size',
					page_size_index='$this->page_size_index'
				WHERE
					id=1
				LIMIT  1";
		return parent::update($_sql);
		
	}

In the function of the production list, the system settings parameter page_size_index saved in the previous step is finally invoked. Then enter the function no_top for database query operation. The page_size_index parameter eventually brings in $this->_limit

//生成列表
	public function lists(){
		if(isset($_POST['send'])){
			echo str_repeat(" ",1024);
			//公共
			$_sys=$this->_sys->system();
			$_syspage=$_sys[0]->page_size_index;
			$this->common();
			$_nav=$this->_nav->getAllNav();
			if($_nav){
				foreach ($_nav as $_value){
					//父类	
					$this->getNav($_value->id);//洋葱皮
					$_page=$this->getClassPage($_value->id,$_syspage);//ID,每页条数		
					for($i=1;$i<=$_page;$i++){
						if($i==1){		
							$_GET['page']=$i;
							$this->_tpl->assign('pages','');//页码
							$this->par_main($_value->id,$_value->nav_ename,$_syspage); //列表主体
							$_html=$_value->nav_ename.'/index.html';
							$content=$this->_tpl->fetch('index/public/list.tpl');
							$_filename=ROOT_PATH.'/'.$_html;
							Tool::makeHtmlFile($_filename, $content);
						}else{
							$_GET['page']=$i;
							$this->_tpl->assign('pages','_第'.$i.'页');//页码
							$this->par_main($_value->id,$_value->nav_ename,$_syspage); //列表主体
							$_html=$_value->nav_ename.'/index_'.$i.'.html';
							$content=$this->_tpl->fetch('index/public/list.tpl');
							$_filename=ROOT_PATH.'/'.$_html;
							Tool::makeHtmlFile($_filename, $content);
						}
						echo '<span style="font-size:12px;">正在生成 '.$_html.'</span><br />';
						ob_flush();
						flush();
						//sleep(2);
						echo '<script>document.body.innerHTML="";</script>';
					}
									
				}		
			}
			
//列表主体
	private function par_main($_id,$_ename,$_page){
		$this->_art->cid=$_id;
		parent::page2($this->_art->notop_total(),$_page,$this->_art,$_ename,$_fx='index');
		$_arts=$this->_art->no_top();
		if($_arts){
			foreach ($_arts as $_value){
				$_attr=explode(',', $_value->attr);
				if(in_array('加粗', $_attr)){
					$_value->b=1;
				}
			}
		}
		
   ......
   
   //筛选非置顶的
	public function no_top(){
		$_sql="SELECT
					*
				FROM
					my_article
				WHERE
					cid IN ($this->cid)
				ORDER BY
					time DESC
				$this->_limit";
		var_dump($_sql);
		
		return parent::select($_sql);
	}

Local Test

Enter the management background, set the system settings, and set the parameter page_size_index to inject payload into our SQL

avatar

Go to Static Generation, Generate List Page, Click Generate List. You can see that because SQL injection statements are successfully executed, each statement executes "SELECT * FROM my_article WHERE cid IN (92) ORDER BY time DESC LIMIT 0,2;select sleep(5)", resulting in a page generation time of 400057 Millisecond

avatar

Summary

this paper verifies the sql injection vulnerability in the function of no_topin yccms ver3.3 through local tests.

发表评论