防止图像上传代码注入 [英] Prevent image upload code injection

查看:100
本文介绍了防止图像上传代码注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个用户填写歌词信息并上传专辑封面的表格。提交的数据将被插入到数据库中,专辑封面将被移至子文件夹。

localhost / project-folder / covers $ b

我已经采取了一些预防措施(转义,预先准备的语句)针对表单输入的SQL注入。最近,我了解到,我还需要对文件(图像)上传采取防范措施,以便用户可以上传恶意图像。



例如,添加HTML,JS或图像元数据中的PHP代码,或将代码直接嵌入图像文件。由于我没有广泛使用PHP,我不知道这是如何造成问题的,特别是在我的情况下。



我正在服务器上进行表单验证 -
$ b

localhost / project-folder / lyrics / add.php

 < form action =../ scripts / lyrics / submit_lyrics.phpid =lyricsFormmethod =postautocomplete =offenctype =multipart / form-data > 

localhost / project-folder / scripts / lyrics / submit_lyrics.php

  $ form_data = new FormData([artist,album,song,year,track_no, lyrics],sssiis); 
$ file_data = new FileUpload(cover,[
max_file_size=> 512 * 1024,
extensions=> [gif,jpg,jpeg ,bng],
mimes=> [image / gif,image / jpeg,image / png],
max_width=> 1024,
max_height=> 1024,
]);
$ cover = new Cover($ mysqli,$ form_data,$ file_data,BASE。covers /);

验证在初始化 FormData FileUpload 。如果存在无效字段或上传的图片无效,用户将被重定向回表单页面(add.php)并附带相应的警告。



其中一种方式为了防止恶意图片上传,我读过的是从上传的图片上创建一个新图片,这就是我在新的Cover()中所做的事情。我还调整了上传的图片的大小,以便这种方法有效。我正在用这个函数调整大小:

  public function new_image($ file_data,$ new_width,$ new_height){
$ img_data = file_get_contents($ file_data-> tmp_name);
$ image_type = $ file_data->类型;
$ img_create = null;
switch($ image_type){
case IMAGETYPE_GIF:
$ img_create =imagecreatefromgif;;
休息;
case IMAGETYPE_JPEG:
$ img_create =imagecreatefromjpeg;
休息;
case IMAGETYPE_PNG:
$ img_create =imagecreatefrompng;
休息;
}
$ uploaded_image_resource = $ img_create($ file_data-> tmp_name);
$ new_image_resource = imagecreatetruecolor($ new_width,$ new_height);
imagecopyresampled($ new_image_resource,$ uploaded_image_resource,0,0,0,$ new_width,$ new_height,$ file_data-> image [width],$ file_data-> image [height]) ;
返回$ new_image_resource;

$ b $ public function write_to_disk(){
if(isset($ this-> image [resource])){
$ destination = $ this - > target_dir。 $ this-> file_name。 .JPG;
imagejpeg($ this-> image [resource],$ destination);
imagedestroy($ this-> image [resource]);






$ p这个调整大小也删除(我认为)任何代码元数据和/或代码嵌入图像(如果有的话),因为我正在创建一个新的干净的图像。



这足够用于文件上传保护吗?我错过了什么?还有什么我需要注意的事情吗?例如,在图像元数据中添加HTML,JS或PHP代码,或者直接嵌入代码进入图像文件。由于我没有广泛使用PHP,我不知道这是如何造成问题的。


原则上它不应该:if您使用正确的媒体类型(例如 image / jpeg )将图像提供给最终用户,它应该仅作为图像进行处理和呈现。



然而,有些工具会忽略该类型信息,并可能将内容视为更危险的类型:


  • 旧浏览器,特别是 IE ,将嗅探文件的内容以猜测它可能是什么类型,并且在文件内容中包含HTML标签使其将其呈现为HTML而不是图像。用户提供的HTML =跨网站脚本。


  • 插件;在历史上,Java会将任何由第三方站点嵌入的资源视为小程序,而另一个站点上的Flash插件可能会使用 loadPolicyFile 来针对该文件重新解释内容为< crossdomain.xml 政策,打开跨网站脚本


  • 今天的事情并没有那么糟糕,因为这些已经以各种方式得到了缓解 - 例如,在松鼠示例中,它被用作text / html,并且仅被重新解释为image / jpeg ,一个不太强大的类型(下滑)。然而,我们并没有真正承诺文件不会被我们当前或未来的工具用作网络平台上的不同类型。


>


这个调整大小还会删除(我认为)因为我正在创建的元数据和/或代码中嵌入的任何代码(如果有的话)一个新的干净的形象。


它肯定会删除元数据;实际上只是 imagecreatefromX 然后 imagejpeg 会这样做,因为PHP图像对象不会保留元数据。



然而,它不一定会改变图像本身的内容。从理论上讲,知道你使用的是什么图像压缩器的攻击者可以构造一张图片,该图片在被该代码压缩后会输出一串攻击者选择的字节,这可能会像上面那样被不安全地误解。

这是否是一种可能的攻击?不,我认为我可以将它与一个简单的无损压缩器(如GIF或PNG)相提并论,但JPEG中更复杂,更难预测的有损压缩可能会使其变得更加棘手并且更加耗时。

我希望图片加载和保存舞会保护您免受绝大多数偶然攻击者的伤害(当然,还有其他一些很好的理由,比如确保图片大小和格式),但它不能很好地保证XSS上传攻击的安全。



如果您需要比这更好,或者您需要允许上传其他任意文件类型你不能对它们进行重新映像压缩,最严重的网站所采取的做法是仅从单独的主机名(*)提供用户上传的内容,以便如果任何种类的XSS攻击成功抵御它,则主站点不会受影响的。
$ b (*:理想情况下,花费更多,甚至是一个单独的域名。无论哪种方式,用户内容的主机名不能是主站点的子域名,否则它可能会从中读取会话cookie并以此方式损害它。)


I have a form which the user fills with lyrics information and uploads an album cover. Submitted data will be inserted into a database and the album cover will be moved to a subfolder.

localhost/project-folder/covers

I've taken some precautions (escaping, prepated statements) against SQL Injection for the form input. Recently, I've learned that I also need to take precautions for file (image) upload, that the user can upload malicious images.

For example, adding HTML, JS or PHP code in image metadata, or embedding code directly into the image file. Since I haven't used PHP extensively, I don't how how this poses a problem, especially in my case.

I'm doing the form validation on the server-side.

localhost/project-folder/lyrics/add.php

<form action="../scripts/lyrics/submit_lyrics.php" id="lyricsForm" method="post" autocomplete="off" enctype="multipart/form-data">

localhost/project-folder/scripts/lyrics/submit_lyrics.php

$form_data  = new FormData(["artist", "album", "song", "year", "track_no", "lyrics"], "sssiis");
$file_data  = new FileUpload("cover", [
    "max_file_size" => 512 * 1024,
    "extensions"    => ["gif", "jpg", "jpeg", "png"],
    "mimes"         => ["image/gif", "image/jpeg", "image/png"],
    "max_width"     => 1024,
    "max_height"    => 1024,
]);
$cover = new Cover($mysqli, $form_data, $file_data, BASE."covers/");

Validation is done at the initialization of FormData and FileUpload. If there is an invalid field or the uploaded image is invalid, user is redirected back to the form page (add.php) with the corresponding warnings.

One of the ways to prevent malicious image upload that I've read was to create a new image from the uploaded one, and that is what I'm doing inside new Cover(). I also resize the uploaded image so this approachs works. I'm doing the resizing with this function:

public function new_image($file_data, $new_width, $new_height) {
    $img_data   = file_get_contents($file_data->tmp_name);
    $image_type = $file_data->type;
    $img_create = null;
    switch ($image_type) {
        case IMAGETYPE_GIF:
            $img_create = "imagecreatefromgif";
            break;
        case IMAGETYPE_JPEG:
            $img_create = "imagecreatefromjpeg";
            break;
        case IMAGETYPE_PNG:
            $img_create = "imagecreatefrompng";
            break;
    }
    $uploaded_image_resource = $img_create($file_data->tmp_name);
    $new_image_resource      = imagecreatetruecolor($new_width, $new_height);
    imagecopyresampled($new_image_resource, $uploaded_image_resource, 0, 0, 0, 0, $new_width, $new_height, $file_data->image["width"], $file_data->image["height"]);
    return $new_image_resource;
}

public function write_to_disk() {
    if (isset($this->image["resource"])) {
        $destination = $this->target_dir . $this->file_name . ".jpg";
        imagejpeg($this->image["resource"], $destination);
        imagedestroy($this->image["resource"]);
    }
}

This resizing also removes (I think) any code in metadata and/or code embedded in the image (if there are any) since I'm creating a new clean image.

Is this enough for file upload protection? Am I missing anything? Are there any other things that I need to be aware of?

解决方案

For example, adding HTML, JS or PHP code in image metadata, or embedding code directly into the image file. Since I haven't used PHP extensively, I don't how how this poses a problem

In principle it shouldn't: if you serve the image back up to the end user with a correct media type such as image/jpeg, it should be treated and rendered as an image only.

However there are tools around which ignore that type information and can treat the content as a more dangerous type:

  • old browsers, particularly IE, would sniff the contents of a file to guess what type it might be, and inclusion of HTML tags in the content of the file caused it to render it as HTML instead of an image. User-supplied HTML = cross-site-scripting.

  • plugins; historically Java would treat any resource embedded by a third-party site as an applet, and a Flash plugin on another site could use loadPolicyFile against the file to reinterpret the contents as a crossdomain.xml policy, opening up cross-site-scripting

  • things aren't as bad today as these have been mitigated in various ways - for example in the squirrel example that's served as text/html and only being re-interpreted as image/jpeg, a less-powerful type (downsniffing). However, we don't really have any strong commitment that files won't we re-used as a different type on the web platform, by current or future tools.

This resizing also removes (I think) any code in metadata and/or code embedded in the image (if there are any) since I'm creating a new clean image.

It will certainly remove metadata; actually just imagecreatefromX then imagejpeg will do that, because the PHP image object doesn't retain metadata.

However it won't necessarily change the content of the image itself. In theory, an attacker who knows what image compressor you are using could construct a picture which, when compressed by that code, output a string of attacker-chosen bytes, which could be misinterpreted unsafely as above.

Is this a likely attack? No. I think I could probably pull it off against a simple lossless compressor like GIF or PNG's, but the more complicated, less-predictable lossy compression in JPEG would likely make it much trickier and more time-consuming.

I expect the image load-and-save dance would protect you from the vast majority of casual attackers (and there are certainly other good reasons to it, like ensuring a certain image size and format), but it's not a hard-and-fast guarantee of safety against XSS upload attacks.

If you need better than that, or you need to allow upload of other arbitrary filetypes where you can't re-image-compress them, the approach most serious sites go for is to serve user-uploaded content only from a separate hostname(*) so that if any kind of XSS attack succeeds against it your main site isn't affected.

(*: ideally, at some further expense, even a separate domain name. Either way the user-content hostname must not be a subdomain of the main site, otherwise it may be able to read session cookies from it and compromise it that way.)

这篇关于防止图像上传代码注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆