绕过PHP图片上传转换实现远程代码执行(RCE)危险

 更新时间:2016年11月25日 15:21  点击:2186
无意之中发现特殊的图片上传可以绕过php gd库对图片处理,然后实现php执行,太危险了,下面来看看我是怎么实现的,然后你如何也存在这样的情况,赶快把漏洞补起吧。

我使用了一个特殊的图片上传技巧,绕过PHP GD库对图片的转换处理,最终成功实现了远程代码执行。

事情是这样的。当时我正在测试该网站上是否存在sql注入漏洞,不经意间我在网站个人页面发现了一个用于上传头像的文件上传表单。开始时我并没指望在上传功能处发现漏洞,但我决定试试。

我上传了一个图片文件,通过截断http数据包,修改jpg图片的文件名后缀为php,然后继续上传。我惊讶的居然上传成功了,我几乎不敢相信这么简单的漏洞居然存在。于是我复制了图片url并且在浏览器上打开。进入我眼帘的是图片的二进制代码,这意味着图片以php解析了,并根据响应包里的 content-type以text/html格式返回。

我现在要做的是在jpg文件中注入php代码以进行远程代码执行,于是我尝试将代码写入图片的EXIF头里,但是悲剧的是再次上传发现php代码没有被执行。

在本机进行了测试,结果仍然无效——代码没有被执行

绕过PHP图片上传转换实现远程代码执行(RCE)危险

在上传到服务器后,EXIF里的代码都被删除了,应用通过imagecreatefromjpeg()函数调用了PHP GD库(GD库,是php处理图形的扩展库),对图片进行了转换。那么如果不将代码注入EXIF头而是注入到图片里呢?

绕过PHP图片上传转换实现远程代码执行(RCE)危险

本机测试通过,但当我上传“1.jpg”到服务器上,返回以下结果:

绕过PHP图片上传转换实现远程代码执行(RCE)危险

报错上写着“文件必须是合法的图片(.gif, .jpg, .jpeg, 或.png)”,我惊叹于应用是怎么判断图片不合法的。我又测试了一些其他jpg文件,结果发现修改任何一个图片字符都会引起php-gd库的错误判断,进而造成上传失败。

接下来我又使用gif图片进行了同样的操作,结果是:图片上传成功了,但是图片中的php代码完全被删除了。

虽然这看起来不可思议,但是我不能放弃,因为现在距离成功利用远程代码执行(RCE)只有一步之遥,我必须绕过imagecreatefromgif()函数。我对图片的处理和php GD库的运行知之甚少,可是这不影响我使用一些传统渗透测试方法。

我想到一个方法:对比两张经过php-gd库转换过的gif图片,如果其中存在相同之处,这就证明这部分图片数据不会经过转换。然后我可以注入代码到这部分图片文件中,最终实现远程代码执行。连我自己都佩服我的机智!

绕过PHP图片上传转换实现远程代码执行(RCE)危险

如图,我用十六进制编辑器打开图片文件,找到了php转换前后仍然保持相同的十六进制串“3b45d00ceade0c1a3f0e18aff1”并修改它为。

绕过PHP图片上传转换实现远程代码执行(RCE)危险

保存图片,上传到服务器:

绕过PHP图片上传转换实现远程代码执行(RCE)危险

我的PHP代码被执行了,我最终成功实现了远程代码执行。

CMS为了文章编辑内容,都会在后台集成在线编辑器,如FCKEditor等,但是这种很容易XSS跨站攻击,以下我们来看一下使用 HTML Purifier 如何防止xss跨站攻击

随着html可视即可得编辑器的流行,很多网站使用了这样的编辑器,比如FCKEditor、百度UEditor编辑器等等。

跨站脚本攻击(XSS)已经不是什么新鲜的话题了,甚至很多大公司也为此吃尽苦头。最简单直接的防范方法,就是不允许任何html标签输入,对用户输入进行编码(htmlencode)。

但是如果想用户输入支持一些格式,怎么办?一种办法就是很多论坛采用的BB Code的方法。使用特定的标签代替一些格式。比如:[ B ]表示粗体,等等。但是,BB Code这种形式并不被广泛接受,它的表现力实在太差了,而且并不是标准格式。

为了让用户的输入更具表现力,涌现了大量的Html编辑器控件,著名的有FCKEditor,FreeTextBox,Rich TextBox,Cute Editor,TinyMCE等等。我个人比较喜欢Cute Editor,功能强大,性能不错,而且容易定制。

使用这些Html编辑器控件的潜在危险,是用户可能会输入一些危险字符,注入到网站中,形成XSS攻击。一个最简单的输入就是:

<script>alert('xss')</script>

XSS 输入攻击也可能是 HTML 代码段,譬如:

(1).网页不停地刷新 <meta http-equiv="refresh" content="0;">
(2).嵌入其它网站的链接 <iframe src=http://xxxx width=250 height=250></iframe>

对于PHP开发者来说,如何去防范XSS攻击呢?(php防止xss攻击的函数),这里飘易推荐HTML Purifier工具。

HTML Purifier官网:http://htmlpurifier.org/

HTML Purifier是基于php 5所编写的HTML过滤器,支持自定义过滤规则,还可以把不标准的HTML转换为标准的HTML,是WYSIWYG编辑器的福音。
HTML Purifier,这是一个符合W3C标准的HTML过滤器,可以生成标准的HTML代码,并且有很多的自定义配置,可以过滤掉javascript代码等,有效的防止XSS!

一、使用HTML Purifier的要求

HTML Purifier 只需要PHP 5.0.5以及以上版本,并且不需要其他核心组件的支持。HTML Purifier 不兼容  zend.ze1_compatibility_mode。

以下5个是可选扩展,可以增强HTML Purifier的性能(can enhance the capabilities of HTML Purifier):

    * iconv  : Converts text to and from non-UTF-8 encodings
    * bcmath : Used for unit conversion and imagecrash protection
    * tidy   : Used for pretty-printing HTML
    * CSSTidy : Clean CSS stylesheets using %Core.ExtractStyleBlocks
    * Net_IDNA2 (PEAR) : IRI support using %Core.EnableIDNA

使用前请阅读HTML Purifier详细安装说明:http://htmlpurifier.org/live/INSTALL

二、基本用法

默认下,使用UTF-8编码,和XHTML 1.0 Transitional文档类型.
require_once('HTMLPurifier/library/HTMLPurifier.auto.php');
$config = HTMLPurifier_Config::createDefault();
$purifier = new HTMLPurifier($config);
 
$dirty_html = <<<EOF 
<h1>Hello 
<script>alert("world");</script> 
EOF; 

$cleanHtml = $purifier->purify($dirty_html); 

输出:

<h1>Hello 
</h1> 

过滤了XSS代码,过滤规则:http://htmlpurifier.org/live/smoketests/xssAttacks.php

自动填充了残缺的标签

三、使用配置

配置主要用于设置规则,使用比较简单

$config = HTMLPurifier_Config::createDefault(); 
// something.... 
$purifier = new HTMLPurifier($config); 

详细的配置规则:http://htmlpurifier.org/live/configdoc/plain.html

Sqlmap是一个开源的SQL注入漏洞检测工具,本文我们来学习一下Sqlmap联合Nginx服务器对网站进行“地毯式”检测网站SQL注入漏洞。

以安全防御方的角度来看,防御的广度比深度更具优先级,这也是信息安全中木桶原理的体现。

Sqlmap是一个开源的SQL注入漏洞检测工具,Nginx是高性能的WEB服务器。今天我们将二者结合起来,对网站的SQL注入漏洞实现“地毯式”的检测!

思路

sqlmap可以批量导入http代理的日志,根据日志中的每一个请求进行分析和探测。(可参考sqlmap帮助文档)

所以,我们可以配置nginx记录下网站所有的http请求信息,格式化处理后提供给sqlmap,这样sqlmap就能根据网站的每一个请求进行检测,从而实现最全面的检测效果。

操作步骤

实验环境:centos 6.5 + nginx + sqlmap

1. 配置nginx,记录请求信息

nginx无法记录完整的请求信息(反正我没找到),只能指定相应的字段进行记录,不过够了,关键信息基本都有了。

这里有个细节可以注意下,sqlmap接受的log日志是有一定格式的,所以要拼凑出这个格式。

修改nginx配置文件中的log_format的内容如下:

log_format main '=====================================================
 
 
=====================================================
$request
Cookie: $http_cookie
User-Agent: $http_user_agent
Content-Type: $content_type
Content-Length: $content_length
Host: $host
 
$request_body
=====================================================
 
 
';   #到这结束,注意上面的空行

记录的字段分别为:请求行、cookie、agent、content-type、content-length、host、post参数。

这样记录下来post请求参数也能检测了;实际上如果是get请求的话只记录请求行就行了。

配置好后记得重启nginx。

现在日志应该是这个样子了:

Sqlmap+Nginx“地毯式”检测网站SQL注入漏洞教程

2.格式化日志

在linux下换行符是LF,而HTTP协议中要求的换行符为CRLF,所以要替换换行符为CRLF;

方法1

终端执行

perl -p -i -e 's/n/rn/' access.log

方法2

使用vi编辑器编辑access.log 在命令模式下输入:set ff=dos 然后保存退出

3.根据日志,执行检测

终端执行:

sqlmap.py -l access.log --batch -smart

可以看到针对日志中的请求记录进行检测了:

 

Sqlmap+Nginx“地毯式”检测网站SQL注入漏洞教程

 

总结

这个方案的优势在于:可以利用网站的普通访问来帮助我们对网站来进行注入检测。

.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文件,否则也不能包含了。 再比如,你只是想隐藏个后门,这个方式是最方便的。

本文我们来讲讲另外一种网站注入攻击方式,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 服务状态,了解哪些修改和未修改的文件并确保漏洞未被利用。

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

[!--infotagslink--]

相关文章

  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • C#从数据库读取图片并保存的两种方法

    这篇文章主要介绍了C#从数据库读取图片并保存的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下...2021-01-16
  • Python 图片转数组,二进制互转操作

    这篇文章主要介绍了Python 图片转数组,二进制互转操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-09
  • Photoshop古装美女图片转为工笔画效果制作教程

    今天小编在这里就来给各位Photoshop的这一款软件的使用者们来说说把古装美女图片转为细腻的工笔画效果的制作教程,各位想知道方法的使用者们,那么下面就快来跟着小编一...2016-09-14
  • php抓取网站图片并保存的实现方法

    php如何实现抓取网页图片,相较于手动的粘贴复制,使用小程序要方便快捷多了,喜欢编程的人总会喜欢制作一些简单有用的小软件,最近就参考了网上一个php抓取图片代码,封装了一个php远程抓取图片的类,测试了一下,效果还不错分享...2015-10-30
  • jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮

    jquery左右滚动焦点图banner图片鼠标经过显示上下页按钮...2013-10-13
  • Photoshop枪战电影海报图片制作教程

    Photoshop的这一款软件小编相信很多的人都已经是使用过了吧,那么今天小编在这里就给大家带来了用Photoshop软件制作枪战电影海报的教程,想知道制作步骤的玩家们,那么下面...2016-09-14
  • python opencv通过4坐标剪裁图片

    图片剪裁是常用的方法,那么如何通过4坐标剪裁图片,本文就详细的来介绍一下,感兴趣的小伙伴们可以参考一下...2021-06-04
  • 使用PHP下载CSS文件中的图片的代码

    共享一段使用PHP下载CSS文件中的图片的代码 复制代码 代码如下: <?php //note 设置PHP超时时间 set_time_limit(0); //note 取得样式文件内容 $styleFileContent = file_get_contents('images/style.css'); //not...2013-10-04
  • 利用JS实现点击按钮后图片自动切换的简单方法

    下面小编就为大家带来一篇利用JS实现点击按钮后图片自动切换的简单方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2016-10-25
  • PHP swfupload图片上传的实例代码

    PHP代码如下:复制代码 代码如下:if (isset($_FILES["Filedata"]) || !is_uploaded_file($_FILES["Filedata"]["tmp_name"]) || $_FILES["Filedata"]["error"] != 0) { $upload_file = $_FILES['Filedata']; $fil...2013-10-04
  • C#中图片旋转和翻转(RotateFlipType)用法分析

    这篇文章主要介绍了C#中图片旋转和翻转(RotateFlipType)用法,实例分析了C#图片旋转及翻转Image.RotateFlip方法属性的常用设置技巧,需要的朋友可以参考下...2020-06-25
  • OpenCV如何去除图片中的阴影的实现

    这篇文章主要介绍了OpenCV如何去除图片中的阴影的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-29
  • ps怎么制作图片阴影效果

    ps软件是现在很多人比较喜欢的,有着非常不错的使用效果,这次文章就给大家介绍下ps怎么制作图片阴影效果,还不知道制作方法的赶紧来看看。 ps图片阴影效果怎么做方法/...2017-07-06
  • C#将图片和字节流互相转换并显示到页面上

    本文主要介绍用C#实现图片转换成字节流,字节流转换成图片,并根据图片路径返回图片的字节流,有需要的朋友可以参考下...2020-06-25
  • 微信小程序如何获取图片宽度与高度

    这篇文章主要给大家介绍了关于微信小程序如何获取图片宽度与高度的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-10
  • 百度编辑器ueditor修改图片上传默认路径

    本案例非通用,仅作笔记以备用 修改后的结果是 百度编辑器里上传的图片路径为/d/file/upload1...2014-07-03
  • JavaScript 如何禁止用户保存图片

    这篇文章主要介绍了JavaScript 如何禁止用户保存图片,帮助大家完成需求,更好的理解和使用JavaScript,感兴趣的朋友可以了解下...2020-11-19
  • js实现上传图片及时预览

    这篇文章主要为大家详细介绍了js实现上传图片及时预览的相关资料,具有一定的参考价值,感兴趣的朋友可以参考一下...2016-05-09
  • php上传图片学习笔记与心得

    我们在php中上传文件就必须使用#_FILE变量了,这个自动全局变量 $_FILES 从 PHP 4.1.0 版本开始被支持。在这之前,从 4.0.0 版本开始,PHP 支持 $HTTP_POST_FILES 数组。这...2016-11-25