【漏洞练习-Day16】WordPress 的 All In One WP Security & Firewall 4.1.4插件 导致XSS漏洞

开始练习【红日团队】的PHP-Audit-Labs 代码审计 Day16
链接:https://github.com/hongriSec/PHP-Audit-Labs
感兴趣的同学可以去练习练习
预备知识:
内容题目均来自 PHP SECURITY CALENDAR 2017
Day 16 - Poem代码如下:

class FTP {
  public $sock;

  public function __construct($host, $port, $user, $pass) {
    $this->sock = fsockopen($host, $port);
    $this->login($user, $pass);
    $this->cleanInput();
    $this->mode($_REQUEST['mode']);
    $this->send($_FILES['file']);
  }

  private function cleanInput() {
    $_GET = array_map('intval', $_GET);
    $_POST = array_map('intval', $_POST);
    $_COOKIE = array_map('intval', $_COOKIE);
  }

  public function login($username, $password) {
    fwrite($this->sock, "USER " . $username . "\n");
    fwrite($this->sock, "PASS " . $password . "\n");
  }

  public function mode($mode) {
    if ($mode == 1 || $mode == 2 || $mode == 3) {
      fputs($this->sock, "MODE $mode\n");
    }
  }

  public function send($data) {
    fputs($this->sock, $data);
  }
}

new FTP('localhost', 21, 'user', 'password');

漏洞解析 :

这道题目包含了两个漏洞,利用这两个漏洞,我们可以往FTP连接资源中注入恶意数据,执行FTP命令
首先看到 第7行代码,可以发现程序使用 cleanInput方法

    $this->cleanInput();

过滤 GET 、 POST 、 COOKIE 数。

  private function cleanInput() {
    $_GET = array_map('intval', $_GET);
    $_POST = array_map('intval', $_POST);
    $_COOKIE = array_map('intval', $_COOKIE);
  }

将他们强制转成整型数据。然而在 第8行处。

    $this->mode($_REQUEST['mode']);

却传入了一个从REQUEST方式获取的 mode变量。我们都知道超全局数组 $_REQUEST中的数据,是 $_GET 、 $_POST 、 $_COOKIE的合集,而且数据是复制过去的,并不是引用。我们先来看一个例子,来验证这一观点:
在这里插入图片描述
可以发现 REQUEST 数据丝毫不受过滤函数的影响。

回到本例题,例题中的程序过滤函数只对 GET 、 POST 、 COOKIE数据进行操作,最后拿来用的却是REQUEST数据,这显然会存在安全隐患。

$_REQUEST :

(PHP 4, PHP 5, PHP 7)

功能:

$_REQUEST — HTTP Request 变量

定义:

默认情况下包含了 $_GET$_POST$_COOKIE的数组。

说明:
  • “Superglobal”也称为自动化的全局变量。这就表示其在脚本的所有作用域中都是可用的。不需要在函数或方法中用 global $variable; 来访问它。

  • 以命令行方式运行时,将不包含argvargc信息;它们将存在于 $_SERVER数组。

  • 由于$_REQUEST中的变量通过 GETPOSTCOOKIE输入机制传递给脚本文件,因此可以被远程用户篡改而并不可信。这个数组的项目及其顺序依赖于 PHP 的 variables_order 指令的配置。
    在这里插入图片描述

第二个漏洞的话,在代码 第24行,这里用了 == 弱比较

=====
==为弱相等,也就是说12=="12"–> true,而且12=="12cdf"–> true,只取字符串中开头的整数部分,但是1e3dgf这样的字符串在比较时,取的是符合科学计数法的部分:1e3,也就是1000.
这里推荐PHP弱类型比较(松散比较)方面的漏洞

至于本次案例的攻击payload,可以使用: ?mode=1%0a%0dDELETE%20test.file,这个即可达到删除FTP服务器文件的效果。

实例分析:

本次实例分析, 我们选取的是WordPressAll In One WP Security & Firewall插件 。
该插件在 4.1.4 - 4.1.9 版本中存在反射型XSS漏洞,漏洞原因和本次案例中的漏洞成因一致,官方也在4.2.0 版本中修复了该漏洞。本次,我们将以4.1.4 版本插件作为案例讲解。

漏洞POC 本站提供安全工具、程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负!

漏洞分析:

将下载下来的插件zip包,通过后台插件管理上传压缩包安装即可。
在这里插入图片描述

本次发生问题的文件在于 admin\wp-security-dashboard-menu.php ,为了方便大家理解,我将问题代码抽取出来,简化如下:
在这里插入图片描述
我们可以很清晰的看到,问题就出在 第25行render_tab3 方法中,这里直接将 REQUEST方式获取的tab变量拼接并输出。而实际上,在第20行已经获取了经过过滤处理的 $tab变量。我们来看一下get_current_tab方法:
在这里插入图片描述
过滤函数的调用链如下图第1行,接着 $tab 变量就会经过wp_check_invalid_utf8 方法的检测。
在这里插入图片描述

漏洞利用:

下面我们来看看攻击 payload (向 http://10.211.55.5/phpcode/day16/wordpress/wp-admin/admin.php?page=aiowpsec&tab=tab3POST数据 tab="><script>alert(1)</script> ):
在这里插入图片描述
可以看到成功引发XSS攻击。我们最后再根据payload对代码的调用过程进行分析。

首先,我们的 payload 会传入 wp-admin/admin.php 文件中,最后进入 第14行do_action('toplevel_page_aiowpsec');代码。
在这里插入图片描述
wp-includes/plugin.php 文件中,程序又调用了 WP_Hook 类的 do_action方法,该方法调用了自身的 apply_filters方法。
在这里插入图片描述
然后apply_filters 方法调用了wp-content\plugins\all-in-one-wp-security-and-firewall\admin\wp-security-admin-init.php文件的 handle_dashboard_menu_rendering方法,并实例化了一个 AIOWPSecurity_Dashboard_Menu 对象。
在这里插入图片描述
接下来就是开头文章分析的部分,也就是下面这张图片:

在这里插入图片描述
整个漏洞的攻击链就如下图所示:
在这里插入图片描述
这里还有一个小知识点要提醒大家的是,案例中 $_REQUEST["tab"]最后取到的是 $_POST["tab"]的值,而不是 $_GET["tab"] 变量的值。这其实和 php.ini中的 request_order对应的值有关。例如在我的环境中, request_order配置如下:
在这里插入图片描述
这里的 "GP"表示的是 GETPOST ,且顺序从左往右。例如我们同时以GETPOST方式传输 tab变量,那么最终用 $_REQUEST['tab'] 获取到的就是 $_POST['tab']的值。

修复建议:

对于这个漏洞的修复方案,我们只要使用过滤后的 $tab变量即可,且变量最好经过HTML实体编码后再输出,例如使用htmlentities函数等。

结语

再次感谢【红日团队】

发布了35 篇原创文章 · 获赞 19 · 访问量 5180

猜你喜欢

转载自blog.csdn.net/zhangpen130/article/details/104096610
今日推荐