这两天突然看到 https://blog.ripstech.com/2020/sql-injection-impresscms/,想着复现一下,记录一下学习过程。
漏洞分析
漏洞复现
首先我们先下载安装一下这个 cms,然后直接访问:
http://127.0.0.1:81/admin.php/modules/system' and sleep(2) and '1
这个 url,会发现延迟了三秒,没错这个漏洞就是这么简单。更深的用法我们就不讨论了。
漏洞分析
打开 cms 的文件: \htdocs\libraries\icms\module\Handler.php,找到 service 函数:
static public function service($inAdmin = FALSE) {
if ($inAdmin || ... ) {
$url_arr = explode('/', strstr($_SERVER['PHP_SELF'], '/modules/'));
if (isset($url_arr[2])) {
//关键点
$module = icms::handler("icms_module")->getByDirname($url_arr[2], TRUE);
我们首先访问 admin.php 会执行到这个函数,然后 inAdmin 会设置成 true,到第四行获取了 PHP_SELF 并以 /modules/ 分割,然后讲 /modules/ 后的内容带入 getByDirname,跟进该函数:
public function getByDirname($dirname, $loadConfig = FALSE) {
if (!empty($this->_cachedModule[$dirname]) &&
$this->_cachedModule[$dirname]->getVar('dirname') == $dirname
) {
...
} else {
$sql = "SELECT * FROM " . $this->db->prefix('modules') . " WHERE dirname = '" . trim($dirname) . "'";
//执行sql
可以看到这里直接带入了 $sql 没有任何过滤。
扩展思考
之前我也审计到过一个此类的漏洞,这里顺便分享一下:
然后下面的代码:
//此处的 $uri 就是 PHP_SELF
$tmp = strtolower(substr($uri,-4));
if(in_array($tmp,array('.jpg','.gif','.png','jpeg')) && substr($uri,0,11) == 'res/_cache/'){
$tmp = substr($uri,11);
$tmp = explode("/",$tmp);
get_one($tmp[0]);
当文件名是 .jpg 结尾并且 uri 前十一位是 res/_cache/ 时进入,最后用 / 分割 uri 并带入 sql 语句。
很容易就可以 payload:
index.php/res/_cache/a'-sleep(3)-'/test/test.jpg
此外还有一个点,但是暂时没有见到过案例,比如:
<?php
print_r($_SERVER['REQUEST_URI']);
?>
这样的代码,然后我们用 bp 讲 /test/test.php 修改成:/abc'd/../test/test.php
当然,不管是 PHP_SELF 还是 REQUEST_URI 我们直接 echo 出来都会造成 反射的 XSS
实际上我们访问的依然是 test.php,但是 REQUEST_URI 输出的却是 /abc'd/../test/test.php。
当然,$_SERVER 里还有很多好玩的,期待师傅们挖掘出来教我QAQ