PandoraFMS 742多个漏洞分析

  • A+
所属分类:安全开发

PandoraFMS 742多个漏洞分析

Pandora FMS是用于监视IT基础架构和网络的开源软件。它可以监视网络设备,操作系统,虚拟基础架构以及所有不同类型的对安全敏感的应用程序和系统(如防火墙、数据库和Web服务器)的状态和性能。

2020年09月22日,SonarSource网络安全研究员Dennis Brinkrolf公开了Pandora FMS 742版中最近发现的四个漏洞的细节。这些漏洞使远程攻击者可以在任何Pandora FMS服务器上执行任意代码或受到更严重的攻击。攻击者不需要任何先于经验的知识、访问特权或特定配置。Pandora官方立即发布了安全补丁程序版本743以修复这些漏洞。

 

影响范围

Pandora FMS 742此次被暴露出存在以下漏洞:

1.  SQL注入(认证前)
2.  Phar反序列化(认证前)
3.  远程文件包含(最低特权用户)
4.  跨站点请求伪造(CSRF)

其中,最为严重的是SQL注入漏洞。攻击者可以在没有任何访问权限的情况下远程利用它绕过管理员身份验证,最终可以在系统上执行任意代码。

 

技术分析

在下文中,我们将研究用PHP编写的Pandora FMS源代码中漏洞的根本原因。为此,我们将首先介绍Pandora FMS使用的安全机制及如何清理用户控制的输入、潜在的安全问题以及SQL注入漏洞形成的详细过程。

 

安全机制

在Pandora FMS的源代码中,通常使用名为io_safe_input()的自定义函数对用户输入进行清理。它使用PHP内置函数htmlspecialchars()对字符串值进行清理,该函数对某些HTML标记字符(“ <>')进行编码。此外,此功能还采取了其它安全措施。

/include/functions_io.php

72 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参数检索的用户输入。通常使用这种包装器函数来解决开发人员清除值的烦恼。包装器函数绝对是有用的,但有一些缺陷需要注意:

1.  此功能的使用是可选的。仍然可以直接访问未清除的$ _GET或$_POST变量。直接访问在Pandora FMS代码库中发生过几次,这在过去已导致过安全问题。

2.  包装程序检索到的已净化数据仍然可能导致安全问题,因为必须根据标记上下文来净化输入。例如,如果将用户输入嵌入到各种JavaScript代码部分中,则htmlspecialchars()函数无法防范跨站点脚本攻击。开发人员可能盲目地相信包装器功能的安全性,却不知道其实际作用。

3.  除了GET和POST参数外,还有很多参数可以处理用户的输入,例如cookie或HTTP标头,但所有用户的输入都应该被清除。


未经身份验证的SQL注入

让我们看一下如何在Pandora FMS的图表生成器中处理用户输入。访问图表生成器时,首先将检查身份验证。

/include/chart_generator.php

71  // Try toinitialize session using existing php session id.

72  $user = new PandoraFMSUser(['phpsessionid'=> $_REQUEST['session_id']]);

73  if(check_login(false) === false) {  

74     // Errorhandler.

 

96  }

97

98  // Accessgranted.

正如我们在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          );

75

76         if($info !== false) {

77            // Process.

78            $session_data= session_decode($info['data']);

79           $this->idUser = $_SESSION['id_usuario'];

80

81            //Valid session.

82           return $this;

83         }

在第73行中,用户控制的参数传递给函数db_get_row_filter()。此函数使用了几个内部函数,这些函数根据提供的表名和作为数组提供的条件动态构建SQL查询。此时,它将攻击者控制的变量直接连接到SQL WHERE子句中,而没有进行适当的清理,导致SQL注入(mysql.php中的762 行)。

 

/include/lib/mysql.php

848  functiondb_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  functiondb_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     }

772

773     return(!empty($query) ? $prefix : '') . $query;

 

通过SQL注入,攻击者可以使构造的SQL格式错误,从而使数据库查询的结果集格式错误。从这里,攻击者可以控制User.php的 71行中$ info ['data']中的数据。然后使用PHP函数session_decode()从$ info ['data']加载会话数据,并将其填充到当前的$ _SESSION行中的第78行中。通过这种方式,可以模拟任何用户,包括模拟具有完全访问权限的管理员加载其用户ID。SQL注入可用于以任何用户身份进行身份验证。

 

需要注意的是,函数session_decode()可以反序列化任意对象,类似于函数unserialize()。这意味着攻击者可以通过SQL注入反序列化任意对象,并且将这作为一个攻击媒介。

 

补丁

目前,Pandora FMS供应商已使用以前引入的包装函数io_safe_input()清理输入,在Pandora FMS 743修复了该漏洞。

/include/lib/User.php

71          $info =db_get_row_filter(

72             'tsessions_php',

73              ['id_session'=> io_safe_input($data['phpsessionid'])]

74          );

通过查看第73行中的补丁,我们不知道db_get_row_filter()内部的SQL查询的确切上下文,以及io_safe_input()是否足够有效。如果db_get_row_filter()在内部创建SQL查询并嵌入用户提供的数据而又不将其用引号(')引起来,则为HTML标记设计的输入清理操作将是不够的,因为攻击者的有效负载将不需要任何引号进行利用。将上下文相关的输入清理(转义VS.类型转换),或者是将准备好的语句添加到数据库包装器函数本身中,将能够独立于用户提供的过滤器而更安全地使用这些函数。

 

参考链接

https://blog.sonarsource.com/pandora-fms-742-critical-code-vulnerabilities-explained

https://portswigger.net/daily-swig/multiple-vulnerabilities-in-pandora-fms-could-trigger-remote-execution-attack

https://pandorafms.com/blog/whats-new-in-pandora-fms-743/

https://sourceforge.net/p/pandora/activity/page=3&limit=100#5e409944e8ba7c0d58897e78

 

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: