博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
上传伪技术~很多人都以为判断了后缀,判断了ContentType,判断了头文件就真的安全了。是吗?...
阅读量:7121 次
发布时间:2019-06-28

本文共 7471 字,大约阅读时间需要 24 分钟。

今天群里有人聊图片上传,简单说下自己的经验(大牛勿喷)

0.如果你的方法里面是有指定路径的,记得一定要过滤../,比如你把 aa文件夹设置了权限,一些类似于exe,asp,php之类的文件不能执行,那么如果我在传路径的时候,前面加了一个../呢,这样这种服务器端的限制就跳过了。(DJ音乐站基本上都有这个问题,以及用某编辑器的同志)

1.常用方法:这种就是根据后缀判断是否是图片文件,需要注意的是这种格式:文件:1.asp;.jpg  1.asp%01.jpg  目录: 1.jpg/1.asp 1.jpg/1.php 等等,IIS和Nginx部分版本是有解析漏洞的(不要用文件原有名称,eg:1.asp.jpg=》去后缀后的名字就是1.asp)

///         /// 图片上传        ///         ///         /// 
public JsonResult UploadA(HttpPostedFileBase file) { if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); } if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); } string filterStr = ".gif,.jpg,.jpeg,.bmp,.png"; string fileExt = Path.GetExtension(file.FileName).ToLower(); if (!filterStr.Contains(fileExt)) { return Json(new { status = false, msg = "图片格式不对" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd")); string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), fileExt); string sqlPath = string.Format("{0}/{1}", path, fileName); string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } try { //todo:缩略图 file.SaveAs(Path.Combine(dirPath, fileName)); //todo: 未来写存数据库的Code } catch { return Json(new { status = false, msg = "图片保存失败" }); } return Json(new { status = true, msg = sqlPath }); }

2.Context-Type的方法(很多人说这个安全性比上一个高。。。。。呃,也许吧,上面至少还有个文件后缀硬性判断,contentType这玩意抓个包,本地代理一开,直接就可以串改,传的是1.asp,你收的contextType依旧是图片格式,最后保存就玩完了)

///         /// 图片上传        ///         ///         /// 
public JsonResult UploadB(HttpPostedFileBase file) { if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); } if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); } //判断文件格式(MimeMapping) var contentType = file.ContentType; if (contentType == null) { return Json(new { status = false, msg = "图片提交失败" }); } contentType = contentType.ToLower(); var extList = new Dictionary
() { { "image/gif", ".gif" }, { "image/jpeg", ".jpg" }, { "image/bmp", ".bmp" }, { "image/png", ".png" } }; if (!extList.ContainsKey(contentType)) { return Json(new { status = false, msg = "图片格式不对" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd")); string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), extList[contentType]); string sqlPath = string.Format("{0}/{1}", path, fileName); string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } try { //todo:缩略图 file.SaveAs(Path.Combine(dirPath, fileName)); //todo: 未来写存数据库的Code } catch { return Json(new { status = false, msg = "图片保存失败" }); } return Json(new { status = true, msg = sqlPath }); }

如果非要用这个,建议和第一个一起用

3.头文件判断,很多人都以为这是最终方案。。。。。。呃,也许吧。。。

先贴代码:

    /*头文件参考:(我自己测是如有偏差请联系我)

        7790:exe,dll

 

        5666:psd

        6677:bmp

        7173:gif

        13780:png

        255216:jpg,jpeg

        

        239187:js

        6787:swf

        7368:mp3

        4838:wma

 

        6063:xml

 

        8297:rar

        55122:7z

        8075:docx,xlsx,pptx,vsdx,mmap,xmind,“zip”

        208207:doc,xls,ppt,mpp,vsd

   */

 

///     /// 判断扩展名是否是指定类型---默认是判断图片格式,符合返回true(没有释放stream,请手动:file.InputStream.Dispose();)    /// eg:图片+压缩+文档:"7173", "255216", "6677", "13780", "8297", "55122", "8075", "208207"    /// eg:img,"7173", "255216", "6677", "13780" //gif  //jpg  //bmp //png    /// eg:file,"8297", "55122", "8075", "208207" //rar //7z //zip + 文档系列    ///     /// 文件流    /// 文件扩展名    /// 
public static bool CheckingExt(this Stream stream, params string[] fileTypes) { if (fileTypes == null || fileTypes.Length == 0) { fileTypes = new string[] { "7173", "255216", "6677", "13780" }; } bool result = false; string fileclass = ""; #region 读取头两个字节 var reader = new BinaryReader(stream); byte[] buff = new byte[2]; try { reader.Read(buff, 0, 2);//读取每个文件的头两个字节 fileclass = buff[0].ToString() + buff[1].ToString(); } catch (System.Exception ex) { stream.Dispose(); reader.Dispose(); return false; } #endregion #region 校验 for (int i = 0; i < fileTypes.Length; i++) { if (fileclass == fileTypes[i]) { result = true; break; } } #endregion return result; }

 

///         /// 图片上传(理论上需要二次渲染下图片,微软Save的时候有应该有一定的验证[我把含有一句话木马的图片上传,最后会返回一张空图片])        ///         /// 
public JsonResult UploadC(HttpPostedFileBase file) { if (file == null) { return Json(new { status = false, msg = "图片提交失败" }); } if (file.ContentLength > 10485760) { return Json(new { status = false, msg = "文件10M以内" }); } string filterStr = ".gif,.jpg,.jpeg,.bmp,.png"; string fileExt = Path.GetExtension(file.FileName).ToLower(); if (!filterStr.Contains(fileExt)) { return Json(new { status = false, msg = "图片格式不对" }); } //防止黑客恶意绕过,头文件判断文件后缀 if (!file.InputStream.CheckingExt()) { //todo:一次危险记录 return Json(new { status = false, msg = "图片格式不对" }); } //todo: md5判断一下文件是否已经上传过,如果已经上传直接返回 return Json(new { status = true, msg = sqlPath }); string path = string.Format("{0}/{1}", "/lotFiles", DateTime.Now.ToString("yyyy-MM-dd")); string fileName = string.Format("{0}{1}", Guid.NewGuid().ToString("N"), fileExt); string sqlPath = string.Format("{0}/{1}", path, fileName); string dirPath = Request.MapPath(path); if (!Directory.Exists(dirPath)) { Directory.CreateDirectory(dirPath); } try { //todo:缩略图 + 水印 file.SaveAs(Path.Combine(dirPath, fileName)); //todo: 未来写存数据库的Code } catch { return Json(new { status = false, msg = "图片保存失败" }); } return Json(new { status = true, msg = sqlPath }); }

其实这个很好欺骗的,好几种方法,简单说2种:

第1个,用Copy命令

生成了一句话图片木马

第2个,用edjpgcom 打开一张图片就可以直接插入一句话木马了

图片跟之前看起来没什么不同的

WinHex看看~

上传测试

成功上传了

 

有人说把图片另存为其他格式就能消除一句话木马。。。。。呃,好吧,你可以这样理解~看图:

 

渗透的时候一般遇到这种图片上传后再二次渲染的,一般直接放弃,因为内部的一句话已经不存在了

至于二次渲染是什么鬼,可以先自行研究会,先睡了~~~

 

public static bool CheckingExt(this Stream stream, params string[] fileTypes)    {        if (fileTypes == null || fileTypes.Length == 0) { fileTypes = new string[] { "7173", "255216", "6677", "13780" }; }        bool result = false;        string fileclass = "";

        #region 读取头两个字节        var reader = new BinaryReader(stream);        byte[] buff = new byte[2];        try        {            reader.Read(buff, 0, 2);//读取每个文件的头两个字节            fileclass = buff[0].ToString() + buff[1].ToString();        }        catch (System.Exception ex) { stream.Dispose(); reader.Dispose(); return false; }        #endregion
        #region 校验        for (int i = 0; i < fileTypes.Length; i++)        {            if (fileclass == fileTypes[i])            {                result = true;                break;            }        }        #endregion        return result;    }

转载地址:http://jpiel.baihongyu.com/

你可能感兴趣的文章
面试题解:输入一个数A,找到大于A的一个最小数B,且B中不存在连续相等的两个数字...
查看>>
助力春运 重庆机场今晨新增一架飞机入列
查看>>
刘海I关于iPhone X 的适配
查看>>
百度Apollo发布智能驾驶商业化解决方案
查看>>
关闭tomcat报错Cannot allocate memory
查看>>
从源码角度看ContentProvider
查看>>
iOS--React Native浏览器插件
查看>>
一个JSON字符串和文件处理的命令行神器jq,windows和linux都可用
查看>>
Flask源码解析:从第一个版本开始阅读Flask源码
查看>>
JavaScript 工作原理之二-如何在 V8 引擎中书写最优代码的 5 条小技巧(译)
查看>>
SpringBoot Cache 深入
查看>>
Three.js Scene Graph
查看>>
PAT A1045 动态规划
查看>>
保持ssh的连接不断开
查看>>
897-递增顺序查找树
查看>>
wiki迁移方法操作步骤
查看>>
php_screw
查看>>
Go语言之读写锁
查看>>
openstack mitaka 完整安装详细文档(亲测,花了3天时间)
查看>>
for 循环嵌套for循环
查看>>