Pandora FMS是一款开源的应用程序,用于监控网络和IT基础设施等。它可以监视网络设备、操作系统、虚拟基础设施以及其它应用程序和系统(如防火墙、数据库和Web服务器)。许多行业巨头都在使用企业版Pandora FMS,包括怡安、安联和东芝等。
研究人员发现Pandora FMS 742版本中存在多个漏洞,这些漏洞允许远程攻击者在任何一个Pandora FMS服务器上执行任意代码。攻击者不需要任何先验知识、访问权限或特定配置。连接用于监视Pandora FMS的系统可能会遭受进一步的攻击。研究人员已经将漏洞信息上报给了受影响的供应商,供应商已经针对743版本发布了补丁程序。 攻击向量 研究人员在对Pandora FMS 742的控制台进行分析后,发现存在以下四种漏洞:SQL注入漏洞
phar反序列化漏洞
远程文件包含漏洞
跨站请求伪造漏洞
此次主要针对SQL注入漏洞进行分析,该漏洞无需任何权限即可被远程利用,使攻击者能够完全绕过管理员身份验证,并在系统上执行任意代码。Pandora FMS主要用于内网,远程攻击者通常无法直接对其进行访问。但是,可以通过跨站请求伪造攻击进行SQL注入。如果受害者能够通过浏览器访问Pandora FMS安装,则访问精心设计的恶意网站也可能引发攻击。目标用户无需在Pandora FMS中拥有帐户或任何特权。分析过程中,研究人员还发现一些可以通过Internet直接访问的Pandora的实例。
监控解决方案对攻击者而言是一个具有吸引力的目标,因为其通常具有攻击者所监控设备的访问权,并且是入侵其它基础设施的起点。研究人员制作了一个概念验证(POC)视频,如下所示:
技术分析 为了探究此次漏洞的根本原因,研究人员对用PHP编写的Pandora FMS源代码进行了分析,并介绍了Pandora FMS所使用的安全机制。 安全机制 Pandora FMS源代码中,通常利用 io_safe_input() 自定义函数,对用户输入进行清理。它使用PHP内置函数 htmlspecialchars() 对字符串值进行清理,该函数对某些HTML标记字符(“ <>')进行编码。除此之外,该功能还采取了其它安全措施。 /include/functions_io.php72 function io_safe_input($value) { ⋮ 94 $valueHtmlEncode = htmlentities($value, ENT_QUOTES, 'UTF-8', true); ⋮128 return $valueHtmlEncode;129 }
Pandora FMS开发人员还实现了一个封装函数,用于检索称为get_parameter()的GET和POST参数。该函数使用io_safe_input()函数来清除从$ _GET/$ _POST参数检索的用户输入。这种封装函数通常用于避免开发者不得不担心清除值。封装函数的作用很大,但在使用时还需注意以下一些陷阱。
此功能是可选的,可以直接访问未清除的$ _GET或$ _POST变量。直接访问在Pandora FMS代码库中发生了多次,曾经导致了安全问题。
包装函数检索到的已清除的数据仍然会导致安全问题,因为必须根据标记上下文清除输入。例如,将用户输入嵌入到各种JavaScript代码部分中,则htmlspecialchars()函数将不能防止跨站脚本漏洞。开发人员可能过于相信封装函数的安全性,却不知道其实际作用。
除了GET和POST参数外,cookies或HTTP头也会记录用户输入,而所有的用户输入都必须清除。
当访问Pandora FMS的图表生成器时,首先检查身份验证。
/include/chart_generator.php
71 // Try to initialize session using existing php session id.72 $user = new PandoraFMS\User(['phpsessionid' => $_REQUEST['session_id']]);73 if (check_login(false) === false) {74 // Error handler. ⋮96 }9798 // Access granted.
从chart_generator.php的第72行中可以看出,用户输入是从$ _REQUEST超全局变量中获取的,该全局变量包含GET和POST参数以及cookie值。后者可能是为什么未在此处使用get_parameter()的原因。用户输入$ _REQUEST ['session_id']没有经过任何清除就传送给PandoraFMS \ User类的构造函数。然后,check_login()函数被用于检查登录会话变量是否已设置并有效。最终,如果存在具有给定会话ID的用户,然后授予访问权限,则函数check_login()的评估结果为true。
以下代码片段显示了在PandoraFMS \ User类的构造函数中,攻击者控制值为$ data ['phpsessionid']的情况。
/include/lib/User.php
60 public function __construct($data)61 { ⋮68 if (is_array($data) === true) {69 if (isset($data['phpsessionid']) === true) {70 $this->sessions[$data['phpsessionid']] = 1;71 $info = \db_get_row_filter(72 'tsessions_php',73 ['id_session' => $data['phpsessionid']]74 );7576 if ($info !== false) {77 // Process.78 $session_data = session_decode($info['data']);79 $this->idUser = $_SESSION['id_usuario'];8081 // Valid session.82 return $this;83 }
第73行中,用户控制的参数传递给db_get_row_filter()函数。该函数使用了几个内部函数,这些内部函数根据提供的表名和数组提供的条件,动态构建SQL查询。由于,该函数将攻击者控制的变量直接连接到SQL WHERE子句中,而没有进行适当的清除,从而导致了SQL注入(mysql.php中的762行)。
/include/lib/mysql.php848 function db_get_row_filter($table, $filter, $fields=false)849 { ⋮861 $filter = db_format_array_where_clause_sql($filter, ' WHERE '); ⋮868 $sql = sprintf('SELECT %s FROM %s %s', $fields, $table, $filter);
/include/lib/mysql.php
660 function db_format_array_where_clause_sql($values, $prefix=false)661 {668 $query = ''; ⋮709 foreach ($values as $field => $value) { ⋮762 $query .= sprintf("%s = '%s'", $field, $value); ⋮771 }772773 return (!empty($query) ? $prefix : '') . $query;
通过SQL注入,攻击者可以构造SQL语句,从而破坏数据库查询的结果。从这里开始,攻击者可以对User.php第71行中$ info ['data']的数据进行控制。然后使用PHP的session_decode()函数从$ info ['data']加载会话数据,并将其填充到第78行中的当前$ _SESSION中。如此,便可以通过加载其用户ID来冒充任何用户,包括具有完全访问权限的管理员账户。最终,从而实现未经身份验证的SQL注入可用以任何用户身份进行身份验证。
需要注意的是,session_decode()函数可以反序列化类似于unserialize()函数的任意对象,这意味着攻击者可以通过SQL注入反序列化任意对象
。
缓解措施
Pandora FMS团队已经发布了该漏洞的补丁程序,建议受影响的用户尽快进行更新,详情请参考以下链接。
https://pandorafms.com/blog/whats-new-in-pandora-fms-743/
END
好文!必须在看