首页 > 编程技术 > php

PNG图像元数据中iFrame注入攻击及防护【多图】

发布时间:2016-11-25 15:21

本文我们来讲讲另外一种网站注入攻击方式,PNG图像元数据中iFrame注入攻击,这个也是本人最近接触,以前没有注意过,或许也有很多站长不清楚,现在分享出来。

我们一直在努力保持领先的最新趋势,今天我们发现了一个非常有趣的事,这或者是我们之前没有发现,或者是刚发生的。 我们只能说这是新发现的。

我们都了解的iFrame注入攻击,对吧?

了解一个iFrame注入

今天的iFrame 是非常标准的HTML标记,它是在自己网页中嵌入其他网站内容的简单方式。 被几乎所有的浏览器支持和百万计的网站使用,使用AdSense吗? 那么你的网站中就有一个iFrame。

我知道这东西很好,然而总是福祸相惜。

今天的攻击,特别是当我们谈论路过式下载,首选是利用IFRAME标记。 它简单方便,只需简单的属性修改,攻击者可以稳妥的从另一个站点嵌入代码,并通过客户的浏览器不知不觉的加载。

像这样:

iframe-sample

攻击者通常从其他网站嵌入的恶意文件,通常是一个PHP文件或类似的形式。 当然,这并不是唯一的方法,但是是最普遍的。 从检测和修复的角度来看,这往往很容易修复。

新的iFrame注入法

然而今天,我们发现一个有趣的iFrame注入类型。

它的特殊之处不是在iframe标签中嵌入的内容,而是它分发恶意软件的方式。 你会看到,攻击者将威胁隐藏在PNG文件中。

我几乎可以听到很多你的窃笑,PFF .. 这不是新的…. 但问题是在细节上我的朋友。

如下,iFrame加载了一个有效的文件,没有什么恶意,一个叫jquery.js的JavaScript文件。这一切看上去都很好。你要细细的找:

blog_injection1-494x650

起初,很多人会说我们傻。 这些代码很好,没看见什么问题,对不对? 然后,我们注意到了这个小函数,loadFile()。 函数本身并不奇怪,但事实上,它是装载一个PNG-var strFile = ‘./dron.png。 你会被它惊讶良久,它才是一个真正的黑手。

自然,下一步就是好奇的打开dron.png文件。 会有什么可怕的事情发生吗?

噢,什么都没有,太无聊了,这纯粹是浪费时间。

Sucuri-iframe-png

但是,请等一下,我发现这里有个有趣的小循环。

Sucuri-PNG-Decoding-Loop

嗯,这是确实挺奇怪的,这是一个解码循环。 为什么要一个循环的解码PNG文件呢?

作为一个优秀的研究人员,采取最简单的方式,我可以将它加载到简单的测试页上 并提取图像内容。搞定!

测试页上加载它之后这,我们获得了strData变量:

sucuri-png-iframe-payload

看到它在干嘛了吗?

它做了个iFrame注入,并把它嵌入到PNG的元数据中,像一个新的分配机制。

有两点需要特别注意了,它使用createElement做了一个iFrame标签,然后设置elm.style.position.left 和 elm.style.position.top 属性的值为-1000px,把iframe放到可视区域之外。这些值都是负值,在浏览器中根本看不到。但是你知道谁能看到吗?只有浏览器和Google能看到。这就是下载驱动和搜索引擎感染(SEP)攻击的小伎俩。

最后我们在elm.src元素中发现了真正的威胁。

做的这么独特到底有什么用呢?

它尽力隐藏真正的威胁的水平是独特的。现在的杀毒软件不会解码图像元数据,直到JavaScript文件加载完毕就停止扫描。不会追踪cookie文件,对于攻击者来说,这太好了,使它们很难被发现。

记住一点,尽管我们这里谈论的是PNG文件,这些方法和概念也可以应用到其他类型图像中。重要的一点是:留意你的web 服务状态,了解哪些修改和未修改的文件并确保漏洞未被利用。

通常情况下,一些新的侦查和排障需要一定的时间。 现在我们的 网站恶意软件扫描器能发现它吗 ? 绝对可以!

.user.ini简单的说就是php除默认配置文件php.ini外的另额外的可以放在网站目录下的配置文件,本文我们来看看.user.ini文件的PHP后门及防范。

背景

这个估计很多同学看了不屑,认为是烂大街的东西了:

.htaccess文件构成的PHP后门,那么我来个新的吧:.user.ini。它比.htaccess用的更广,不管是 nginx/apache/IIS,只要是以fastcgi运行的php都可以用这个方法。我的nginx服务器全部是fpm/fastcgi,我的 IIS php5.3以上的全部用的fastcgi/cgi,我win下的apache上也用的fcgi,可谓很广,不像.htaccess有局限性。

.user.ini

那么什么是.user.ini?

这得从php.ini说起了。php.ini是php默认的配置文件,其中包括了很多php的配置,这些配置中,又分为几种:PHP_INI_SYSTEM、PHP_INI_PERDIR、PHP_INI_ALL、PHP_INI_USER。 在此可以查看:http://php.net/manual/zh/ini.list.php 这几种模式有什么区别?看看官方的解释:

enter image description here

其中就提到了,模式为PHP_INI_USER的配置项,可以在ini_set()函数中设置、注册表中设置,再就是.user.ini中设置。 这里就提到了.user.ini,那么这是个什么配置文件?那么官方文档在这里又解释了:

除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。

在 .user.ini 风格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 设置可被识别。

这里就很清楚了,.user.ini实际上就是一个可以由用户“自定义”的php.ini,我们能够自定义的设置是模式为“PHP_INI_PERDIR 、 PHP_INI_USER”的设置。(上面表格中没有提到的PHP_INI_PERDIR也可以在.user.ini中设置)

实际上,除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通过.user.ini来设置的。

而且,和php.ini不同的是,.user.ini是一个能被动态加载的ini文件。也就是说我修改了.user.ini后,不需要重启服务器中间件,只需要等待user_ini.cache_ttl所设置的时间(默认为300秒),即可被重新加载。

然后我们看到php.ini中的配置项,可惜我沮丧地发现,只要稍微敏感的配置项,都是PHP_INI_SYSTEM模式的(甚至是php.ini only的),包括disable_functions、extension_dir、enable_dl等。 不过,我们可以很容易地借助.user.ini文件来构造一个“后门”。

Php配置项中有两个比较有意思的项(下图第一、四个):

enter image description here

auto_append_file、auto_prepend_file,点开看看什么意思:

enter image description here

指定一个文件,自动包含在要执行的文件前,类似于在文件前调用了require()函数。而auto_append_file类似,只是在文件后面包含。 使用方法很简单,直接写在.user.ini中:

12auto_prepend_file=01.gif

01.gif是要包含的文件。

所以,我们可以借助.user.ini轻松让所有php文件都“自动”包含某个文件,而这个文件可以是一个正常php文件,也可以是一个包含一句话的webshell。

测试一下,我分别在IIS6.0+Fastcgi+PHP5.3和nginx+fpm+php5.3上测试。 目录下有.user.ini,和包含webshell的01.gif,和正常php文件echo.php:

enter image description here

enter image description here

访问echo.php即可看到后门:

enter image description here

Nginx下同样:

enter image description here

enter image description here

那么,我们可以猥琐地想一下,在哪些情况下可以用到这个姿势? 比如,某网站限制不允许上传.php文件,你便可以上传一个.user.ini,再上传一个图片马,包含起来进行getshell。不过前提是含有.user.ini的文件夹下需要有正常的php文件,否则也不能包含了。 再比如,你只是想隐藏个后门,这个方式是最方便的。

加密php文件对于一些重要的非开源程序都会这样做了,而加密php程序官方有提供一个Zend工具了,下面我们来给各位介绍Zend加密php文件的操作步骤.

安装破解版的Zend Guard 6.0软件之后,博主Jhonse哥就尝试给php文件加密。


第一步: 打开Zend Guard 6.0软件


20150124142748

 

20150124142757

 

第二步: php文件加密

 

1. 创建Zend Guard Project

 

20150124143014

 

2. 填写项目信息

 

20150124143436

 

3. 添加源文件或者源文件夹

 

20150124143849

 

4. 配置源文件加密属性

 

因为我的windows/Linux服务器的php版本都是5.4的,所以选择版本为5.4加密

 

20150124144015

 

5. 开始加密

 

20150124144247

 

6. 加密成功

 

20150124144448

 

7. 查看php文件加密效果

 

20150124144627

 

20150124144711

 

验证码通常是用来安全保证我们网站注册或登录不被注入的,但为了更安全我们通常会生成一些混合验证码了,下面一起来看看例子.

在我们开发登录模块或者是论坛的灌水模块的时候,为了防止恶意提交,需要用到验证码。验证码就是用来区分人和机器的一种手段,当然这种手段不是万无一失,但总归会起到一些作用。

验证码的实现需要GD库的支持,没有开启GD库的童鞋需开启GD库。

其实验证码的制作和使用非常的简单,仅仅只是需要4个步骤就可以搞定:创建验证码底图,显示验证码内容,增加干扰元素,输出验证码。下面我们来进行步骤拆分:

第一步:创建验证码底图

$image = imagecreatetruecolor(100, 30); // 创建一个宽为 100 高为 30 的底图  该底图的背景色 为黑色  是系统定义的
$bgcolor = imagecolorallocate($image, 255, 255, 255);   // 为上面创建的底图分配 白色的背景颜色
imagefill($image, 0, 0, $bgcolor);  // 填充白色背景色


第二步:显示验证码内容

// 输出验证码内容
for ($i=0; $i < 4; $i++) {
    $fontsize = 6;
    $fontcolor = imagecolorallocate($image, rand(0,120), rand(0,120), rand(0,120));
    $data = 'qwertyuipkjhgfdsazxcvbnm23456789';
    $content = substr($data, rand(0, strlen($data)), 1);

    $x = ($i*100/4) + rand(5,9); 
    $y = rand(5,10);
    imagestring($image, $fontsize, $x, $y, $content, $fontcolor);  //在图像上水平输出一行字符串
}


第三步:增加干扰元素

// 增加干扰点元素
for ($i=0; $i < 300; $i++) {
    $pointcolor = imagecolorallocate($image, rand(50,200), rand(50,200), rand(50,200));
    imagesetpixel($image, rand(0,99), rand(0,29), $pointcolor);
}

// 增加干扰线元素   线 和 点 的颜色一定要控制好  要比验证码数字的颜色浅  避免出现验证码数字看不见的现象
for ($i=0; $i < 4; $i++) {
    $linecolor = imagecolorallocate($image, rand(100,240), rand(100,240), rand(100,240));
    imageline($image, rand(0,99), rand(0,29), rand(0,99), rand(0,29), $linecolor);
}

第四步:输出验证码

// 输出创建的图像   在输出图像之前 必须输出头信息  用来规定输出的图像类型
header("Content-Type: image/png");
imagepng($image);

// 销毁图像
imagedestroy($image);


至此,一个简单的验证码就实现了,关于实现验证码的注意事项已经写在了注释里。

使用验证码的时候,我们一般都需要用session来保存以便验证,在这里就不作详细介绍。

我们只要查看开源的程序几乎都会有下面两段差不多相关的代码,代码的功能就是过滤提交数据中的一些特殊字符了,通常是有post与get了,下面来看看吧.

 

/**
 * 递归方式的对变量中的特殊字符进行转义
 *
 * @access  public
 * @param   mix     $value
 *
 * @return  mix
 */
function addslashes_deep($value)
{
    if (empty($value))
    {
        return $value;
    }
    else
    {
        return is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
    }
}

使用:

/* 对用户传入的变量进行转义操作。*/
if (!get_magic_quotes_gpc())
{
    if (!empty($_GET))
    {
        $_GET  = addslashes_deep($_GET);
    }
    if (!empty($_POST))
    {
        $_POST = addslashes_deep($_POST);
    }
 
    $_COOKIE   = addslashes_deep($_COOKIE);
    $_REQUEST  = addslashes_deep($_REQUEST);
}

标签:[!--infotagslink--]

您可能感兴趣的文章: