PbootCMS-XSS(stored)漏洞分析
- 2019 年 10 月 7 日
- 笔记
本文作者:WHITE(Ms08067实验室核心成员)
一、漏洞摘要
bootCMS是全新内核且永久开源免费的cms,在其V2.0.2版本中存在存储型XSS 漏洞名称:PbootCMS存储型XSS 产品首页:https://www.pbootcms.com 软件链接:
https://github.com/hnaoyun/PbootCMS 版本:V2.0.2-20190915
二、漏洞概述
漏洞路径为
/PbootCMS/apps/home/controller/ParserController.php
public function parserSiteLabel($content) { $pattern = '/{pboot:site([w]+)(s+[^}]+)?}/'; if (preg_match_all($pattern, $content, $matches)) { $data = $this->model->getSite(); $count = count($matches[0]); for ($i = 0; $i < $count; $i ++) { $params = $this->parserParam($matches[2][$i]); switch ($matches[1][$i]) { case 'index': $content = str_replace($matches[0][$i], Url::home('home/Index/'), $content); break; case 'path': $content = str_replace($matches[0][$i], SITE_DIR, $content); break; case 'logo': if (isset($data->logo) && $data->logo) { if (! preg_match('/^http/', $data->logo)) { $content = str_replace($matches[0][$i], $this->adjustLabelData($params, SITE_DIR . $data->logo), $content); } else { $content = str_replace($matches[0][$i], $this->adjustLabelData($params, $data->logo), $content); } } else { $content = str_replace($matches[0][$i], STATIC_DIR . '/images/logo.png', $content); } break; case 'tplpath': $content = str_replace($matches[0][$i], APP_THEME_DIR, $content); break; case 'language': $content = str_replace($matches[0][$i], get_lg(), $content); break; case 'statistical': if (isset($data->statistical)) { $content = str_replace($matches[0][$i], decode_string($data->statistical), $content); } else { $content = str_replace($matches[0][$i], '', $content); } case 'copyright': if (isset($data->copyright)) { $content = str_replace($matches[0][$i], decode_string($data->copyright), $content); } else { $content = str_replace($matches[0][$i], '', $content); } default: if (isset($data->{$matches[1][$i]})) { $content = str_replace($matches[0][$i], $this->adjustLabelData($params, $data->{$matches[1][$i]}), $content); } else { $content = str_replace($matches[0][$i], '', $content); } } } } return $content; }
内容传入此函数后进行了decode_string()方法
位于PbootCMS/core/function/handle.php
function decode_string($string) { if (! $string) return $string; if (is_array($string)) { // 数组处理 foreach ($string as $key => $value) { $string[$key] = decode_string($value); } } elseif (is_object($string)) { // 对象处理 foreach ($string as $key => $value) { $string->$key = decode_string($value); } } else { // 字符串处理 $string = stripcslashes($string); $string = htmlspecialchars_decode($string, ENT_QUOTES); } return $string; }
此方法是html实体编码转义普通字符,而不是将普通字符转义成html实体编码,应当使用escape_string()处理数据,该方法同样位于PbootCMS/core/function/handle.php。
function escape_string($string) { if (! $string) return $string; if (is_array($string)) { // 数组处理 foreach ($string as $key => $value) { $string[$key] = escape_string($value); } } elseif (is_object($string)) { // 对象处理 foreach ($string as $key => $value) { $string->$key = escape_string($value); } } else { // 字符串处理 $string = htmlspecialchars(trim($string), ENT_QUOTES, 'UTF-8'); $string = addslashes($string); } return $string; }
三、利用代码
登陆后台在后台的-基础内容-站点信息-统计代码和尾部信息等处插入xss payload payload:<img src=x onerror=alert(1)>

进入主页触发xss


四、参考信息
五、补丁
case 'statistical': if (isset($data->statistical)) { $content = str_replace($matches[0][$i], decode_string($data->statistical), $content); } else { $content = str_replace($matches[0][$i], '', $content); } case 'copyright': if (isset($data->copyright)) { $content = str_replace($matches[0][$i], decode_string($data->copyright), $content); } else { $content = str_replace($matches[0][$i], '', $content); }
将其中的decode_string修改为escape_string即可修复!