漏洞出现在 lib/base/dao/dao.class.php
这里只对 $order 部分进行了校验, 而没有对 limit 后面的部分进行校验。
看到 printTradeBlock
在 $this->processParams() 中设置好 $this->params
可以看到 $this->params 就是 json_decode(base64_decode($_GET[\'param\']))
然后又会调用
orderBy($this->params->orderBy)所以我们可以控制 limit 后面的部分, SQL注入。
这套程序中还会执行 sql 语句,用的是 Pdo用的是 $pdo->query(), 这个函数可以一次执行多条 sql 语句。
/** * 执行SQL语句,返回PDOStatement结果集。 * Query the sql, return the statement object. * * @access public * @return object the PDOStatement object. */ public function query($sql = \'\') { /* 如果有错误,返回一个空的PDOStatement对象,确保后续方法能够执行。*/ /* If any error, return an empty statement object to make sure the remain method to execute. */ if(!empty(dao::$errors)) return new PDOStatement(); if($sql) { $sql = trim($sql); $sqlMethod = strtolower(substr($sql, 0, strpos($sql, \' \'))); $this->setMethod($sqlMethod); $this->sqlobj = new sql(); $this->sqlobj->sql = $sql; } else { $sql = $this->processSQL(); // 大概就是获取 sql 语句 } $key = md5($sql); try { $method = $this->method; $this->reset(); if($this->slaveDBH and $method == \'select\') { if(isset(dao::$cache[$key])) return dao::$cache[$key]; $result = $this->slaveDBH->query($sql); dao::$cache[$key] = $result; return $result; } else { if($this->method == \'select\') { if(isset(dao::$cache[$key])) return dao::$cache[$key]; $result = $this->slaveDBH->query($sql); dao::$cache[$key] = $result; return $result; } return $this->dbh->query($sql); } } catch (PDOException $e) { $this->sqlError($e); } }这样我们的利用方式就简单了。
闭合 limit 语句,用 ; 连接多条语句
没有回显, 使用 时间盲注
poc
任意文件下载 && 任意文件删除由于可以一次执行多条 sql 语句 ,我们实质上已经可以控制数据库了。
在 app/sys/file/control.php ,有两个函数 delete 和 download, 分别用于删除文件和下载文件。
以 delete 为例
$this->file->getById($fileID) 时间就是在 表前缀sys_file 中查找对应 id 相对应的 路径。
利用 sql 注入修改为目标路径(用 ../ 进行目录跳转),然后选择相应 id 即可删除指定文件。下载文件也是类似。
getshell删除 my.php 后 会要求我们重新安装系统。
在重装系统的最后一步,会直接使用 POST 中的值,来设置 my.php 的内容,同时 , 访问 install.php 时,是不会调用参数过滤的函数的
所以可以注入 php 代码,getshell