文件上传漏洞防御——图片写马的剔除
最近回顾了一下CasperKid大牛在2011年11月发布的Upload Attack Framework,非常有感触,写得非常好,想深入了解这个漏洞的都推荐看看。 上传功能常见于图片的上传,例如博客头像设置,广告位图片上传等。 上传检测方法在paper中也写的比较明朗,这里总结一下: 1. 客户端使用JS对上传图片做检测,例如文件大小,文件扩展名,文件类型 2. 服务端检测,例如文件大小(免得拒绝服务),文件路径(避免0x00截断,目录遍历),文件扩展名(避免服务器以非图片的文件格式解析文件),文件类型(避免修改Content-Type为image/jpeg等),文件内容(避免图片写马) 上传检测绕过的方法,也总结一下: 1.客户端检测,相当于没有检测,可以使用HTTP代理例如burp绕过 2.服务端检测,一般采用白名单+黑名单的方式,但也极有可能出纰漏。例如大小写,不在名单内的特例,操作系统bt特性(windows系统会自动去掉文件名最后面的点和空格),0x00截断,服务器文件解析漏洞,最后还有图片写马绕过类型检测 本篇博客重点讲讲图片写马的检测。 我们知道PHP中文件类型的检测可以使用 1.$_FILES['uploaded']['type']; 2.getimagesize 两种方式来判断是否是正常图片,其实只要在不破坏图片文件格式的情况下,就可以绕过检测 例如使用以下命令,将正常图片与一句话php木马绑定在一起生成一个新的文件的方式 copy /b tangwei.jpg+yijuhua.php tangweiyijuhua.jpg 我们查看新生图片的内容,在图片底端可以看到一句话木马写入,如下图所示 strings tangweiyijuhua.jpg ![]() 接下来我们演示这张图片是否能正常上传。 试验用到了两个脚本 1.upload.html 上传客户端 Choose an image to upload 2. upload.php 上传文件处理 这个脚本会检测文件后缀与文件类型,符合白名单jpeg格式的才允许上传,并打印出上传文件的基本信息及显示图片。 注意:红色字体部分可以先注释掉,下一步演示中会使用到 if (isset($_POST['upload'])){ // 获得上传文件的基本信息,文件名,类型,大小,临时文件路径 $filename = $_FILES['uploaded']['name']; $filetype = $_FILES['uploaded']['type']; $filesize = $_FILES['uploaded']['size']; print " File name : $filename "; print " File type : $filetype "; print " File size : $filesize "; $tmpname = $_FILES['uploaded']['tmp_name']; print " Temp File path : $tmpname "; $uploaddir='/var/www/upload/'; $target_path=$uploaddir.basename($filename); // 获得上传文件的扩展名 $fileext= substr(strrchr($filename,"."),1); print " File extension : $fileext "; $serverip = $_SERVER['SERVER_ADDR']; //判断文件后缀与类型,合法才进行上传操作 if(($fileext == "jpg") && ($filetype=="image/jpeg")){ if(move_uploaded_file($tmpname,$target_path)){ print $target_path." successfully uploaded ! "; //显示上传的图片 print 'Origin image '; //使用上传的图片生成新的图片 $im = imagecreatefromjpeg($target_path); //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; print " new file name $newfilename "; $newimagepath = $uploaddir.$newfilename; imagejpeg($im,$newimagepath); //显示二次渲染后的图片(使用用户上传图片生成的新图片) print 'New image '; }else{ print " Your image was not uploaded. "; } }else{ print " Your image was not uploaded. "; } }else{ print " Your image was not uploaded. "; } ?> 进行上传操作,我们会发现写马后的图片也能正常生成预览,如下图所示 ![]() 带有一句话木马的图片,如果配合文件解析攻击(将图片当成PHP或HTML等非图片格式来解析),就能起到webshell的作用。 所以,我们需要剔除掉图片中恶意代码部分内容, paper中说可以采取二次渲染,刚开始有点被这个名词吓到,后来才明白是啥意思,其实就是根据用户上传的图片,生成一个新的图片,然后删除用户上传的原始图片,将新图片存储到数据库中。这个过程,PHP开发会非常眼熟吧,这个不就是论坛头像设置功能中根据用户上传图片生成缩略图需求的代码实现大纲嘛。 接下来,我们试验一下重新生成的图片是否还包含恶意代码 让我们回到upload.php脚本的红色字体部分,代码功能是使用用户上传的图片生成新的图片,重新命名并在前端显示 //使用上传的图片生成新的图片 $im = imagecreatefromjpeg($target_path); //给新图片指定文件名 srand(time()); $newfilename = strval(rand()).".jpg"; print " new file name $newfilename "; $newimagepath = $uploaddir.$newfilename; imagejpeg($im,$newimagepath); //显示二次渲染后的图片(使用用户上传图片生成的新图片) print 'New image '; 关键函数imagecreatefromjpeg ,从jpeg生成新的图片(类似的还有imagecreatefromgif,imagecreatefrompng等),下图就是生成的新图片。 (编辑:云计算网_泰州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |